Exemple #1
0
 def __init__(self, machine, sim_data):
     # Machine is the simulation's machine.
     # SimData cannot be empty.
     self.machine  = machine
     if sim_data.strip() == '': die('empty sim data')
     self.data = sim_data.splitlines()
     self.step = e.settings.step
Exemple #2
0
def _jsonInsertExternal(img, pat, data):
    # Looks for the corresponding metaobject and sets the submachine data to it
    if pat in img['objects']:
        img['extobjects'][pat] = {}
        img['extobjects'][pat]['objects'] = img['metaobjects'][pat]
        img['extobjects'][pat]['data'] = data
        del img['metaobjects'][pat]
    else:
        log.error('pattern = %s' % pat)
        die('trying to set sub-machine data to non-metaobject')
Exemple #3
0
    def _checkCycleLine(self, line):
        # Some sanity checks on split line (that time and clk are integers).
        try:    time = int(line[0])
        except: die('first col (time) in sim output not an int decimal')

        try:    clk = int(line[1], 2)
        except: die('second col (clk) in sim output not a binary decimal')

        log.info('emulator pass, time=%s, clk=%s' % (time, clk))
        return time, clk
Exemple #4
0
    def _findDataProgFiles(self, files):
        if files[0].endswith('.d'): data_file = files[0]
        elif files[1].endswith('.d'): data_file = files[1]
        else: die('cannot find data (.d) file')

        if files[0].endswith('.p'): program_file = files[0]
        elif files[1].endswith('.p'): program_file = files[1]
        else: die('cannot find program (.p) file')

        return data_file, program_file
Exemple #5
0
    def __init__(self):
        ap = ArgParser(description='Online Machine Simulation Tool')

        addarg = ap.add_argument
        outf = sys.stdout.fileno()
        errf = sys.stderr.fileno()

        addarg('machine', type=str, metavar='MACHINE',
               help='Machine name M to run')
        addarg('step', type=int, metavar='STEP',
               help='Step number to retrieve')
        addarg('files', metavar='FILES', nargs='+',
               help='Program files to compile and run')
        addarg('-m', '--max-steps', default=500, type=int, metavar='N',
               help='Maximum number of steps [%(default)s]')
        addarg('-x', '--range', default=10, type=int, metavar='N',
               help='Range of steps to cache [%(default)s]')
        addarg('-f', '--format', default='js', type=str, metavar='FMT',
               choices=['js', 'json'],
               help='Output format (%(choices)s) [%(default)s]')
        addarg('-c', '--compress', default=False, type=bool, metavar='C',
               help='Compress output [%(default)s]')
        addarg('-d', '--mach-dir', default='machines/', type=str, metavar='D',
               help='Directory with machine files [%(default)s]')
        addarg('-t', '--text', default=outf, type=int, metavar='FD',
               help='Text output file descriptor [stdout]')
        addarg('-e', '--error', default=errf, type=int, metavar='FD',
               help='Error output file descriptor [stderr]')
        addarg('-w', '--warn', default=errf, type=int, metavar='FD',
               help='Warning output file descriptor [stderr]')
        addarg('-r', '--result', default=7, type=int, metavar='FD',
               help='Result output file descriptor [%(default)s]')
        addarg('-l', '--sim-log', default=devnull, type=str, metavar='F',
               help='Dump simulation log to file [%(default)s]')
        args = ap.parse_args()

        # do some sanity checks
        if args.range > args.max_steps: die('bad range > max_steps')
        if args.step < 0:               die('step should be >= 0')

        self.machineName = args.machine
        self.step        = args.step
        self.machineFile = path.join(args.mach_dir, args.machine, 'main.machine')
        self.text        = fdopen(args.text, 'w')
        self.error       = fdopen(args.error, 'w')
        self.warn        = fdopen(args.warn, 'w')
        self.files       = args.files
        self.simLogFile  = args.sim_log
        self.format      = args.format
        self.maxSteps    = args.max_steps
        self.range       = args.range

        try:            self.result = fdopen(args.result, 'w')
        except OSError: self.result = self.text
Exemple #6
0
def export(machine):
    f = e.settings.format
    out = e.settings.result

    if f.startswith('js'):
        res = json.dumps(jsonExport(machine), indent=2)
        if e.settings.compress == True: res = _compressJSON(res)

        tmpJS = 'var machine = %s;'

        if f == 'js': out.write(tmpJS % res)
        elif f == 'json': out.write(res)
        else: die('unknown format')
