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

Subversion Repositories ssbcc

[/] [ssbcc/] [trunk/] [ssbcc] - Blame information for rev 12

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 12 sinclairrf
# Copyright 2012-2015, Sinclair R.F., Inc.
4 2 sinclairrf
# Build an SSBCC system.
5
 
6
import math
7
import os
8
import re
9
import sys
10
import tempfile
11
 
12
from ssbccUtil import *;
13
from ssbccConfig import SSBCCconfig;
14 12 sinclairrf
from ssbccPeripheral import InterruptPeripheralAssigned;
15 2 sinclairrf
 
16
################################################################################
17
#
18
# Surround the program with a try ... except clause
19
#
20
################################################################################
21
 
22
try:
23
 
24
  ################################################################################
25
  #
26
  # Parse the command line arguments
27
  #
28
  ################################################################################
29
 
30
  #
31
  # Construct the command-line argument list parser
32
  #
33
 
34
  def validateFile(filename):
35
    if filename == '-':
36
      filename = '/dev/stdin';
37
    try:
38
      return file(filename,'r');
39
    except:
40
      raise SSBCCException('Error opening "%s"' % filename);
41
 
42
  import argparse
43
  argListParser = argparse.ArgumentParser(description='SSBCC system builder');
44 9 sinclairrf
  argListParser.add_argument('-D', metavar='D_name', type=str, action='append', help='Define symbol (must start with "D_")');
45 2 sinclairrf
  argListParser.add_argument('-G', metavar='parameter_name=value', type=str, action='append', help='Override parameter value');
46
  argListParser.add_argument('-I', metavar='include_dir', type=str, action='append', help='Add search directory for included files and peripherals');
47 3 sinclairrf
  argListParser.add_argument('-M', metavar='macropath', action='append', help='Macro search path');
48 2 sinclairrf
  argListParser.add_argument('-P', metavar='peripheral_name[="parameters"]', type=str, action='append', help='Add peripheral');
49
  argListParser.add_argument('-o', metavar='outCoreName', type=str, help='output core name');
50
  argListParser.add_argument('-q', action='store_true', help='quiet');
51
  argListParser.add_argument('--define-clog2', action='store_true', help='define clog2 instead of using built-in $clog2');
52
  argListParser.add_argument('--display-opcode', action='store_true', help='add 3-letter decode of opcode (for trace viewer)');
53 11 sinclairrf
  argListParser.add_argument('--help-macro', metavar='macroName', type=str, help='Display usage message for the specified macro (passed on to the assembler)');
54
  argListParser.add_argument('--list-macros', action='store_true', help='list the built-in and user-defined macros (passed on to the assembler)');
55 3 sinclairrf
  argListParser.add_argument('--rand-instr-mem', action='store_true', help='fill unused instruction memory with random values');
56
  argListParser.add_argument('--synth-instr-mem', type=str, help='synthesis constraint for instruction memory');
57 2 sinclairrf
  argListParser.add_argument('--verilator-tracing-on', action='store_true', help='show all signals in verilator waveform files');
58
  argListParser.add_argument('filename', metavar='filename', type=validateFile, help='SSBCC configuration file');
59
  argList = argListParser.parse_args();
60
 
61
  #
62
  # Set the command-line dependent configuration parameters.
63
  #
64
 
65
  config = SSBCCconfig();
66
 
67
  config.Set('define_clog2',argList.define_clog2);
68 3 sinclairrf
  config.Set('rand_instr_mem',argList.rand_instr_mem);
69 2 sinclairrf
  config.Set('verilator_tracing_on',argList.verilator_tracing_on);
70
 
71
  if argList.display_opcode:
72
    config.functions['display_opcode'] = True;
73
 
74
  if argList.D:
75 9 sinclairrf
    for name in argList.D:
76
      if not re.match('D_',name):
77 12 sinclairrf
        raise SSBCCException('Argument "%s" to %s should start with "D_"' % (name,sys.argv[0],));
78 9 sinclairrf
      config.AddDefine(name);
79 2 sinclairrf
 
80 3 sinclairrf
  if argList.I:
81
    for pathString in argList.I:
82
      if not os.path.isdir(pathString):
83 9 sinclairrf
        raise SSBCCException('Bad path string:  "%s/%s"' % (os.getcwd(),pathString,));
84 3 sinclairrf
      config.AppendIncludePath(pathString);
85
      config.InsertPeripheralPath(pathString);
