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

Subversion Repositories ssbcc

[/] [ssbcc/] [trunk/] [core/] [9x8/] [asm] - Blame information for rev 2

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 sinclairrf
#!/usr/bin/python2.7
2
 
3
################################################################################
4
#
5
# Copyright 2012, Sinclair R.F., Inc.
6
#
7
# Assembler for SSBCC 9x8 processor
8
#
9
################################################################################
10
 
11
# global modules
12
import argparse
13
import re
14
import sys
15
 
16
# User defined modules
17
import asmDef
18
 
19
################################################################################
20
#
21
# Surround the program with a try ... except clause
22
#
23
################################################################################
24
 
25
try:
26
 
27
  ################################################################################
28
  #
29
  # The main loop:
30
  #
31
  # - Process the command line arguments.
32
  #
33
  ################################################################################
34
 
35
  #
36
  # Construct the command-line argument list parser
37
  #
38
 
39
  def validateFile(filename):
40
    try:
41
      return file(filename,'r');
42
    except:
43
      raise asmDef.AsmException('Error opening "%s"' % filename);
44
 
45
  argListParser = argparse.ArgumentParser(description='SSBCC 9x8 assembler');
46
  argListParser.add_argument('-C', metavar='CONSTANT=value', action='append', help='Constant definition');
47
  argListParser.add_argument('-G', metavar='parametername', action='append', help='parameter names');
48
  argListParser.add_argument('-I', metavar='PORT=index', action='append', help='Input port names');
49
  argListParser.add_argument('-L', metavar='librarypath', action='append', help='Library search path');
50
  argListParser.add_argument('-O', metavar='PORT=index', action='append', help='Output port names');
51
  argListParser.add_argument('-R', metavar='PORT=index', action='append', help='Strobe-only output port names');
52
  argListParser.add_argument('-S', metavar='MEMORY=length', action='append', help='Memory length');
53
  argListParser.add_argument('-i', action='store_true', help='enable/require interrupt');
54
  argListParser.add_argument('-o', metavar='outfile', type=argparse.FileType('w'), required =True, help='output metafile');
55
  argListParser.add_argument('-s', metavar='STACK_NAME=length', action='append', help='Stack length');
56
  argListParser.add_argument('filename', metavar='filename', nargs='+', type=validateFile, help='required list of files');
57
  argList = argListParser.parse_args();
58
 
59
  # Construct the keyword parser
60
  from asmDef_9x8 import asmDef_9x8
61
  ad = asmDef_9x8();
62
 
63
  # Record the constants in the program symbol table.
64
  if argList.C:
65
    for constant in argList.C:
66
      a=re.findall(r'^(C_\w+)=(\w+)$',constant);
67
      if not a:
68
        raise asmDef.AsmException('Malformed -C argument: "%s"' % constant);
69
      a = list(a[0]);
70
      try:
71
        a[1] = eval(a[1]);
72
      except:
73
        raise asmDef.AsmException('Cannot evaluate "%s"' % a[1]);
74
      if ad.IsSymbol(a[0]):
75
        raise asmDef.AsmException('Command line constant "%s" already defined' % a[0]);
76
      ad.AddSymbol(a[0], 'constant', body=[a[1]]);
77
 
78
  # Record the input names and values in the appropriate record type
79
  if argList.G:
80
    for parameter in argList.G:
81
      a = re.findall(r'^([LG]_\w+)$',parameter);
82
      if not a:
83
        raise asmDef.AsmException('Malformed -G argument: "%s"' % parameter);
84
      if ad.IsSymbol(a[0]):
85
        raise asmDef.AsmException('Program Bug -- repeated symbol "%s"' % a[0]);
86
      ad.RegisterParameterName(a[0]);
87
  if argList.I:
88
    for inport in argList.I:
89
      a=re.findall(r'^(I_\w+)=(0|[1-9]\d*)$',inport);
90
      if not a:
91
        raise asmDef.AsmException('Malformed -I argument: "%s"' % inport);
92
      a = a[0];
93
      if ad.IsSymbol(a[0]):
94
        raise Exception('Program Bug -- repeated symbol "%s"' % a[0]);
95
      ix = int(a[1]);
96
      if not (0 <= ix < 256):
97
        raise asmDef.AsmException('Out-of-range inport index:  "%s"' % inport);
