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