86
 
87 2 sinclairrf
  if argList.o:
88
    config.Set('outCoreName',argList.o);
89
  else:
90
    config.Set('outCoreName',os.path.splitext(os.path.basename(argList.filename.name))[0]);
91
 
92 3 sinclairrf
  if argList.synth_instr_mem:
93
    config.Set('synth_instr_mem',argList.synth_instr_mem);
94
  else:
95
    config.Set('synth_instr_mem',None);
96
 
97 2 sinclairrf
  #
98
  # Read the configuration file into a line-by-line buffer.
99 3 sinclairrf
  # Note:  argList.filename is a file handle, so no paths will be searched by
100
  #        LoadFile.  This is ensured by setting config to None.
101 2 sinclairrf
  #
102
 
103
  filename = argList.filename.name;
104 3 sinclairrf
  configList = LoadFile(argList.filename,None);
105 2 sinclairrf
  ifstack = list();
106
 
107
  configListStack = list();
108
 
109
  #
110
  # Read the configuration file.
111
  #
112
 
113
  bufLine = "";
114
  compiler = [];
115
  user_header = list();
116
  while configList or configListStack:
117
    # If the current file has ended, then proceed to the next file.
118
    if not configList:
119
      if not len(bufLine) == 0:
120
        raise SSBCCException('Malformed configuration command at the end of %s' % filename);
121
      if ifstack:
122
        raise SSBCCException('%d unmatched conditional(s) at end of %s' % (len(ifstack),filename,));
123
      (filename,configList,ifstack) = configListStack.pop();
124
      continue;
125
    # Get the next line to process and its line number.
126
    (tmpLine,ixLine) = configList.pop(0);
127
    # Use the start line of a sequence of lines for error messages.
128
    if not bufLine:
129
      loc = '%s:%d' % (filename,ixLine,);
130
    # Merge continuation lines.
131
    bufLine += tmpLine;
132
    if bufLine and bufLine[-1] == '\\':
133
      bufLine = bufLine[:-1];
134
      continue;
135
    line = bufLine;
136
    bufLine = "";
137
    # Reject blank and comment lines
138
    if re.match(r'\s*(#.*)?$',line):
139
      pass;
140
    # .ELSE
141
    elif re.match(r'\s*\.ELSE\b',line):
142
      if not ifstack:
143
        raise SSBCCException('unmatched ".ELSE" at %s' % loc);
144
      ifstack[-1] = not ifstack[-1];
145
    # .ENDIF
146
    elif re.match(r'\s*\.ENDIF\b',line):
147
      if not ifstack:
148
        raise SSBCCException('unmatched ".ENDIF" at %s' % loc);
149
      ifstack.pop();
150
    # .IFDEF conditional
151
    elif re.match(r'\s*\.IFDEF\b',line):
152
      cmd = re.findall(r'\s*\.IFDEF\s+(\w+)\s*$',line);
153
      if not cmd:
154
        raise SSBCCException('Malformed ".IFDEF" configuration command on %s' % loc);
155
      cmd = cmd[0];
156
      ifstack.append(config.IsSymbol(cmd));
157
    # .IFNDEF conditional
158
    elif re.match(r'\s*\.IFNDEF\b',line):
159
      cmd = re.findall(r'\s*\.IFNDEF\s+(\w+)\s*$',line);
160
      if not cmd:
161
        raise SSBCCException('Malformed ".IFNDEF" configuration command on %s' % loc);
162
      cmd = cmd[0];
163
      ifstack.append(not config.IsSymbol(cmd));
164
    elif re.match(r'\s*.INCLUDE\b',line):
165
      cmd = re.findall(r'\s*\.INCLUDE\s+(\S+)\s*$',line);
166
      if not cmd:
167
        raise SSBCCException('Malformed ".INCLUDE" configuration command on %s' % loc);
168
      configListStack.append((filename,configList,ifstack,));
169
      filename = cmd[0];
170 3 sinclairrf
      configList = LoadFile(filename,config);
171 2 sinclairrf
      ifstack = list();
172
    # Consume configuration commands disabled by conditionals
173
    elif ifstack and not ifstack[-1]:
174
      pass;
175
    # ARCHITECTURE
176
    elif re.match(r'\s*ARCHITECTURE\b',line):
177
      if config.Exists('architecture'):
178
        raise SSBCCException('ARCHITECTURE already specified before %s' % loc);
