ff5107740a1364f0395a2e97654ec56e9aba2bbf
[c4m-jtag.git] / c4m / cocotb / jtag / c4m_jtag_svfcocotb.py
1 from functools import singledispatch
2
3 import cocotb
4 from cocotb.binary import BinaryValue
5
6 from .c4m_jtag_svfgrammar import *
7
8 def decodescanspec(node):
9 length = int(str(node[2]))
10 fstr = "{:0"+str(node[2])+"b}"
11
12 g_tdi = node[4]
13 g_tdo = node[5]
14 g_mask = node[6]
15 g_smask = node[7]
16
17 if g_tdi is None:
18 tdi = None
19 else:
20 tdi = BinaryValue(fstr.format(int(str(g_tdi[2]),16)), length)
21
22 if g_tdo is None:
23 tdo = None
24 else:
25 tdo = BinaryValue(fstr.format(int(str(g_tdo[3]),16)), length)
26
27 if g_mask is None:
28 mask = None
29 else:
30 mask = BinaryValue(fstr.format(int(str(g_mask[3]),16)), length)
31
32 if g_smask is None:
33 smask = None
34 else:
35 smask = BinaryValue(fstr.format(int(str(g_smask[3]),16)), length)
36
37 return (length, tdi, tdo, mask, smask)
38
39
40 class SVF_Executor(object):
41 @cocotb.coroutine
42 def execute(self, node):
43 """This is the generic method"""
44 self._p("generic")
45 if False: # Make coroutine work
46 yield PythonTrigger()
47
48 @cocotb.coroutine
49 def _execute_NOP(self, node):
50 if False: # Make coroutine work
51 yield PythonTrigger()
52
53 @cocotb.coroutine
54 def _execute_EndDR(self, node):
55 self._p("EndDR ignored")
56 if False: # Make coroutine work
57 yield PythonTrigger()
58
59 @cocotb.coroutine
60 def _execute_EndIR(self, node):
61 self._p("EndIR ignored")
62 if False: # Make coroutine work
63 yield PythonTrigger()
64
65 @cocotb.coroutine
66 def _execute_Frequency(self, node):
67 self._p("Frequency ignored")
68 if False: # Make coroutine work
69 yield PythonTrigger()
70
71 @cocotb.coroutine
72 def _execute_HDR(self, node):
73 self._p("HDR ignored")
74 if False: # Make coroutine work
75 yield PythonTrigger()
76
77 @cocotb.coroutine
78 def _execute_HIR(self, node):
79 self._p("HIR ignored")
80 if False: # Make coroutine work
81 yield PythonTrigger()
82
83 @cocotb.coroutine
84 def _execute_SDR(self, node):
85 self._p("Executing SDR")
86 (length, tdi, tdo, mask, smask) = decodescanspec(node)
87
88 samelength = length == self._d_length
89 self._d_length = length
90
91 if tdi is None:
92 if not samelength:
93 raise(JTAGException("TDI needs to be specified when length of data changes"))
94 else:
95 self._d_tdi = tdi
96
97 if mask is not None:
98 self._d_mask = mask
99 elif not samelength:
100 self._d_mask = None
101
102 if smask is not None:
103 self._d_smask = smask
104 elif not samelength:
105 self._d_smask = None
106
107 yield self.master.shift_data(self._d_tdi)
108 if tdo is not None:
109 if self._d_mask is not None:
110 raise(JTAGException("MASK not supported for SDR"))
111 assert(self.master.result == tdo)
112
113 @cocotb.coroutine
114 def _execute_SIR(self, node):
115 (length, tdi, tdo, mask, smask) = decodescanspec(node)
116
117 samelength = length == self._i_length
118 self._i_length = length
119
120 if tdi is None:
121 if not samelength:
122 raise(JTAGException("TDI needs to be specified when length of data changes"))
123 else:
124 self._i_tdi = tdi
125
126 if mask is not None:
127 self._i_mask = mask
128 elif not samelength:
129 self._i_mask = None
130
131 if smask is not None:
132 self._i_smask = smask
133 elif not samelength:
134 self._i_smask = None
135
136 self._p("Executing SIR ({})".format(self._i_tdi.integer))
137
138 yield self.master.load_ir(self._i_tdi)
139 if tdo is not None:
140 if self._i_mask is not None:
141 raise(JTAGException("MASK not supported for SIR"))
142 assert(self.master.result == tdo)
143
144
145 @cocotb.coroutine
146 def _execute_State(self, node):
147 self._p("State")
148 if False: # Make coroutine work
149 yield PythonTrigger()
150
151 @cocotb.coroutine
152 def _execute_TDR(self, node):
153 self._p("TDR")
154 if False: # Make coroutine work
155 yield PythonTrigger()
156
157 @cocotb.coroutine
158 def _execute_TIR(self, node):
159 self._p("TIR")
160 if False: # Make coroutine work
161 yield PythonTrigger()
162
163 @cocotb.coroutine
164 def _execute_Trst(self, node):
165 self._p("TRST ignored")
166 if False: # Make coroutine work
167 yield PythonTrigger()
168
169 @cocotb.coroutine
170 def _execute_Runtest(self, node):
171 if node[1] is not None:
172 raise(JTAGException("State specification for RUNTEST not supported"))
173 # TODO: cycle the right number of clocks or wait the right time
174 yield(self.master.change_state([0]))
175
176 @cocotb.coroutine
177 def _execute_SVFFile(self, node):
178 self._p("Executing SVFFile")
179 for statement in node.elements[0]:
180 yield self.execute(statement)
181
182 def __init__(self, master):
183 # master is assumed to be a JTAG_Master class
184 # it needs to support methods load_ir() and shift_data()
185 self.master = master
186
187 # Due to bug in Grammar definition all possible classes have to have
188 # a dispatch entry otherwise an error will be raised.
189 self.execute = singledispatch(self.execute)
190 self.execute.register(EmptyLine, self._execute_NOP)
191 self.execute.register(Comment, self._execute_NOP)
192 self.execute.register(EndDR, self._execute_EndDR)
193 self.execute.register(EndIR, self._execute_EndIR)
194 self.execute.register(Frequency, self._execute_Frequency)
195 self.execute.register(HDR, self._execute_HDR)
196 self.execute.register(HIR, self._execute_HIR)
197 self.execute.register(Runtest, self._execute_Runtest)
198 self.execute.register(SDR, self._execute_SDR)
199 self.execute.register(SIR, self._execute_SIR)
200 self.execute.register(State, self._execute_State)
201 self.execute.register(TDR, self._execute_TDR)
202 self.execute.register(TIR, self._execute_TIR)
203 self.execute.register(Trst, self._execute_Trst)
204 self.execute.register(SVFFile, self._execute_SVFFile)
205
206 # Store the head and tail for the scan
207 self._d_tdi = self._d_tdi_h = self._d_tdi_t = None
208 self._d_tdo_h = self._d_tdo_t = None
209 self._i_tdi = self._i_tdi_h = self._i_tdi_t = None
210 self._i_tdo_h = self._i_tdo_t = None
211
212 # Remember the masks; smasks are ignored and bits always considered as care, e.g right
213 # value applied
214 self._d_length = self._d_length_h = self._d_length_t = None
215 self._d_mask = self._d_mask_h = self._d_mask_t = None
216 self._d_smask = self._d_smask_h = self._d_smask_t = None
217 self._i_length = self._i_length_h = self._i_length_t = None
218 self._i_mask = self._i_mask_h = self._i_mask_t = None
219 self._i_smask = self._i_smask_h = self._i_smask_t = None
220
221 @cocotb.coroutine
222 def run(self, cmds, p=print):
223 self._p = p
224 if isinstance(cmds, SVFFile):
225 yield self.execute(cmds)
226 else:
227 p = SVFFile.parser()
228 yield self.execute(p.parse_string(cmds))