OpenCores
URL https://opencores.org/ocsvn/ssbcc/ssbcc/trunk

Subversion Repositories ssbcc

[/] [ssbcc/] [trunk/] [core/] [9x8/] [asm] - Diff between revs 2 and 3

Go to most recent revision | Only display areas with differences | Details | Blame | View Log

Rev 2 Rev 3
#!/usr/bin/python2.7
#!/usr/bin/python2.7
################################################################################
################################################################################
#
#
# Copyright 2012, Sinclair R.F., Inc.
# Copyright 2012, Sinclair R.F., Inc.
#
#
# Assembler for SSBCC 9x8 processor
# Assembler for SSBCC 9x8 processor
#
#
################################################################################
################################################################################
# global modules
# global modules
import argparse
import argparse
import re
import re
import sys
import sys
# User defined modules
# User defined modules
import asmDef
import asmDef
################################################################################
################################################################################
#
#
# Surround the program with a try ... except clause
# Surround the program with a try ... except clause
#
#
################################################################################
################################################################################
try:
try:
  ################################################################################
  ################################################################################
  #
  #
  # The main loop:
  # The main loop:
  #
  #
  # - Process the command line arguments.
  # - Process the command line arguments.
  #
  #
  ################################################################################
  ################################################################################
  #
  #
  # Construct the command-line argument list parser
  # Construct the command-line argument list parser
  #
  #
  def validateFile(filename):
  def validateFile(filename):
    try:
    try:
      return file(filename,'r');
      return file(filename,'r');
    except:
    except:
      raise asmDef.AsmException('Error opening "%s"' % filename);
      raise asmDef.AsmException('Error opening "%s"' % filename);
  argListParser = argparse.ArgumentParser(description='SSBCC 9x8 assembler');
  argListParser = argparse.ArgumentParser(description='SSBCC 9x8 assembler');
  argListParser.add_argument('-C', metavar='CONSTANT=value', action='append', help='Constant definition');
  argListParser.add_argument('-C', metavar='CONSTANT=value', action='append', help='Constant definition');
  argListParser.add_argument('-G', metavar='parametername', action='append', help='parameter names');
  argListParser.add_argument('-G', metavar='parametername', action='append', help='parameter names');
  argListParser.add_argument('-I', metavar='PORT=index', action='append', help='Input port names');
  argListParser.add_argument('-I', metavar='PORT=index', action='append', help='Input port names');
  argListParser.add_argument('-L', metavar='librarypath', action='append', help='Library search path');
  argListParser.add_argument('-L', metavar='librarypath', action='append', help='Library search path');
 
  argListParser.add_argument('-M', metavar='macropath', action='append', help='Macro search path');
  argListParser.add_argument('-O', metavar='PORT=index', action='append', help='Output port names');
  argListParser.add_argument('-O', metavar='PORT=index', action='append', help='Output port names');
  argListParser.add_argument('-R', metavar='PORT=index', action='append', help='Strobe-only output port names');
  argListParser.add_argument('-R', metavar='PORT=index', action='append', help='Strobe-only output port names');
  argListParser.add_argument('-S', metavar='MEMORY=length', action='append', help='Memory length');
  argListParser.add_argument('-S', metavar='MEMORY=length', action='append', help='Memory length');
  argListParser.add_argument('-i', action='store_true', help='enable/require interrupt');
  argListParser.add_argument('-i', action='store_true', help='enable/require interrupt');
  argListParser.add_argument('-o', metavar='outfile', type=argparse.FileType('w'), required =True, help='output metafile');
  argListParser.add_argument('-o', metavar='outfile', type=argparse.FileType('w'), required =True, help='output metafile');
  argListParser.add_argument('-s', metavar='STACK_NAME=length', action='append', help='Stack length');
  argListParser.add_argument('-s', metavar='STACK_NAME=length', action='append', help='Stack length');
  argListParser.add_argument('filename', metavar='filename', nargs='+', type=validateFile, help='required list of files');
  argListParser.add_argument('filename', metavar='filename', nargs='+', type=validateFile, help='required list of files');
  argList = argListParser.parse_args();
  argList = argListParser.parse_args();
  # Construct the keyword parser
  # Construct the keyword parser
  from asmDef_9x8 import asmDef_9x8
  from asmDef_9x8 import asmDef_9x8
  ad = asmDef_9x8();
  ad = asmDef_9x8();
  # Record the constants in the program symbol table.
  # Record the constants in the program symbol table.
  if argList.C:
  if argList.C:
    for constant in argList.C:
    for constant in argList.C:
      a=re.findall(r'^(C_\w+)=(\w+)$',constant);
      a=re.findall(r'^(C_\w+)=(\w+)$',constant);
      if not a:
      if not a:
        raise asmDef.AsmException('Malformed -C argument: "%s"' % constant);
        raise asmDef.AsmException('Malformed -C argument: "%s"' % constant);
      a = list(a[0]);
      a = list(a[0]);
      try:
      try:
        a[1] = eval(a[1]);
        a[1] = eval(a[1]);
      except:
      except:
        raise asmDef.AsmException('Cannot evaluate "%s"' % a[1]);
        raise asmDef.AsmException('Cannot evaluate "%s"' % a[1]);
      if ad.IsSymbol(a[0]):
      if ad.IsSymbol(a[0]):
        raise asmDef.AsmException('Command line constant "%s" already defined' % a[0]);
        raise asmDef.AsmException('Command line constant "%s" already defined' % a[0]);
      ad.AddSymbol(a[0], 'constant', body=[a[1]]);
      ad.AddSymbol(a[0], 'constant', body=[a[1]]);
  # Record the input names and values in the appropriate record type
  # Record the input names and values in the appropriate record type
  if argList.G:
  if argList.G:
    for parameter in argList.G:
    for parameter in argList.G:
      a = re.findall(r'^([LG]_\w+)$',parameter);
      a = re.findall(r'^([LG]_\w+)$',parameter);
      if not a:
      if not a:
        raise asmDef.AsmException('Malformed -G argument: "%s"' % parameter);
        raise asmDef.AsmException('Malformed -G argument: "%s"' % parameter);
      if ad.IsSymbol(a[0]):
      if ad.IsSymbol(a[0]):
        raise asmDef.AsmException('Program Bug -- repeated symbol "%s"' % a[0]);
        raise asmDef.AsmException('Program Bug -- repeated symbol "%s"' % a[0]);
      ad.RegisterParameterName(a[0]);
      ad.RegisterParameterName(a[0]);
  if argList.I:
  if argList.I:
    for inport in argList.I:
    for inport in argList.I:
      a=re.findall(r'^(I_\w+)=(0|[1-9]\d*)$',inport);
      a=re.findall(r'^(I_\w+)=(0|[1-9]\d*)$',inport);
      if not a:
      if not a:
        raise asmDef.AsmException('Malformed -I argument: "%s"' % inport);
        raise asmDef.AsmException('Malformed -I argument: "%s"' % inport);
      a = a[0];
      a = a[0];
      if ad.IsSymbol(a[0]):
      if ad.IsSymbol(a[0]):
        raise Exception('Program Bug -- repeated symbol "%s"' % a[0]);
        raise Exception('Program Bug -- repeated symbol "%s"' % a[0]);
      ix = int(a[1]);
      ix = int(a[1]);
      if not (0 <= ix < 256):
      if not (0 <= ix < 256):
        raise asmDef.AsmException('Out-of-range inport index:  "%s"' % inport);
        raise asmDef.AsmException('Out-of-range inport index:  "%s"' % inport);
      ad.RegisterInport(a[0],ix);
      ad.RegisterInport(a[0],ix);
  if argList.O:
  if argList.O:
    for outport in argList.O:
    for outport in argList.O:
      a=re.findall(r'^(O_\w+)=(0|[1-9]\d*)$',outport);
      a=re.findall(r'^(O_\w+)=(0|[1-9]\d*)$',outport);
      if not a:
      if not a:
        raise asmDef.AsmException('Malformed -O argument: "%s"' % outport);
        raise asmDef.AsmException('Malformed -O argument: "%s"' % outport);
      a = a[0];
      a = a[0];
      if ad.IsSymbol(a[0]):
      if ad.IsSymbol(a[0]):
        raise asmDef.AsmException('Program Bug -- repeated symbol "%s"' % a[0]);
        raise asmDef.AsmException('Program Bug -- repeated symbol "%s"' % a[0]);
      ix = int(a[1]);
      ix = int(a[1]);
      if not (0 <= ix < 256):
      if not (0 <= ix < 256):
        raise asmDef.AsmException('Out-of-range outport index:  "%s"' % outport);
        raise asmDef.AsmException('Out-of-range outport index:  "%s"' % outport);
      ad.RegisterOutport(a[0],ix);
      ad.RegisterOutport(a[0],ix);
  if argList.R:
  if argList.R:
    for outstrobe in argList.R:
    for outstrobe in argList.R:
      a=re.findall(r'^(O_\w+)=(0|[1-9]\d*)$',outstrobe);
      a=re.findall(r'^(O_\w+)=(0|[1-9]\d*)$',outstrobe);
      if not a:
      if not a:
        raise asmDef.AsmException('Malformed -R argument: "%s"' % outstrobe);
        raise asmDef.AsmException('Malformed -R argument: "%s"' % outstrobe);
      a = a[0];
      a = a[0];
      if ad.IsSymbol(a[0]):
      if ad.IsSymbol(a[0]):
        raise asmDef.AsmException('Program Bug -- repeated symbol "%s"' % a[0]);
        raise asmDef.AsmException('Program Bug -- repeated symbol "%s"' % a[0]);
      ix = int(a[1]);
      ix = int(a[1]);
      if not (0 <= ix < 256):
      if not (0 <= ix < 256):
        raise asmDef.AsmException('Out-of-range strobe-only outport index:  "%s"' % outstrobe);
        raise asmDef.AsmException('Out-of-range strobe-only outport index:  "%s"' % outstrobe);
      ad.RegisterOutstrobe(a[0],ix);
      ad.RegisterOutstrobe(a[0],ix);
  if argList.S:
  if argList.S:
    for memory in argList.S:
    for memory in argList.S:
      a=re.findall(r'^(\w+)=(0|[1-9]\d*)$',memory);
      a=re.findall(r'^(\w+)=(0|[1-9]\d*)$',memory);
      if not a:
      if not a:
        raise asmDef.AsmException('Malformed -S argument: "%s"' % memory);
        raise asmDef.AsmException('Malformed -S argument: "%s"' % memory);
      a=a[0];
      a=a[0];
      length = int(a[1]);
      length = int(a[1]);
      if not (0 < length <= 256):
      if not (0 < length <= 256):
        raise asmDef.AsmException('Out-of-range memory length:  "%s"' % outport);
        raise asmDef.AsmException('Out-of-range memory length:  "%s"' % outport);
      ad.RegisterMemoryLength(a[0],length);
      ad.RegisterMemoryLength(a[0],length);
  if argList.s:
  if argList.s:
    for stack in argList.s:
    for stack in argList.s:
      a=re.findall(r'^(\w+)=(0|[1-9]\d*)$',stack);
      a=re.findall(r'^(\w+)=(0|[1-9]\d*)$',stack);
      if not a:
      if not a:
        raise asmDef.AsmException('Malformed -s argument: "%s"' % stack);
        raise asmDef.AsmException('Malformed -s argument: "%s"' % stack);
      a = a[0];
      a = a[0];
      ad.RegisterStackLength(a[0],int(a[1]));
      ad.RegisterStackLength(a[0],int(a[1]));
  # Construct the iterator that loops through the code bodies.
  # Construct the iterator that loops through the code bodies.
  fbi = asmDef.FileBodyIterator(argList.filename,ad);
  fbi = asmDef.FileBodyIterator(argList.filename,ad);
 
 
 
  # Add paths for the ".include" directive.
  if argList.L:
  if argList.L:
    for path in argList.L:
    for path in argList.L:
      fbi.AddSearchPath(path);
      fbi.AddSearchPath(path);
 
 
 
  # Add paths for the ".macro" directive.
 
  if argList.M:
 
    for path in argList.M:
 
      ad.AddMacroSearchPath(path);
 
 
  ################################################################################
  ################################################################################
  #
  #
  # Stage 1:  Parse the files.
  # Stage 1:  Parse the files.
  #
  #
  # Read the entire file, doing the following while reading the file:
  # Read the entire file, doing the following while reading the file:
  # - Store the raw content of each line or group of lines for output to the
  # - Store the raw content of each line or group of lines for output to the
  #   assembled memory initialization.
  #   assembled memory initialization.
  #   Note: A group of lines consists the comment lines preceding a directive and
  #   Note: A group of lines consists the comment lines preceding a directive and
  #         the body of the directive.
  #         the body of the directive.
  # - Convert group of lines into an array of the raw tokens.
  # - Convert group of lines into an array of the raw tokens.
  # - Check the integrity of the bodies defined by the list of raw tokens.
  # - Check the integrity of the bodies defined by the list of raw tokens.
  # - For each array of raw tokens, incorporate already-defined symbols and update
  # - For each array of raw tokens, incorporate already-defined symbols and update
  #   the assembler dictionaries.
  #   the assembler dictionaries.
  #   Note: At this point the space required for the function or main program
  #   Note: At this point the space required for the function or main program
  #     is fully computed.
  #     is fully computed.
  #
  #
  ################################################################################
  ################################################################################
  #
  #
  # Loop through the directive bodies in the input files (including ".include"d
  # Loop through the directive bodies in the input files (including ".include"d
  # files).
  # files).
  #
  #
  ifstackStack = list();
  ifstackStack = list();
  ifstack = None;
  ifstack = None;
  for bl in fbi:
  for bl in fbi:
    filename = bl[0];
    filename = bl[0];
    startLine = bl[1];
    startLine = bl[1];
    body = bl[2:];
    body = bl[2:];
    flc_loc = filename + ' at line ' + str(startLine+len(body)-1);
    flc_loc = filename + ' at line ' + str(startLine+len(body)-1);
    # Start-of-file processing.
    # Start-of-file processing.
    if startLine == 0:
    if startLine == 0:
      if ifstack != None:
      if ifstack != None:
        ifstackStack.append(ifstack);
        ifstackStack.append(ifstack);
      ifstack = list();
      ifstack = list();
    # End-of-file processing.
    # End-of-file processing.
    elif startLine == -1:
    elif startLine == -1:
      if len(ifstack) != 0:
      if len(ifstack) != 0:
        raise asmDef.AsmException('%d unmatched .IFDEF/.IFNDEF(s) at the end of %s' % (len(ifstack),filename,));
        raise asmDef.AsmException('%d unmatched .IFDEF/.IFNDEF(s) at the end of %s' % (len(ifstack),filename,));
      if ifstackStack:
      if ifstackStack:
        ifstack = ifstackStack.pop();
        ifstack = ifstackStack.pop();
      else:
      else:
        ifstack = None;
        ifstack = None;
    # Handle conditional compilation directives.
    # Handle conditional compilation directives.
    elif re.match(r'\s*\.ELSE\b',body[-1]):
    elif re.match(r'\s*\.ELSE\b',body[-1]):
      if not re.match(r'\s*\.ELSE\s*(;.*)?$',body[-1]):
      if not re.match(r'\s*\.ELSE\s*(;.*)?$',body[-1]):
        raise asmDef.AsmException('Malformed ".ELSE" in %s' % flc_loc);
        raise asmDef.AsmException('Malformed ".ELSE" in %s' % flc_loc);
      if not ifstack:
      if not ifstack:
        raise asmDef.AsmException('Unmatched ".ELSE" in %s' % flc_loc);
        raise asmDef.AsmException('Unmatched ".ELSE" in %s' % flc_loc);
      ifstack[-1] ^= True;
      ifstack[-1] ^= True;
    elif re.match(r'\s*\.ENDIF\b',body[-1]):
    elif re.match(r'\s*\.ENDIF\b',body[-1]):
      if not re.match(r'\s*\.ENDIF\s*(;.*)?$',body[-1]):
      if not re.match(r'\s*\.ENDIF\s*(;.*)?$',body[-1]):
        raise asmDef.AsmException('Malformed ".ENDIF" in %s' % flc_loc);
        raise asmDef.AsmException('Malformed ".ENDIF" in %s' % flc_loc);
      if not ifstack:
      if not ifstack:
        raise asmDef.AsmException('Unmatched ".ENDIF" in %s' % flc_loc);
        raise asmDef.AsmException('Unmatched ".ENDIF" in %s' % flc_loc);
      ifstack.pop();
      ifstack.pop();
    elif re.match(r'\s*\.IFN?DEF\b',body[-1]):
    elif re.match(r'\s*\.IFN?DEF\b',body[-1]):
      a = re.findall(r'\s*(\.IFN?DEF)\s*(\S+)\b\s*(;.*)?$',body[-1]);
      a = re.findall(r'\s*(\.IFN?DEF)\s*(\S+)\b\s*(;.*)?$',body[-1]);
      if not a:
      if not a:
        raise asmDef.AsmException('Malformed .IFDEF or .IFNDEF in %s' % flc_loc);
        raise asmDef.AsmException('Malformed .IFDEF or .IFNDEF in %s' % flc_loc);
      a = a[0];
      a = a[0];
      ifstack.append(ad.IsSymbol(a[1]));
      ifstack.append(ad.IsSymbol(a[1]));
      if a[0] == '.IFNDEF':
      if a[0] == '.IFNDEF':
        ifstack[-1] ^= True;
        ifstack[-1] ^= True;
    # Ignore bodies rejected by conditional compilation.
    # Ignore bodies rejected by conditional compilation.
    elif ifstack and not ifstack[-1]:
    elif ifstack and not ifstack[-1]:
      pass;
      pass;
    # ".include" directives don't have an associated body
    # ".include" directives don't have an associated body
    elif re.match(r'\s*\.include\s',body[-1]):
    elif re.match(r'\s*\.include\s',body[-1]):
      a = re.findall(r'\s*\.include\s+(\S+)(\s*|\s*;.*)$',body[-1]);
      a = re.findall(r'\s*\.include\s+(\S+)(\s*|\s*;.*)$',body[-1]);
      if not a:
      if not a:
        raise asmDef.AsmException('Malformed .include directive in %s' % flc_loc);
        raise asmDef.AsmException('Malformed .include directive in %s' % flc_loc);
      a = a[0];
      a = a[0];
      fbi.Include(a[0]);
      fbi.Include(a[0]);
    # Parse the body of all other directives and ensure that only one ".main"
    # Parse the body of all other directives and ensure that only one ".main"
    # and one ".interrupt" are defined.
    # and one ".interrupt" are defined.
    else:
    else:
      rawTokens = asmDef.RawTokens(ad,filename,startLine,body);
      rawTokens = asmDef.RawTokens(ad,filename,startLine,body);
      if not rawTokens:
      if not rawTokens:
        continue;
        continue;
      ad.CheckRawTokens(rawTokens);
      ad.CheckRawTokens(rawTokens);
      ad.FillRawTokens(rawTokens);
      ad.FillRawTokens(rawTokens);
  #
  #
  # Ensure a ".main" body was declared.
  # Ensure a ".main" body was declared.
  #
  #
  if not ad.Main():
  if not ad.Main():
    raise asmDef.AsmException('Required ".main" body not provided');
    raise asmDef.AsmException('Required ".main" body not provided');
  #
  #
  # Enforce consistency between the command-line "-i" flag and whether or not an
  # Enforce consistency between the command-line "-i" flag and whether or not an
  # ".interrupt" body was declared.
  # ".interrupt" body was declared.
  #
  #
  if argList.i and not ad.Interrupt():
  if argList.i and not ad.Interrupt():
    raise asmDef.AsmException('Required ".interrupt" body not provided');
    raise asmDef.AsmException('Required ".interrupt" body not provided');
  if not argList.i and ad.Interrupt():
  if not argList.i and ad.Interrupt():
    raise asmDef.AsmException('".interrupt" body not allowed near %s' % ad.Interrupt()[0]['loc']);
    raise asmDef.AsmException('".interrupt" body not allowed near %s' % ad.Interrupt()[0]['loc']);
  ################################################################################
  ################################################################################
  #
  #
  # Stage 2:  Identify the required functions, compute their addresses, and set
  # Stage 2:  Identify the required functions, compute their addresses, and set
  # the addresses for all "jump" and "call" macros.
  # the addresses for all "jump" and "call" macros.
  #
  #
  ################################################################################
  ################################################################################
  ad.EvaluateMemoryTree();
  ad.EvaluateMemoryTree();
  ad.EvaluateFunctionTree();
  ad.EvaluateFunctionTree();
  ################################################################################
  ################################################################################
  #
  #
  # Stage 3:  Emit the program
  # Stage 3:  Emit the program
  #
  #
  # Do the following:
  # Do the following:
  # - If interrupts are enabled, then set the first 4 instructions to be a "dis"
  # - If interrupts are enabled, then set the first 4 instructions to be a "dis"
  #   and a ".jump" instruction to the ".interrupt" function.
  #   and a ".jump" instruction to the ".interrupt" function.
  # - Write the instructions for the ".main" body.
  # - Write the instructions for the ".main" body.
  # - Loop through the ".function" list in the order in which they were defined
  # - Loop through the ".function" list in the order in which they were defined
  #   and write their instructions.
  #   and write their instructions.
  # - Print the memory and instruction usage statistics.
  # - Print the memory and instruction usage statistics.
  #
  #
  ################################################################################
  ################################################################################
  ad.EmitMemories(argList.o);
  ad.EmitMemories(argList.o);
  ad.EmitProgram(argList.o);
  ad.EmitProgram(argList.o);
  argList.o.close();
  argList.o.close();
################################################################################
################################################################################
#
#
# Terminating except clause -- print fatal error message and indicate failure to
# Terminating except clause -- print fatal error message and indicate failure to
# the invoking program.
# the invoking program.
#
#
################################################################################
################################################################################
except asmDef.AsmException, msg:
except asmDef.AsmException, msg:
  print >> sys.stderr, 'FATAL ERROR:  ' + str(msg);
  print >> sys.stderr, 'FATAL ERROR:  ' + str(msg);
  exit(1);
  exit(1);
 
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.