179
      cmd = re.findall(r'\s*ARCHITECTURE\s+(\S+)\s+(\S+)$',line);
180
      if not cmd:
181
        raise SSBCCException('Malformed ARCHITECTURE configuration command at %s: "%s"' % (loc,line,));
182
      cmd = cmd[0];
183
      config.Set('architecture',cmd[0]);
184
      config.Set('hdl',cmd[1]);
185
      config.Set('corepath',os.path.join(sys.path[0],config.Get('architecture')));
186
      if not os.path.isdir(config.Get('corepath')):
187
        raise SSBCCException('Architecture "%s" does not exist at %s' % (cmd,loc,));
188
      config.InsertPeripheralPath(os.path.join(config.Get('corepath'),'peripherals'));
189
      # TODO -- move these assignments into an object
190
      config.Set('data_width',8);
191
    # ASSEMBLY language for processor code
192
    elif re.match(r'\s*ASSEMBLY\b',line):
193
      cmd = re.findall(r'\s*ASSEMBLY\s+(\S.*)',line);
194
      compiler = ('asm',cmd[0],);
195
    # COMBINE
196
    elif re.match(r'\s*COMBINE\b',line):
197
      config.ProcessCombine(loc,line);
198
    # CONSTANTS
199
    elif re.match(r'\s*CONSTANT\b',line):
200
      if not config.Exists('architecture'):
201
        raise SSBCCException('"CONSTANT"s cannot be defined before the "ARCHITECTURE" is defined at %s' % loc);
202 11 sinclairrf
      cmd = re.findall(r'\s*CONSTANT\s+(C_\w+)\s+(0|-?[1-9]\d*|\w+)\s*$',line);
203 2 sinclairrf
      if not cmd:
204
        raise SSBCCException('Malformed "CONSTANT" configuration command on %s: "%s"' % (loc,line,));
205
      cmd = cmd[0];
206
      config.AddConstant(cmd[0],cmd[1],loc);
207
    # DATA_STACK
208
    elif re.match(r'\s*DATA_STACK\b',line):
209
      if config.Exists('data_stack'):
210
        raise SSBCCException('DATA_STACK already defined before %s' % loc);
211
      cmd = re.findall(r'\s*DATA_STACK\s+([1-9]\d*)',line);
212
      if not cmd:
213
        raise SSBCCException('Malformed "DATA_STACK" configuration command on %s: "%s"' % (loc,line,));
214
      x = int(cmd[0]);
215
      if math.modf(math.log(x,2))[0] != 0:
216
        raise SSBCCException('DATA_STACK must be set to a power of 2, not %d, at %s' % (x,loc,));
217
      if x < 8:
218
        raise SSBCCException('DATA_STACK must be at least 8, not %d, at %s' % (x,loc,));
219
      config.Set('data_stack',int(cmd[0]));
220
    # INPORT
221
    elif re.match(r'\s*INPORT\b',line):
222
      if not config.Exists('architecture'):
223
        raise SSBCCException('"INPORT"s cannot be defined before the "ARCHITECTURE" is defined at %s' % loc);
224
      config.ProcessInport(loc,line);
225
    # INSTRUCTION
226
    elif re.match(r'\s*INSTRUCTION\b',line):
227
      if config.Exists('nInstructions'):
228
        raise SSBCCException('INSTRUCTION already specified before %s' % loc);
229
      cmd = re.findall(r'\s*INSTRUCTION\s+([1-9]\d*\*?[1-9]?\d*)\s*$',line);
230
      if not cmd:
231
        raise SSBCCException('Malformed "INSTRUCTION" configuration command at %s: "%s"' % (loc,line,));
232
      config.SetMemoryBlock('nInstructions',cmd[0],(loc,line,));
233
    # INVERT_RESET
234
    elif re.match(r'\s*INVERT_RESET\s*$',line):
235
      if (config.Exists('invertReset')):
236
        raise SSBCCException('INVERT_RESET already specified before %s' % loc);
237
      config.Set('invertReset',True);
238
    # LOCALPARM
239
    elif re.match(r'\s*LOCALPARAM\b',line):
240
      cmd = re.findall(r'\s*LOCALPARAM\s+(L_\w+)\s+(\S+)$',line);
241
      if (not cmd) or (len(cmd[0]) != 2):
242
        raise SSBCCException('Malformed LOCALPARAM configuration command at %s: "%s"' % (loc,line,));