98
      ad.RegisterInport(a[0],ix);
99
  if argList.O:
100
    for outport in argList.O:
101
      a=re.findall(r'^(O_\w+)=(0|[1-9]\d*)$',outport);
102
      if not a:
103
        raise asmDef.AsmException('Malformed -O argument: "%s"' % outport);
104
      a = a[0];
105
      if ad.IsSymbol(a[0]):
106
        raise asmDef.AsmException('Program Bug -- repeated symbol "%s"' % a[0]);
107
      ix = int(a[1]);
108
      if not (0 <= ix < 256):
109
        raise asmDef.AsmException('Out-of-range outport index:  "%s"' % outport);
110
      ad.RegisterOutport(a[0],ix);
111
  if argList.R:
112
    for outstrobe in argList.R:
113
      a=re.findall(r'^(O_\w+)=(0|[1-9]\d*)$',outstrobe);
114
      if not a:
115
        raise asmDef.AsmException('Malformed -R argument: "%s"' % outstrobe);
116
      a = a[0];
117
      if ad.IsSymbol(a[0]):
118
        raise asmDef.AsmException('Program Bug -- repeated symbol "%s"' % a[0]);
119
      ix = int(a[1]);
120
      if not (0 <= ix < 256):
121
        raise asmDef.AsmException('Out-of-range strobe-only outport index:  "%s"' % outstrobe);
122
      ad.RegisterOutstrobe(a[0],ix);
123
  if argList.S:
124
    for memory in argList.S:
125
      a=re.findall(r'^(\w+)=(0|[1-9]\d*)$',memory);
126
      if not a:
127
        raise asmDef.AsmException('Malformed -S argument: "%s"' % memory);
128
      a=a[0];
129
      length = int(a[1]);
130
      if not (0 < length <= 256):
131
        raise asmDef.AsmException('Out-of-range memory length:  "%s"' % outport);
132
      ad.RegisterMemoryLength(a[0],length);
133
  if argList.s:
134
    for stack in argList.s:
135
      a=re.findall(r'^(\w+)=(0|[1-9]\d*)$',stack);
136
      if not a:
137
        raise asmDef.AsmException('Malformed -s argument: "%s"' % stack);
138
      a = a[0];
139
      ad.RegisterStackLength(a[0],int(a[1]));
140
 
141
  # Construct the iterator that loops through the code bodies.
142
  fbi = asmDef.FileBodyIterator(argList.filename,ad);
143
  if argList.L:
144
    for path in argList.L:
145
      fbi.AddSearchPath(path);
146
 
147
  ################################################################################
148
  #
149
  # Stage 1:  Parse the files.
150
  #
151
  # Read the entire file, doing the following while reading the file:
152
  # - Store the raw content of each line or group of lines for output to the
153
  #   assembled memory initialization.
154
  #   Note: A group of lines consists the comment lines preceding a directive and
155
  #         the body of the directive.
156
  # - Convert group of lines into an array of the raw tokens.
157
  # - Check the integrity of the bodies defined by the list of raw tokens.
158
  # - For each array of raw tokens, incorporate already-defined symbols and update
159
  #   the assembler dictionaries.
160
  #   Note: At this point the space required for the function or main program
161
  #     is fully computed.
162
  #
163
  ################################################################################
164
 
165
  #
166
  # Loop through the directive bodies in the input files (including ".include"d
167
  # files).
168
  #
169
 
170
  ifstackStack = list();
171
  ifstack = None;
172
  for bl in fbi:
173
    filename = bl[0];
174
    startLine = bl[1];
175
    body = bl[2:];
176
    flc_loc = filename + ' at line ' + str(startLine+len(body)-1);
177
    # Start-of-file processing.
178
    if startLine == 0:
179
      if ifstack != None:
180
        ifstackStack.append(ifstack);
181
      ifstack = list();
182
    # End-of-file processing.
183
    elif startLine == -1:
184
      if len(ifstack) != 0:
185
        raise asmDef.AsmException('%d unmatched .IFDEF/.IFNDEF(s) at the end of %s' % (len(ifstack),filename,));
186
      if ifstackStack:
187
        ifstack = ifstackStack.pop();
188
      else:
189
        ifstack = None;
190
    # Handle conditional compilation directives.
