1 |
2 |
sinclairrf |
################################################################################
|
2 |
|
|
#
|
3 |
6 |
sinclairrf |
# Copyright 2012-2014, Sinclair R.F., Inc.
|
4 |
2 |
sinclairrf |
#
|
5 |
|
|
################################################################################
|
6 |
|
|
|
7 |
|
|
import math
|
8 |
|
|
import re
|
9 |
|
|
|
10 |
|
|
from ssbccPeripheral import SSBCCperipheral
|
11 |
|
|
from ssbccUtil import SSBCCException;
|
12 |
|
|
|
13 |
|
|
class monitor_stack(SSBCCperipheral):
|
14 |
|
|
"""
|
15 |
|
|
Simulation-specific peripheral to flag invalid stack operations and display
|
16 |
|
|
the execution history immediately before the invalid operation.\n
|
17 |
|
|
Invalid data stack operations are:
|
18 |
|
|
pushing onto a full data stack
|
19 |
|
|
dropping from an empty data stack
|
20 |
|
|
nipping from an almost empty data stack\n
|
21 |
|
|
Invalid return stack operations are:
|
22 |
|
|
pushing onto a full return stack
|
23 |
|
|
dropping values from an empty return stack
|
24 |
|
|
returns from a data entry on the return stack
|
25 |
|
|
non-return operations from an address entry on the return stack\n
|
26 |
|
|
Invalid data operations are:
|
27 |
|
|
swap on an empty or almost empty data stack
|
28 |
|
|
in-place operations on an empty or almost empty data stack\n
|
29 |
|
|
Usage:
|
30 |
|
|
PERIPHERAL monitor_stack \\
|
31 |
|
|
[history==n]\n
|
32 |
|
|
Where:
|
33 |
|
|
history=n
|
34 |
|
|
display the n most recent operations when a stack error is encountered
|
35 |
|
|
Note: Normally the last 50 instructions are displayed.
|
36 |
|
|
"""
|
37 |
|
|
|
38 |
|
|
def __init__(self,peripheralFile,config,param_list,loc):
|
39 |
|
|
# Use the externally provided file name for the peripheral
|
40 |
|
|
self.peripheralFile = peripheralFile;
|
41 |
|
|
# Get the parameters.
|
42 |
6 |
sinclairrf |
allowables = (
|
43 |
|
|
( 'history', r'[1-9]\d*$', int, ),
|
44 |
|
|
);
|
45 |
|
|
names = [a[0] for a in allowables];
|
46 |
|
|
for param_tuple in param_list:
|
47 |
|
|
param = param_tuple[0];
|
48 |
|
|
if param not in names:
|
49 |
|
|
raise SSBCCException('Unrecognized parameter "%s" at %s' % (param,loc,));
|
50 |
|
|
param_test = allowables[names.index(param)];
|
51 |
|
|
self.AddAttr(config,param,param_tuple[1],param_test[1],loc,param_test[2]);
|
52 |
2 |
sinclairrf |
# Set optional parameters.
|
53 |
|
|
if not hasattr(self,'history'):
|
54 |
|
|
self.history = 50;
|
55 |
|
|
# Configure the system for this peripheral.
|
56 |
|
|
config.functions['display_trace'] = True;
|
57 |
|
|
|
58 |
|
|
def GenVerilog(self,fp,config):
|
59 |
|
|
body = self.LoadCore(self.peripheralFile,'.v');
|
60 |
|
|
outport_pure_strobe = '';
|
61 |
|
|
for ix in range(config.NOutports()):
|
62 |
|
|
thisPort = config.outports[ix][2:];
|
63 |
|
|
thisIsStrobe = True;
|
64 |
|
|
for jx in range(len(thisPort)):
|
65 |
|
|
signal = thisPort[jx];
|
66 |
|
|
signalType = signal[2];
|
67 |
|
|
if signalType == 'data':
|
68 |
|
|
thisIsStrobe = False;
|
69 |
|
|
elif signalType == 'strobe':
|
70 |
|
|
pass;
|
71 |
|
|
else:
|
72 |
|
|
raise Exception('Program Bug: Unrecognized outport signal type "%s"' % signalType);
|
73 |
|
|
if thisIsStrobe:
|
74 |
|
|
if len(outport_pure_strobe) > 0:
|
75 |
|
|
outport_pure_strobe += ' || ';
|
76 |
|
|
outport_pure_strobe += ('(s_T == 8\'h%02X)' % ix);
|
77 |
|
|
if len(outport_pure_strobe) == 0:
|
78 |
|
|
outport_pure_strobe = '1\'b0';
|
79 |
|
|
outport_pure_strobe = 'wire s__outport_pure_strobe = ' + outport_pure_strobe + ';';
|
80 |
6 |
sinclairrf |
for subpair in (
|
81 |
|
|
( r'\\bix__', 'ix__monitor_stack__', ),
|
82 |
|
|
( r'\\bs__', 's__monitor_stack__', ),
|
83 |
|
|
( r'@CORENAME@', config.Get('outCoreName'), ),
|
84 |
|
|
( r'@HISTORY@', str(self.history), ),
|
85 |
|
|
( r'@LAST_INPORT@', '9\'h%03X' % config.NInports(), ),
|
86 |
|
|
( r'@LAST_OUTPORT@', '9\'h%03X' % config.NOutports(), ),
|
87 |
|
|
( r'@NINSTRUCTIONS@', str(config.Get('nInstructions')['length']), ),
|
88 |
|
|
( r'@OUTPORT_PURE_STROBE@', outport_pure_strobe, ),
|
89 |
|
|
):
|
90 |
|
|
body = re.sub(subpair[0],subpair[1],body);
|
91 |
2 |
sinclairrf |
for ixBank in range(4):
|
92 |
|
|
memParam = config.GetMemoryByBank(ixBank);
|
93 |
|
|
if memParam:
|
94 |
|
|
maxLength = memParam['maxLength'];
|
95 |
|
|
else:
|
96 |
|
|
maxLength = 0;
|
97 |
|
|
body = re.sub('@MEM_LIMIT_%d@' % ixBank, str(maxLength), body);
|
98 |
|
|
fp.write(body);
|