243
      cmd = cmd[0];
244
      config.AddParameter(cmd[0],cmd[1],loc);
245
    # MEMORY
246
    elif re.match(r'\s*MEMORY\b',line):
247
      if not config.Exists('architecture'):
248
        raise SSBCCException('"MEMORY"s cannot be defined before the "ARCHITECTURE" is defined at %s' % loc);
249
      # TODO -- make the maximum number of memories architecture dependent
250
      if config.NMemories() >= 4:
251
        raise SSBCCException('Program is limited to 4 memories');
252
      cmd = re.findall(r'\s*MEMORY\s+(RAM|ROM)\s+([A-Za-z]\w*)\s+(\d+)\s*$',line);
253
      if (not cmd) or (len(cmd[0]) != 3):
254
        raise SSBCCException('Malformed MEMORY configuration command at %s: "%s"' % (loc,line,));
255
      config.AddMemory(cmd[0],loc);
256
    # OUTPORT
257
    elif re.match(r'\s*OUTPORT\b',line):
258
      if not config.Exists('architecture'):
259
        raise SSBCCException('"OUTPORT"s cannot be defined before the "ARCHITECTURE" is defined at %s' % loc);
260
      config.ProcessOutport(line,loc);
261
    # PARAMETER
262
    elif re.match(r'\s*PARAMETER\b',line):
263
      cmd = re.findall(r'\s*PARAMETER\s+(G_\w+)\s+(\S+)$',line);
264
      if (not cmd) or (len(cmd[0]) != 2):
265
        raise SSBCCException('Malformed PARAMETER configuration command at %s: "%s"' % (loc,line,));
266
      cmd = cmd[0];
267
      config.AddParameter(cmd[0],cmd[1],loc);
268
    # PERIPHERAL
269
    elif re.match(r'\s*PERIPHERAL\b',line):
270
      if not config.Exists('architecture'):
271
        raise SSBCCException('"PERIPHERAL"s cannot be defined before the "ARCHITECTURE" is defined at %s' % loc);
272
      config.ProcessPeripheral(loc,line);
273
    # PORTCOMMENT
274
    elif re.match(r'\s*PORTCOMMENT\b',line):
275
      cmd = re.findall(r'\s*PORTCOMMENT\s+(.*)',line);
276
      config.AddIO(cmd[0],0,'comment',loc);
277
    # RETURN_STACK
278
    elif re.match(r'\s*RETURN_STACK\b',line):
279
      if config.Exists('return_stack'):
280
        raise SSBCCException('RETURN_STACK already specified before %s' % loc);
281
      cmd = re.findall(r'\s*RETURN_STACK\s+([1-9]\d*)',line);
282
      if not cmd:
283
        raise SSBCCException('Malformed "RETURN_STACK" configuration command at %s: "%s"' % (loc,line,));
284
      config.Set('return_stack',int(cmd[0]));
285
    # SRAM_WIDTH
286
    elif re.match(r'\s*SRAM_WIDTH\b',line):
287
      if config.Exists('sram_width'):
288
        raise SSBCCException('SRAM_WIDTH already specified before %s' % loc);
289
      cmd = re.findall(r'\s*SRAM_WIDTH\s+([1-9]\d*)',line);
290
      if not cmd:
291
        raise SSBCCException('Malformed "SRAM_WIDTH" configuration command %s: "%s"' % (loc,line,));
292
      config.Set('sram_width',int(cmd[0]));
293
    # USER_HEADER
294
    elif re.match(r'\s*USER_HEADER\b',line):
295
      user_header_done = False;
296 3 sinclairrf
      while configList:
297
        (line,ixLine) = configList.pop(0);
298
        if re.match(r'\s*END_USER_HEADER\b',line):
299 2 sinclairrf
          user_header_done = True;
300
          break;
301
        user_header.append(line);
302
      if not user_header_done:
303
        raise SSBCCException('No "END_USER_HEADER" found for "USER_HEADER" at %s' % loc);
304
    # error
305
    else:
306
      raise SSBCCException('Unrecognized configuration command at %s: "%s"' % (loc,line,));
307
  if bufLine:
308
    raise SSBCCException('Malformed last line(s): "%s"' % bufLine);
309
 
310
  if ifstack:
311
    raise SSBCCException('%d unmatched conditional(s) at end of %s' % (len(ifstack),filename,));
312
 
313
  #