191
    elif re.match(r'\s*\.ELSE\b',body[-1]):
192
      if not re.match(r'\s*\.ELSE\s*(;.*)?$',body[-1]):
193
        raise asmDef.AsmException('Malformed ".ELSE" in %s' % flc_loc);
194
      if not ifstack:
195
        raise asmDef.AsmException('Unmatched ".ELSE" in %s' % flc_loc);
196
      ifstack[-1] ^= True;
197
    elif re.match(r'\s*\.ENDIF\b',body[-1]):
198
      if not re.match(r'\s*\.ENDIF\s*(;.*)?$',body[-1]):
199
        raise asmDef.AsmException('Malformed ".ENDIF" in %s' % flc_loc);
200
      if not ifstack:
201
        raise asmDef.AsmException('Unmatched ".ENDIF" in %s' % flc_loc);
202
      ifstack.pop();
203
    elif re.match(r'\s*\.IFN?DEF\b',body[-1]):
204
      a = re.findall(r'\s*(\.IFN?DEF)\s*(\S+)\b\s*(;.*)?$',body[-1]);
205
      if not a:
206
        raise asmDef.AsmException('Malformed .IFDEF or .IFNDEF in %s' % flc_loc);
207
      a = a[0];
208
      ifstack.append(ad.IsSymbol(a[1]));
209
      if a[0] == '.IFNDEF':
210
        ifstack[-1] ^= True;
211
    # Ignore bodies rejected by conditional compilation.
212
    elif ifstack and not ifstack[-1]:
213
      pass;
214
    # ".include" directives don't have an associated body
215
    elif re.match(r'\s*\.include\s',body[-1]):
216
      a = re.findall(r'\s*\.include\s+(\S+)(\s*|\s*;.*)$',body[-1]);
217
      if not a:
218
        raise asmDef.AsmException('Malformed .include directive in %s' % flc_loc);
219
      a = a[0];
220
      fbi.Include(a[0]);
221
    # Parse the body of all other directives and ensure that only one ".main"
222
    # and one ".interrupt" are defined.
223
    else:
224
      rawTokens = asmDef.RawTokens(ad,filename,startLine,body);
225
      if not rawTokens:
226
        continue;
227
      ad.CheckRawTokens(rawTokens);
228
      ad.FillRawTokens(rawTokens);
229
 
230
  #
231
  # Ensure a ".main" body was declared.
232
  #
233
 
234
  if not ad.Main():
235
    raise asmDef.AsmException('Required ".main" body not provided');
236
 
237
  #
238
  # Enforce consistency between the command-line "-i" flag and whether or not an
239
  # ".interrupt" body was declared.
240
  #
241
 
242
  if argList.i and not ad.Interrupt():
243
    raise asmDef.AsmException('Required ".interrupt" body not provided');
244
  if not argList.i and ad.Interrupt():
245
    raise asmDef.AsmException('".interrupt" body not allowed near %s' % ad.Interrupt()[0]['loc']);
246
 
247
  ################################################################################
248
  #
249
  # Stage 2:  Identify the required functions, compute their addresses, and set
250
  # the addresses for all "jump" and "call" macros.
251
  #
252
  ################################################################################
253
 
254
  ad.EvaluateMemoryTree();
255
  ad.EvaluateFunctionTree();
256
 
257
  ################################################################################
258
  #
259
  # Stage 3:  Emit the program
260
  #
261
  # Do the following:
262
  # - If interrupts are enabled, then set the first 4 instructions to be a "dis"
263
  #   and a ".jump" instruction to the ".interrupt" function.
264
  # - Write the instructions for the ".main" body.
265
  # - Loop through the ".function" list in the order in which they were defined
266
  #   and write their instructions.
267
  # - Print the memory and instruction usage statistics.
268
  #
269
  ################################################################################
270
 
271
  ad.EmitMemories(argList.o);
272
  ad.EmitProgram(argList.o);
273
  argList.o.close();
274
 
275
################################################################################
276
#
277
# Terminating except clause -- print fatal error message and indicate failure to
278
# the invoking program.
279
#
280
################################################################################
281
 
282
except asmDef.AsmException, msg:
283
  print >> sys.stderr, 'FATAL ERROR:  ' + str(msg);
284
  exit(1);

powered by: WebSVN 2.1.0

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