1
package com.sun.electric.tool.simulation.test;
4
import java.util.ArrayList;
7
* Created by IntelliJ IDEA.
11
* Copyright (c) 2004,2005 by Sun Microsystems, Inc.
16
* Parent class for {@link NanosimJtagTester} and {@link NanosimJtagSubchainTester}.
17
* Contains common code shared between the child classes.
19
public abstract class NanosimJtag extends JtagTester {
21
protected final NanosimModel nm;
22
protected float tapVolt; // ignored at this time
23
protected double delay; // delay in ns
25
private static final boolean DEBUG = false;
27
NanosimJtag(NanosimModel nm) {
31
void configure(float tapVolt, long kiloHerz) {
32
this.tapVolt = tapVolt;
33
this.delay = (1.0/kiloHerz * 1e6) / 2;
38
void setLogicOutput(int index, boolean newLevel) {
39
System.out.println("Nanosim JtagTester does not support 'setLogicOutput("+index+", "+newLevel+"). Use LogicSettable instead.");
42
public boolean isBypassScanning() {
43
return nm.isBypassScanning();
46
// ==========================================================
48
protected void doBypassScanning(ChainNode chain, boolean readEnable, boolean writeEnable) {
49
// this mode bypasses scanning, and reads/writes directly
50
// to the bits the scan chain controls, as long as those
51
// nets have been defined in the XML file.
52
if (DEBUG) System.out.println("Scanning in "+chain.getName()+" in bypass-scanning mode");
54
// initialize out bits last data scanned in
55
// this prevents problems with uninitialized bit vectors if the user does not read
56
if (chain.getOutBitsExpected().isInvalid())
57
chain.getOutBits().set(0, chain.getOutBitsExpected().getNumBits(), false);
59
chain.getOutBits().put(0, chain.getOutBitsExpected());
62
chain.getOutBits().put(0, readDirect(chain));
66
checkDataNets(chain, 0);
67
checkDataNets(chain, 1);
72
* Get a list of DataNets from the chain.
73
* @param chain the chain to read
74
* @param set which set to get. Currently only two supported, so only 0 or 1
75
* @return a list of DataNets of the (hierarchical) data out net names.
76
* May contain null for undefined nets
78
protected static List getDataNets(SubchainNode chain, int set) {
79
// get the scan chain data nets node corresponding to the chain
80
MyTreeNode system = chain.getParent().getParent(); // this is the system node
81
MyTreeNode scanchainnets = MyTreeNode.getNode(system, XMLIO.SCAN_CHAIN_DATA_NETS);
82
if (scanchainnets == null) return getDataNetsOld(chain, set); // must be using old version
84
SubchainNode datachain = (SubchainNode)MyTreeNode.getNode(scanchainnets, chain.getName());
85
if (datachain == null) {
86
// if more than one jtag contoller, datanet chain name is prepended with chip name
87
MyTreeNode chip = chain.getParent();
88
datachain = (SubchainNode)MyTreeNode.getNode(scanchainnets, chip.getName()+"_"+chain.getName());
90
if (datachain == null) return getDataNetsOld(chain, set);
92
List datanets = new ArrayList();
93
for (int i=0; i<datachain.getChildCount(); i++) {
94
SubchainNode subnode = (SubchainNode)datachain.getChildAt(i);
96
datanets.add(subnode.getDataNet());
98
datanets.add(subnode.getDataNet2());
105
* Get a list of DataNets from the chain.
106
* @param chain the chain to read
107
* @param set which set to get. Currently only two supported, so only 0 or 1
108
* @return a list of DataNets of the (hierarchical) data out net names.
109
* May contain null for undefined nets
110
* @deprecated this was used when the xml file contains data nets specified hierarchically
111
* along with the scan chain bits. I have since split the data nets out into a separate,
114
protected static List getDataNetsOld(SubchainNode chain, int set) {
115
// get names of data out bits
116
if (chain.getChildCount() == 0) {
117
List list = new ArrayList();
118
SubchainNode.DataNet dataNet;
119
if (set == 0) dataNet = chain.getDataNet();
120
else dataNet = chain.getDataNet2();
122
if (dataNet == null || dataNet.getName().equals("")) {
123
// pad list with correct number of null entries
124
for (int i=0; i<chain.getLength(); i++)
129
MyTreeNode [] hier = chain.getParent().getHierarchy();
130
StringBuffer newPath = new StringBuffer();
131
for (int j=0; j<hier.length; j++) {
132
// remove the chip name and the chain name (3), as they are
133
// not part of the spice hierarchy.
135
newPath.append("X"+hier[j].getName()+".");
137
//newPath.append("X"+chain.getName()+".");
139
// special case: if Fake Chain, do not use the name in the
140
// hierarchical path to the dataNet. This is because schematics
141
// that do not have scanChainElements must refer to data nets
142
// in the schematic, which are at a level above where a scanChain.dataNet
144
boolean fakeChain = false;
145
if (chain.getParentChain().getOpcode().equals("fakeChain")) {
146
// this is a fake chain
150
Name netName = Name.findName(dataNet.getName());
152
for (int j=0; j<netName.busWidth(); j++) {
153
String net = netName.subname(j).toString();
154
// create hierarchical spice net name
155
SubchainNode.DataNet singleNet = new SubchainNode.DataNet(newPath.toString() + net,
156
dataNet.isReadable(), dataNet.isWriteable(), dataNet.isInverted());
158
//System.out.println("DataNet added: "+singleNet);
161
// chain may be bussed, bussed name should match length of chain
162
Name dataName = Name.findName(chain.getName());
163
for (int i=0; i<dataName.busWidth(); i++) {
164
netName = Name.findName(dataNet.getName());
165
for (int j=0; j<netName.busWidth(); j++) {
166
String net = "x" + dataName.subname(i).toString() + "." + netName.subname(j).toString();
167
// create hierarchical spice net name
168
SubchainNode.DataNet singleNet = new SubchainNode.DataNet(newPath.toString() + net,
169
dataNet.isReadable(), dataNet.isWriteable(), dataNet.isInverted());
171
//System.out.println("DataNet added: "+singleNet);
176
if (list.size() != chain.getLength()) {
177
System.out.println("Error: data net list of size "+list.size()+" does not match length of chain "+chain.getName()+" of length "+chain.getLength());
179
for (int i=0; i<chain.getLength(); i++)
185
// this just contains more sub nodes
186
List list = new ArrayList();
187
for (int i=0; i<chain.getChildCount(); i++) {
188
SubchainNode subnode = (SubchainNode)chain.getChildAt(i);
189
list.addAll(getDataNets(subnode, set));
197
* Check that the bits in the chain have been applied to the dataNets for the
198
* scan chain. This only applies for scan bits that have their "dataNet" or
199
* "dataNet2" property in the XML file.
200
* @param chain the scan chain
201
* @param set which set of nets to check. Only 0 and 1 currently.
202
* @return true if a discrepancy found, false otherwise.
204
protected boolean checkDataNets(ChainNode chain, int set) {
205
boolean foundDiscrepancy = false;
206
List dataNets = getDataNets(chain, set);
208
for (int i=0; i<dataNets.size(); i++) {
209
SubchainNode.DataNet dataNet = (SubchainNode.DataNet)dataNets.get(i);
210
//System.out.println(i+":\t"+netName);
211
if (dataNet == null) continue; // undefined net
212
if (dataNet.isWriteable()) {
213
// check that data in inbits was written
214
int simState = nm.getNodeState(dataNet.getName());
215
int setState = chain.getInBits().get(i) ? 1 : 0;
216
if (dataNet.isInverted())
217
setState = (setState==1 ? 0 : 1);
218
if (simState != setState) {
219
System.out.println("Error! Attempted to set bit '"+dataNet.getName()+"' to "+setState+" via the scan chain, but its state is "+simState);
220
foundDiscrepancy = true;
223
System.out.println("Checked "+dataNet.getName()+" read "+simState+": ok");
228
return foundDiscrepancy;
232
* Read directly from the data bits the scan chain controls, rather than
233
* applying "read" and scanning out the data. This is much faster than
235
* @param chain the scan chain
236
* @return a BitVector of the bits read directly out
238
protected BitVector readDirect(ChainNode chain) {
239
List dataNets = getDataNets(chain, 0);
240
List dataNets2 = getDataNets(chain, 1);
242
BitVector outBits = new BitVector(chain.getOutBits().getNumBits(), "outBits");
244
for (int i=0; i<outBits.getNumBits(); i++) {
245
SubchainNode.DataNet dataNet = (SubchainNode.DataNet)dataNets.get(i);
246
SubchainNode.DataNet dataNet2 = (SubchainNode.DataNet)dataNets2.get(i);
248
int state = readDirect(dataNet);
249
int state2 = readDirect(dataNet2);
251
if (state >=0 && state2 >= 0) {
252
// both were read and are valid, check that they match
253
if (state != state2) {
254
System.out.println("Error! Inconsistency reading directly from scan chain data bit "+i+
255
" of chain '"+chain.getName()+"', "+dataNet.getName()+" is "+state+" and "+
256
dataNet2.getName()+" is "+state2);
260
state = state2; // state holds any valid state
263
// nothing valid read, set it to whatever was shifted in
264
state = chain.getInBits().get(i) ? 1 : 0;
265
if (state == -2) bitsRead++; // bit was read, just in undefined state
269
outBits.set(i, state==1 ? true : false);
272
System.out.println("Info: Read directly "+bitsRead+" bits from chain '"+chain.getName()+
273
"' of length "+chain.getOutBits().getNumBits()+
274
" bits (others unchanged).");
279
* Read directly from a scan chain data output
280
* @param dataNet the data net to read from
281
* @return the value read. 0 or 1 valid values, -1 on error
283
private int readDirect(SubchainNode.DataNet dataNet) {
284
if (dataNet == null) return -1;
285
if (!dataNet.isReadable()) return -1;
287
int state = nm.getNodeState(dataNet.getName());
288
if (DEBUG) System.out.println("Read directly "+(dataNet.isInverted()?"(inverted)":"")+" from net "+dataNet.getName()+": "+state);
289
if (state == -2) System.out.println("Warning, read intermediate (undefined) voltage state from net "+dataNet.getName());
290
if (state < 0) return state;
291
if (dataNet.isInverted()) state = state==1 ? 0 : 1;
296
* Write scan chain data directly to the data bits, rather than
297
* scanning them in and then applying "write". This should be much
298
* faster than scanning them in.
299
* @param chain the scan chain
301
protected void writeDirect(ChainNode chain) {
302
List dataNets = getDataNets(chain, 0);
303
List dataNets2 = getDataNets(chain, 1);
305
int dataNetsWritten = 0;
306
int dataNet2sWritten = 0;
307
for (int i=0; i<chain.getInBits().getNumBits(); i++) {
308
int state = chain.getInBits().get(i) ? 1 : 0;
309
SubchainNode.DataNet dataNet = (SubchainNode.DataNet)dataNets.get(i);
310
SubchainNode.DataNet dataNet2 = (SubchainNode.DataNet)dataNets2.get(i);
311
if (writeDirect(dataNet, state)) dataNetsWritten++;
312
if (writeDirect(dataNet2, state)) dataNet2sWritten++;
314
// apply write (above writes)
316
// release writes, unless it is a fake chain control
317
if (!chain.getOpcode().equals("fakeChain")) {
318
nm.releaseNodes(getNames(dataNets));
319
nm.releaseNodes(getNames(dataNets2));
322
System.out.println("Info: Wrote directly "+dataNetsWritten+" bits and "+
323
dataNet2sWritten+" secondary bits from scan chain '"+chain.getName()+ "' of length "+
324
chain.getInBits().getNumBits()+" bits.");
328
* Write directly to a scan chain data output
329
* @param dataNet the data net to write to
330
* @param state the state to write (0 or 1)
331
* @return true if written, false if not
333
private boolean writeDirect(SubchainNode.DataNet dataNet, int state) {
334
if (dataNet == null) return false;
335
if (!dataNet.isWriteable()) return false;
336
int setState = state;
337
if (dataNet.isInverted()) state = (state==1) ? 0 : 1;
338
nm.setNodeState(dataNet.getName(), setState);
339
if (DEBUG) System.out.println("Wrote directly "+state+" to net "+dataNet.getName());
343
private static List getNames(List dataNets) {
344
List names = new ArrayList();
345
for (int i=0; i<dataNets.size(); i++) {
346
SubchainNode.DataNet dataNet = (SubchainNode.DataNet)dataNets.get(i);
347
if (dataNet == null) continue;
348
names.add(dataNet.getName());