314
  # Incorporate command-line specified parameter and localparam values.
315
  #
316
 
317
  if argList.G:
318
    for parameter in argList.G:
319
      if not re.match(r'[LG]_\w+=\S+$',parameter):
320
        raise SSBCCException('Malformed parameter specification: "%s"' % parameter);
321
      cmd = re.findall(r'([LG]_\w+)=(\S+)',parameter);
322
      cmd = cmd[0];
323
      config.OverrideParameter(cmd[0],cmd[1]);
324
 
325
  #
326
  # Append peripherals from command-line.
327
  #
328
 
329
  if argList.P:
330
    for peripheral in argList.P:
331
      config.ProcessPeripheral(-1,'PERIPHERAL '+peripheral);
332
 
333
  #
334
  # Set unspecified default values
335
  #
336
 
337
  if not config.Exists('sram_width'):
338
    config.Set('sram_width',9);
339
  if not config.Exists('invertReset'):
340
    config.Set('invertReset',False);
341
 
342
  #
343
  # end-of-file processing
344
  #
345
 
346
  if not config.Exists('architecture'):
347
    raise SSBCCException('Required ARCHITECTURE configuration command missing');
348
  if not config.Exists('data_stack'):
349
    raise SSBCCException('Required DATA_STACK configuration command missing');
350
  if not config.Exists('nInstructions'):
351
    raise SSBCCException('Required INSTRUCTION configuration command missing');
352
  if not config.Exists('return_stack'):
353
    raise SSBCCException('Required RETURN_STACK configuration command missing');
354
 
355
  # Ensure reasonable values
356
  if config.Get('nInstructions')['length'] > 2**13:
357
    raise SSBCCException('Instruction space cannot exceed %d at %s: "%s"' % (2**13,loc,line,));
358
 
359
  # Add memories that are not combined into singleton entries in the "combined"
360
  # list and complete the address range assignments.
361
  config.CompleteCombines();
362
 
363
  ################################################################################
364
  #
365
  # Compile the processor code and read the tables it generated.
366
  #
367
  ################################################################################
368
 
369
  # Generate peripheral libraries (if any).
370 9 sinclairrf
  for p in config.peripheral:
371
    p.GenAssembly(config);
372 2 sinclairrf
 
373
  # Compute the file name to store the assembler output
374
  assemblerOutput = os.path.splitext(argList.filename.name)[0]+'.9x8-meta'
375
 
376
  # Compute the command to invoke the compiler.
377
  if not compiler:
378
    raise SSBCCException('ASSEMBLY configuration command is missing');
379
  cmd = os.path.join(config.Get('corepath'), compiler[0]);
380 11 sinclairrf
  if argList.help_macro:
381
    cmd += ' --help-macro %s' % argList.help_macro
382
  if argList.list_macros:
383
    cmd += ' --list-macros'
384 12 sinclairrf
  if InterruptPeripheralAssigned():
385
    cmd += ' -i';
386 2 sinclairrf
  for name in config.constants:
387
    cmd += (' -C %s=%s' % (name,config.constants[name],));
388 9 sinclairrf
  for name in config.defines:
389
    cmd += (' -D %s' % name);
390 2 sinclairrf
  for ix in range(len(config.parameters)):
391
    cmd += (' -G %s' % config.parameters[ix][0]);
392
  for ix in range(config.NInports()):
393
    cmd += (' -I %s=%d' % (config.inports[ix][0],ix));
394
  for ix in range(config.NOutports()):
395
    if config.IsStrobeOnlyOutport(config.outports[ix]):
396
      cmd += (' -R %s=%d' % (config.outports[ix][0],ix));
397
    else:
398
      cmd += (' -O %s=%d' % (config.outports[ix][0],ix));
399
  for memNameLength in config.MemoryNameLengthList():
400
    cmd += (' -S %s=%d' % memNameLength);
401
  for signalNameLength in config.SignalLengthList():
402
    cmd += (' -S %s=%d' % signalNameLength);
403
  cmd += ' -o ' + assemblerOutput;
404
  for stack_name in ('data_stack','return_stack',):
405
    cmd += ' -s %s=%d' % (stack_name,config.config[stack_name],);
406 3 sinclairrf
  cmd += ' -L %s' % os.path.join(sys.path[0],'lib','9x8');
407
  if argList.M:
408
    for path in argList.M:
409
      cmd += ' -M %s' % path;