Exemple #7
0
    def run(self):
        # This is the main flowchart-like logic to deal with possible
        # cases of missing machine file and/or simulator
        # binary. Described in docs/simulation.dia.
        simcode = self.machine['simcode']
        simulator = self.machine['simulator']

        if not simcode:
            log.info('sim machine is empty, checking simulator')

            if not simulator: die('no simulator nor machine provided')
            else:
                log.info('simulator not empty, checking')

                if simulator == 'veriwell': die('no machine for verilog sim')
                elif simulator == 'vhdl': die('no machine for vhdl sim')
                else: self._runStandaloneSim()
        else:
            log.info('sim machine not empty, checking simulator')

            if not simulator:
                log.info('simulator empty, checking extension')

                if simcode.endswith('.v'):
                    log.info('machine ends in .v, using veriwell')
                    self._runVeriwellSim()
                elif simcode.endswith('.vh'):  # put other simulators here
                    log.info('machine ends in .vh, using vhdl')
                    # run vhdl simulation
                else:
                    die('cannot determine simulator from extension')
            else:
                log.info('simulator not empty, checking')

                if simulator == 'veriwell':
                    log.info('machine not empty, simulator is veriwell')
                    self._runVeriwellSim()
                elif simulator == 'vhdl':  # put other simulators here
                    log.info('machine not empty, simulator is vhdl')
                else:
                    die('unknown simulator given')
Exemple #8
0
    def _checkSplitSimOutput(self):
        # Check sanity of the simulator output and splits it accordingly.
        sInd = '=== start ==='
        eInd = '=== end ==='

        if sInd not in self.data: die('start-ind not found in sim output')
        if eInd not in self.data: die('end-ind not found in sim output')

        if self.data.index(eInd) < self.data.index(sInd):
            die('end-ind found before start-ind in sim output')

        self.data = self.data.split(sInd)[1].split(eInd)[0].strip()
Exemple #9
0
    def advance(self, step=0):
        # Moves through the simulation data, parsing every line. Works
        # according to the emulator state machine:
        # START: Get 0 -> S0
        # S0:    Get 0 -> S0
        # S0:    Get 1 -> S1
        # S1:    Get 1 -> S1
        # S1:    Get 0 -> S0, step++, machine.load_values()
        # END when counter == wanted_steps or premature_finish
        # Returns True for success
        # Returns False for premature finish
        splitLine = lambda row: self.data[row].strip().split(':')

        if len(self.data) == 0: die('empty sim data')
        if step < 0:            die('bad step number %s' % step)

        if step == 0:
            tmpLine = splitLine(0)

            if tmpLine[0] == 'mw': die('step 0 is a memwrite operation')

            self._checkCycleLine(tmpLine)
            _machineLoadMem(self.machine)
            _machineLoadValues(self.machine, tmpLine[2].split(','))
            _machineUnmarkAll(self.machine)
        else:
            i = 0
            row = 0
            state = 0

            _machineLoadMem(self.machine)

            while i < step:
                if row == len(self.data) - 1: return False

                _machineUnmarkAll(self.machine)
                tmpLine = splitLine(row)

                if tmpLine[0] == 'mw':
                    _machineMemWrite(self.machine, tmpLine[1].split(','))
                else:
                    time, clk = self._checkCycleLine(tmpLine)

                    if state == 0 and clk == 1: state = 1
                    elif state == 1 and clk == 0:
                        state = 0; i += 1
                        pLine = splitLine(row-1) # previous line
                        log.info('applying line at time=%s, clk=%s' %
                                 (pLine[0], pLine[1]))
                        _machineLoadValues(self.machine, pLine[2].split(','))
                row += 1
        return True
Exemple #10
0
    def run(self):
        # Runs assembler according to flowchart in docs/assembler.dia
        files = e.settings.files
        assembler = self.machine['assembler']

        if len(files) == 1:
            log.info('single file provided')

            if self.machine['single_mem']:
                log.info('machine is single memory')

                if not assembler:
                    log.info('no assembler, using input directly')
                    tmp = mktempf('_tmp')
                    shutil.copyfile(files[0], tmp)
                    e.settings.program_prog = tmp
                    self.machine['debug_info'] = False
                else:
                    log.info('have assembler, trying to assemble')

                    returncode = self._tryAssembling(files[0], canDie=False)
                    log.info('assembler returned errorcode %s' % returncode)

                    if returncode != 0:
                        log.info('assembler failed, using input directly')
                        tmp = mktempf(suffix='_tmp')
                        shutil.copyfile(files[0], tmp)
                        e.settings.program_prog = tmp
                        self.machine['debug_info'] = False
                    else:
                        log.info('assembler succeeded')
            else:
                log.info('machine is dual memory')

                if not assembler: die('machine does not have an assembler')
                else:
                    log.info('machine has an assembler')
                    self._tryAssembling(files[0])
        elif len(files) == 2:
            log.info('two files provided')

            if self.machine['single_mem']:
                log.info('machine is single mem, merging files (data first)')

                dataFile, progFile = self._findDataProgFiles(files)

                with open(dataFile, 'r') as f:
                    data = f.read()
                with open(progFile, 'r') as f:
                    data += f.read()

                name = mktempf('_name')
                with open(name, 'w') as f:
                    f.write(data)
                e.settings.program_prog = name

                self.machine['debug_info'] = False
            else:
                log.info('machine is dual mem')

                dataFile, progFile = self._findDataProgFiles(files)

                tmp = mktempf('_tmp')
                shutil.copyfile(progFile, tmp)
                e.settings.programProg = tmp

                tmp = mktempf('_tmp')
                shutil.copyfile(dataFile, tmp)
                e.settings.program_data = tmp

                self.machine['debug_info'] = False
        else:
            die('more than 2 files given')