/* -*- tab-width: 4 -*- * * Electric(tm) VLSI Design System * * File: VerilogOut.java * Input/output tool: reader for Verilog output (.v) * Written by Steven M. Rubin, Sun Microsystems. * * Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved. * * Electric(tm) is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * Electric(tm) is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Electric(tm); see the file COPYING. If not, write to * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, * Boston, Mass 02111-1307, USA. */ package com.sun.electric.tool.io.input.verilog; import com.sun.electric.database.hierarchy.Cell; import com.sun.electric.tool.io.input.Input; import com.sun.electric.tool.simulation.BusSample; import com.sun.electric.tool.simulation.DigitalSample; import com.sun.electric.tool.simulation.MutableSignal; import com.sun.electric.tool.simulation.Signal; import com.sun.electric.tool.simulation.SignalCollection; import com.sun.electric.tool.simulation.Stimuli; import com.sun.electric.tool.simulation.DigitalSample.Strength; import com.sun.electric.tool.simulation.DigitalSample.Value; import com.sun.electric.util.TextUtils; import java.io.IOException; import java.net.URL; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; /** * Class for reading and displaying waveforms from Verilog output. * These are contained in .v files. */ public class VerilogOut extends Input<Stimuli> { public VerilogOut() {} /** * Method to read an Verilog output file. */ protected Stimuli processInput(URL fileURL, Cell cell, Stimuli sd) throws IOException { sd.setNetDelimiter(" "); // open the file if (openTextInput(fileURL)) return sd; // show progress reading .dump file startProgressDialog("Verilog output", fileURL.getFile()); // read the actual signal data from the .dump file readVerilogFile(cell, sd); // stop progress dialog, close the file stopProgressDialog(); closeInput(); return sd; } private void readVerilogFile(Cell cell, Stimuli sd) throws IOException { SignalCollection sc = Stimuli.newSignalCollection(sd, "SIGNALS"); Map<String,Signal<DigitalSample>[]> busMembers = new HashMap<String,Signal<DigitalSample>[]>(); double timeScale = 1.0; String currentScope = ""; int curLevel = 0; int numSignals = 0; Map<String,Object> symbolTable = new HashMap<String,Object>(); List<Signal<?>> curArray = null; for(;;) { String keyword = getNextKeyword(); if (keyword == null) break; // ignore "$date", "$version" or "$timescale" if (keyword.equals("$date") || keyword.equals("$version")) { parseToEnd(); continue; } if (keyword.equals("$timescale")) { String units = getNextKeyword(); timeScale = TextUtils.atof(units); if (units.endsWith("ms")) timeScale /= 1000.0; else if (units.endsWith("us")) timeScale /= 1000000.0; else if (units.endsWith("ns")) timeScale /= 1000000000.0; else if (units.endsWith("ps")) timeScale /= 1000000000000.0; else if (units.endsWith("fs")) timeScale /= 1000000000000000.0; parseToEnd(); continue; } if (keyword.equals("$scope")) { String scope = getNextKeyword(); if (scope == null) break; if (scope.equals("module") || scope.equals("task") || scope.equals("function")) { // scan for arrays // cleanUpScope(curArray, an); sd.makeBusSignals(curArray, sc); curArray = new ArrayList<Signal<?>>(); String scopeName = getNextKeyword(); if (scopeName == null) break; if (currentScope.length() > 0) currentScope += "."; currentScope += scopeName; curLevel++; } parseToEnd(); continue; } if (keyword.equals("$upscope")) { if (curLevel <= 0 || currentScope.length() == 0) { System.out.println("Unbalanced $upscope on line " + lineReader.getLineNumber()); continue; } // scan for arrays // cleanUpScope(curArray, an); sd.makeBusSignals(curArray, sc); curArray = new ArrayList<Signal<?>>(); int dotPos = currentScope.lastIndexOf('.'); if (dotPos >= 0) { currentScope = currentScope.substring(0, dotPos); curLevel--; } parseToEnd(); continue; } if (keyword.equals("$var")) { String varName = getNextKeyword(); if (varName == null) break; if (varName.equals("wire") || varName.equals("reg") || varName.equals("supply0") || varName.equals("supply1") || varName.equals("parameter") || varName.equals("trireg") || varName.equals("in") || varName.equals("out") || varName.equals("inout")) { // get the bus width String widthText = getNextKeyword(); if (widthText == null) break; int width = TextUtils.atoi(widthText); // get the symbol name for this signal String symbol = getNextKeyword(); if (symbol == null) break; // get the signal name String signalName = getNextKeyword(); if (signalName == null) break; // see if there is an index String index = getNextKeyword(); if (index == null) break; if (index.equals("$end")) index = ""; else { parseToEnd(); } numSignals++; Signal<?> sig = null; if (width <= 1) { sig = DigitalSample.createSignal(sc, sd, signalName + index, currentScope); if (index.length() > 0) curArray.add(sig); // put it in the symbol table addSignalToHashMap(sig, symbol, symbolTable); } else { Signal<DigitalSample>[] subsigs = (Signal<DigitalSample>[])new Signal[width]; for(int i=0; i<width; i++) { subsigs[i] = DigitalSample.createSignal(sc, sd, signalName + "[" + i + "]", currentScope); } sig = BusSample.createSignal(sc, sd, signalName + "[0:" + (width-1) + "]", currentScope, true, subsigs); // put it in the bus symbol table busMembers.put(symbol, subsigs); } numSignals++; } continue; } if (keyword.equals("$enddefinitions")) { parseToEnd(); System.out.println("Found " + numSignals + " signal names"); continue; } if (keyword.equals("$dumpvars")) { double curTime = 0.0; for(;;) { String currentLine = getLineAndUpdateProgress(); if (currentLine == null) break; char chr = currentLine.charAt(0); String restOfLine = currentLine.substring(1); if (chr == '0' || chr == '1' || chr == 'x' || chr == 'X' || chr == 'z' || chr == 'Z') { Object entry = symbolTable.get(restOfLine); if (entry == null) { System.out.println("Unknown symbol '" + restOfLine + "' on line " + lineReader.getLineNumber()); continue; } if (entry instanceof List<?>) entry = ((List<Signal<?>>)entry).get(0); Signal<DigitalSample> sig = (Signal<DigitalSample>)entry; // insert the stimuli DigitalSample ds = null; switch (chr) { case '0': ds = DigitalSample.getSample(Value.LOW, Strength.LARGE_CAPACITANCE); break; case '1': ds = DigitalSample.getSample(Value.HIGH, Strength.LARGE_CAPACITANCE); break; case 'X': case 'x': ds = DigitalSample.getSample(Value.X, Strength.LARGE_CAPACITANCE); break; case 'Z': case 'z': ds = DigitalSample.getSample(Value.Z, Strength.HIGH_IMPEDANCE); break; } ((MutableSignal<DigitalSample>)sig).addSample(curTime, ds); continue; } if (chr == '$') { if (restOfLine.equals("end")) continue; if (restOfLine.equals("dumpon")) continue; if (restOfLine.equals("dumpoff")) continue; if (restOfLine.equals("dumpall")) continue; System.out.println("Unknown directive on line " + lineReader.getLineNumber() + ": " + currentLine); continue; } if (chr == '#') { curTime = TextUtils.atof(restOfLine) * timeScale; continue; } if (chr == 'b') { int spacePos = restOfLine.indexOf(' '); if (spacePos < 0) { System.out.println("Bus has missing signal name on line " + lineReader.getLineNumber() + ": " + currentLine); continue; } String symName = restOfLine.substring(spacePos+1); Signal<DigitalSample>[] members = busMembers.get(symName); for(int i=0; i<members.length; i++) { Signal<DigitalSample> subSig = members[i]; char bit = restOfLine.charAt(i++); DigitalSample ds = null; switch (bit) { case '0': ds = DigitalSample.getSample(Value.LOW, Strength.LARGE_CAPACITANCE); break; case '1': ds = DigitalSample.getSample(Value.HIGH, Strength.LARGE_CAPACITANCE); break; case 'X': case 'x': ds = DigitalSample.getSample(Value.X, Strength.LARGE_CAPACITANCE); break; case 'Z': case 'z': ds = DigitalSample.getSample(Value.Z, Strength.HIGH_IMPEDANCE); break; } ((MutableSignal<DigitalSample>)subSig).addSample(curTime, ds); } continue; } System.out.println("Unknown stimulus on line " + lineReader.getLineNumber() + ": " + currentLine); } } continue; } // remove singular top-level signal name (this code also occurs in HSpiceOut.readTRDCACFile) /* String singularPrefix = null; for(Signal sSig : an.getSignals()) { String context = sSig.getSignalContext(); if (context == null) { singularPrefix = null; break; } int dotPos = context.indexOf('.'); if (dotPos >= 0) context = context.substring(0, dotPos); if (singularPrefix == null) singularPrefix = context; else { if (!singularPrefix.equals(context)) { singularPrefix = null; break; } } } if (singularPrefix != null) { int len = singularPrefix.length(); for(Signal sSig : an.getSignals()) { String context = sSig.getSignalContext(); if (context == null || context.length() <= len) sSig.setSignalContext(null); else { sSig.setSignalContext(context.substring(len+1)); } } } */ } private void addSignalToHashMap(Signal<?> sig, String symbol, Map<String,Object> symbolTable) { Object entry = symbolTable.get(symbol); if (entry == null) { symbolTable.put(symbol, sig); } else if (entry instanceof Signal<?>) { List<Signal<?>> manySigs = new ArrayList<Signal<?>>(); manySigs.add((Signal<?>)entry); manySigs.add(sig); symbolTable.put(symbol, manySigs); } else if (entry instanceof List<?>) { ((List<Signal<?>>)entry).add(sig); } } private void parseToEnd() throws IOException { for(;;) { String keyword = getNextKeyword(); if (keyword == null || keyword.equals("$end")) break; } } private String lastLine = null; private int linePos; private int lineLen; private String getNextKeyword() throws IOException { String keyword = null; for(;;) { if (lastLine == null) { lastLine = getLineAndUpdateProgress(); if (lastLine == null) break; lineLen = lastLine.length(); linePos = 0; } if (linePos < lineLen) { char ch = lastLine.charAt(linePos); if (ch == ' ' || ch == '\t') { linePos++; } else { int startOfKeyword = linePos; for(linePos++; linePos < lineLen; linePos++) { if (lastLine.charAt(linePos) == ' ') break; } keyword = lastLine.substring(startOfKeyword, linePos); } } if (linePos >= lineLen) lastLine = null; if (keyword != null) break; } return keyword; } }