410
  cmd += ' -M %s' % os.path.join(sys.path[0],'macros','9x8');
411 2 sinclairrf
  if argList.I:
412
    for pathString in argList.I:
413
      cmd += ' -L %s' % pathString;
414
  cmd += ' ' + compiler[1];
415
 
416
  # Invoke the compiler and exit if it failed.
417
  if not argList.q:
418 11 sinclairrf
    print 'Invoking the assembler with the following command:  ' + cmd;
419 2 sinclairrf
  cmdStatus = os.system(cmd);
420
  if cmdStatus != 0:
421
    raise SSBCCException('Running the assembler');
422
 
423
  # Read the assembler output tables.
424 11 sinclairrf
  fpAssemberOutput = open(assemblerOutput,'rt');
425 2 sinclairrf
  ixLine = 0;
426
  programBody = list();
427
  programBodyLength = 0;
428
  for line in fpAssemberOutput:
429
    ixLine = ixLine + 1;
430
    # blank line
431
    if re.match('^\s*$',line):
432
      continue;
433
    # memory type, name, index, and length
434
    elif re.match(':memory',line):
435
      cmd = re.findall(':memory (\S+) (\S+) (\S+) (\S+)',line);
436
      cmd = cmd[0];
437
      memName = cmd[1];
438
      if not config.IsMemory(memName):
439
        raise SSBCCException('%s "%s" not declared in %s' % (cmd[0],memName,argList.filename,));
440
      memParam = config.GetMemoryParameters(memName);
441
      if cmd[0] != memParam['type']:
442
        raise SSBCCException('Type of memory "%s" is inconsistent' % memName);
443
      if int(cmd[3]) > memParam['maxLength']:
444
        raise SSBCCException('Length of memory "%s" is %s which exceeds limit of %d' % (memName,cmd[3],memParam['maxLength'],));
445
      memoryBody = list();
446
      for line in fpAssemberOutput:
447
        ixLine = ixLine + 1;
448
        if len(line) > 1:
449
          memoryBody.append(line)
450
        else:
451
          break;
452
      config.SetMemoryParameters(memParam,dict(bank=int(cmd[2]),length=int(cmd[3]),body=memoryBody));
453
    # program .main, optional .interrupt, and length
454
    elif re.match(':program',line):
455
      cmd = re.findall(':program (\d+) (\S+) (\d+)',line);
456
      mainStart = int(cmd[0][0]);
457 12 sinclairrf
      if cmd[0][1] != '[]':
458
        config.Set('interruptAddress',int(cmd[0][1]));
459 2 sinclairrf
      mainLength = int(cmd[0][2]);
460
      for line in fpAssemberOutput:
461
        ixLine = ixLine + 1;
462
        while line and line[-1] in ('\n','\r',):
463
          line = line[:-1];
464
        if not line:
465
          break;
466
        programBody.append(line);
467
        if line[0] != '-':
468
          programBodyLength = programBodyLength + 1;
469
      if programBodyLength != mainLength:
470
        raise SSBCCException('Program Bug:  program length doesn\'t match declared length');
471
      maxProgramBodyLength = config.Get('nInstructions')['length'];
472
      if programBodyLength > maxProgramBodyLength:
473
        raise SSBCCException('Program body length = %d is longer than the allocated instruction table = %d' % (programBodyLength,maxProgramBodyLength,));
474
    else:
475
      raise Exception('Program Bug:  Unrecognized line at %s:%d :  "%s"' % (fpAssemberOutput.filename,ixLine,line,));
476
 
477
  ################################################################################
478
  #
479
  # Ensure the processor has been consistently defined.
480
  #
481
  ################################################################################
482
 
483 12 sinclairrf
  # Ensure consistent implementation of an interrupt peripheral and an interrupt
484
  # handler in the source assembly.
485
  if InterruptPeripheralAssigned() and not config.InterruptVector():
486
    raise SSBCCException('Interrupt peripheral defined but no .interrupt function defined');
487
  if config.InterruptVector() and not InterruptPeripheralAssigned():
488
    raise ssbccPeripheral('.interrupt function defined but no interrupt peripheral defined');
489
 
490 2 sinclairrf
  # Ensure all memories are used.
491
  for ixMem in range(config.NMemories()):
492
    memParam = config.GetMemoryParameters(ixMem);
493
    if 'length' not in memParam:
494
      raise SSBCCException('Memory "%s" not used in program' % memParam['name']);
495
 
496
  ################################################################################
497
  #
498
  # Generate the processor core.
499
  #
500
  ################################################################################
501
 
502
  #
503
  # Access the language-specific core generator and core.
504
  #
505
 
506
  if config.Get('hdl') == 'Verilog':
507
    ssbccGenFile = 'ssbccGenVerilog.py';
508
  elif config.Get('hdl') == 'VHDL':
509
    ssbccGenFile = 'ssbccGenVHDL.py';
510
  else:
511
    raise SSBCCException('Unrecognized hdl = "%s"' % config.Get('hdl'));
512
 
513
  ssbccGenFile = os.path.join(config.Get('corepath'),ssbccGenFile);
514
  if not os.path.isfile(ssbccGenFile):
515
    raise SSBCCException('Core generator "%s" missing for hdl = "%s"' % (ssbccGenFile,config.Get('hdl'),));
516
  execfile(ssbccGenFile);
517
 
518
  rawCoreName = os.path.join(config.Get('corepath'),genCoreName());
519
  if not os.path.isfile(rawCoreName):
520
    raise SSBCCException('Core "%s% missing for hdl = "%s"' % (rawCoreName,config.Get('hdl'),));
521 11 sinclairrf
  fpRawCore = open(rawCoreName,'rt');
522 2 sinclairrf
 
523
  outName = genOutName(config.Get('outCoreName'));
524
  fpOutCore = open(outName,'wt');
525
 
526
  memFileName = re.sub(r'\.v.*','.mem',outName);
527
  fpMemFile = open(memFileName,'wt');
528
 
529
  #
530
  # Loop through the core, copying or filling in the file as required.
531
  #
532
 
533
  for line in fpRawCore:
534
    if not re.match(r'..@SSBCC@',line):
535
      if re.match(r'\s*(reg|wire)\s',line):
536
        cmd = re.findall(r'\s*(reg|wire)\s+([[][^]]+]\s+)?(\w+)\b',line);
537
        if config.IsSymbol(cmd[0][-1]):
538
          raise SSBCCException('Symbol "%s" is used by the core and cannot be used by peripherals, etc.' % cmd[0][-1]);
539
      fpOutCore.write(line);
540
      continue;
541
    fillCommand = re.findall(r'..@SSBCC@\s+(\S+)',line)[0];
542
    # memories
543 12 sinclairrf
    if fillCommand == 'memories':
544 2 sinclairrf
      genMemories(fpOutCore,fpMemFile,config,programBody);
545
    # peripherals
546
    elif fillCommand == 'peripherals':
547
      if not config.peripheral:
548
        fpOutCore.write('//\n// No peripherals\n//\n');
549 9 sinclairrf
      for p in config.peripheral:
550
        if p != config.peripheral[0]:
551 2 sinclairrf
          fpOutCore.write('\n');
552 9 sinclairrf
        p.GenHDL(fpOutCore,config);
553 2 sinclairrf
    # "s_memory" declaration
554
    elif fillCommand == 's_memory':
555
      if config.NMemories() == 0:
556
        fpOutCore.write('wire [7:0] s_memory = 8\'h00;\n');
557
      else:
558
        fpOutCore.write('wire [7:0] s_memory;\n');
559
    # user_header
560
    elif fillCommand == 'user_header':
561
      genUserHeader(fpOutCore,user_header);
562
    # Verilator tracing on/off
563
    elif fillCommand == "verilator_tracing":
564
      if config.Get('verilator_tracing_on'):
565
        fpOutCore.write('/* verilator tracing_on */\n');
566
      else:
567
        fpOutCore.write('/* verilator tracing_off */\n');
568 12 sinclairrf
    # All others are specific to the core.
569 2 sinclairrf
    else:
570 12 sinclairrf
      doFillCommand(fillCommand,fpOutCore,config);
571 2 sinclairrf
 
572
  #
573
  # Write package file (for use in VHDL or mixed-language projects)
574
  #
575
 
576
  import ssbccGenVhdlPkg
577
  ssbccGenVhdlPkg.genVhdlPkg(config);
578
 
579
################################################################################
580
#
581
# Terminating except clause
582
#
583
################################################################################
584
 
585
except SSBCCException, msg:
586
  print >> sys.stderr, 'FATAL ERROR:  ' + str(msg);
587
  exit(1);

powered by: WebSVN 2.1.0

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