iverilog/design_dump.cc

646 lines
15 KiB
C++
Raw Normal View History

1998-11-04 00:28:49 +01:00
/*
* Copyright (c) 1998 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
* General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT)
1999-04-25 02:44:10 +02:00
#ident "$Id: design_dump.cc,v 1.18 1999/04/25 00:44:10 steve Exp $"
1998-11-04 00:28:49 +01:00
#endif
/*
* This file contains all the dump methods of the netlist classes.
*/
# include <typeinfo>
# include <iostream>
# include <iomanip>
# include "netlist.h"
static ostream& operator<< (ostream&o, NetBlock::Type t)
{
switch (t) {
case NetBlock::SEQU:
o << "begin";
break;
case NetBlock::PARA:
o << "fork";
break;
}
return o;
}
/* Dump a net. This can be a wire or register. */
void NetNet::dump_net(ostream&o, unsigned ind) const
{
o << setw(ind) << "" << type() << ": " << name() << "[" <<
pin_count() << "]";
if (local_flag_)
o << " (local)";
o << " #(" << delay1() << "," << delay2() << "," << delay3() <<
") init=";
for (unsigned idx = pin_count() ; idx > 0 ; idx -= 1)
o << ivalue_[idx-1];
o << endl;
dump_obj_attr(o, ind+4);
1998-11-04 00:28:49 +01:00
}
void NetMemory::dump(ostream&o, unsigned ind) const
{
o << setw(ind) << "" << name_ << "[" << width_ << "] " <<
"[" << idxh_ << ":" << idxl_ << "]" << endl;
}
1998-11-04 00:28:49 +01:00
/* Dump a NetNode and its pins. Dump what I know about the netnode on
the first line, then list all the pins, with the name of the
connected signal. */
void NetNode::dump_node(ostream&o, unsigned ind) const
{
o << setw(ind) << "" << "node: ";
o << typeid(*this).name() << " #(" << delay1()
<< "," << delay2() << "," << delay3() << ") " << name()
<< endl;
dump_node_pins(o, ind+4);
dump_obj_attr(o, ind+4);
1998-11-04 00:28:49 +01:00
}
/* This is the generic dumping of all the signals connected to each
pin of the object. The "this" object is not printed, only the
signals connected to this. */
void NetObj::dump_node_pins(ostream&o, unsigned ind) const
{
for (unsigned idx = 0 ; idx < pin_count() ; idx += 1) {
o << setw(ind) << "" << idx;
switch (pin(idx).get_dir()) {
case Link::PASSIVE:
o << " p";
break;
case Link::INPUT:
o << " I";
break;
case Link::OUTPUT:
o << " O";
break;
}
o << ":";
1998-11-04 00:28:49 +01:00
unsigned cpin;
const NetObj*cur;
for (pin(idx).next_link(cur, cpin)
; (cur != this) || (cpin != idx)
; cur->pin(cpin).next_link(cur, cpin)) {
const NetNet*sig = dynamic_cast<const NetNet*>(cur);
if (sig) o << " " << sig->name() << "[" << cpin << "]";
}
o << endl;
}
}
void NetObj::dump_obj_attr(ostream&o, unsigned ind) const
{
for (map<string,string>::const_iterator idx = attributes_.begin()
; idx != attributes_.end()
; idx ++) {
o << setw(ind) << "" << (*idx).first << " = \"" <<
(*idx).second << "\"" << endl;
}
}
1998-11-04 00:28:49 +01:00
void NetAssign::dump_node(ostream&o, unsigned ind) const
{
o << setw(ind) << "" << "Procedural assign: " << *rval_.ref() << endl;
1998-11-04 00:28:49 +01:00
dump_node_pins(o, ind+4);
}
void NetBUFZ::dump_node(ostream&o, unsigned ind) const
{
o << setw(ind) << "" << "BUFZ: " << name() << endl;
dump_node_pins(o, ind+4);
}
void NetConst::dump_node(ostream&o, unsigned ind) const
{
o << setw(ind) << "" << "constant " << value_ << ": " << name() << endl;
dump_node_pins(o, ind+4);
}
1998-11-04 00:28:49 +01:00
void NetLogic::dump_node(ostream&o, unsigned ind) const
{
o << setw(ind) << "" << "logic: ";
switch (type_) {
case AND:
o << "and";
break;
case BUF:
o << "buf";
break;
1999-02-15 03:06:15 +01:00
case BUFIF0:
o << "bufif0";
break;
case BUFIF1:
o << "bufif1";
break;
1998-11-04 00:28:49 +01:00
case NAND:
o << "nand";
break;
case NOR:
o << "nor";
break;
case NOT:
o << "not";
break;
case OR:
o << "or";
break;
case XNOR:
o << "xnor";
break;
1998-11-04 00:28:49 +01:00
case XOR:
o << "xor";
break;
}
o << " #(" << delay1()
<< "," << delay2() << "," << delay3() << ") " << name()
<< endl;
dump_node_pins(o, ind+4);
dump_obj_attr(o, ind+4);
}
void NetUDP::dump_sequ_(ostream&o, unsigned ind) const
{
string tmp = "";
for (unsigned idx = 0 ; idx < ind ; idx += 1)
tmp += " ";
o << tmp << "Sequential UDP" << " #(" << delay1() <<
"," << delay2() << "," << delay3() << ") " << name() <<
endl;
for (FSM_::const_iterator ent = fsm_.begin()
; ent != fsm_.end() ; ent++) {
o << setw(ind+6) << "" << (*ent).first << " -->";
state_t_*st = (*ent).second;
assert((*ent).first[0] == st->out);
for (unsigned idx = 1 ; idx < pin_count() ; idx += 1) {
string tmp = (*ent).first;
if (st->pins[idx].zer) {
tmp[0] = st->pins[idx].zer->out;
tmp[idx] = '0';
o << " " << tmp;
}
if (st->pins[idx].one) {
tmp[0] = st->pins[idx].one->out;
tmp[idx] = '1';
o << " " << tmp;
}
if (st->pins[idx].xxx) {
tmp[0] = st->pins[idx].xxx->out;
tmp[idx] = 'x';
o << " " << tmp;
}
}
o << endl;
}
o << setw(ind+6) << "" << "initial value == " << init_ << endl;
dump_node_pins(o, ind+4);
dump_obj_attr(o, ind+4);
}
void NetUDP::dump_comb_(ostream&o, unsigned ind) const
{
o << setw(ind) << "" << "Combinational UDP: ";
o << " #(" << delay1() << "," << delay2() << "," << delay3() <<
") " << name() << endl;
dump_node_pins(o, ind+4);
dump_obj_attr(o, ind+4);
1998-11-04 00:28:49 +01:00
}
void NetUDP::dump_node(ostream&o, unsigned ind) const
{
if (sequential_)
dump_sequ_(o, ind);
else
dump_comb_(o, ind);
}
1998-11-04 00:28:49 +01:00
void NetPEvent::dump_node(ostream&o, unsigned ind) const
{
o << setw(ind) << "" << "event: ";
switch (edge_) {
case ANYEDGE:
break;
case POSEDGE:
o << "posedge ";
break;
case NEGEDGE:
o << "negedge ";
break;
case POSITIVE:
o << "positive ";
break;
1998-11-04 00:28:49 +01:00
}
o << name() << endl;
dump_node_pins(o, ind+4);
}
void NetProcTop::dump(ostream&o, unsigned ind) const
{
switch (type_) {
case NetProcTop::KINITIAL:
o << "initial /* " << get_line() << " */" << endl;
1998-11-04 00:28:49 +01:00
break;
case NetProcTop::KALWAYS:
o << "always /* " << get_line() << " */" << endl;
1998-11-04 00:28:49 +01:00
break;
}
statement_->dump(o, ind+2);
}
/* Dump an assignment statement */
void NetAssign::dump(ostream&o, unsigned ind) const
{
o << setw(ind) << "";
NetNet*sig;
unsigned msb, lsb;
find_lval_range(sig, msb, lsb);
o << sig->name() << "[" << msb;
if (pin_count() > 1)
o << ":" << lsb;
o << "] = ";
1998-11-04 00:28:49 +01:00
rval_->dump(o);
o << ";" << endl;
}
/* Dump a block statement */
void NetBlock::dump(ostream&o, unsigned ind) const
{
o << setw(ind) << "" << type_ << endl;
if (last_) {
const NetProc*cur = last_;
do {
cur = cur->next_;
cur->dump(o, ind+4);
} while (cur != last_);
}
o << setw(ind) << "" << "end" << endl;
}
void NetCase::dump(ostream&o, unsigned ind) const
{
o << setw(ind) << "" << "case (" << *expr_.ref() << ")" << endl;
for (unsigned idx = 0 ; idx < nitems_ ; idx += 1) {
o << setw(ind+2) << "";
if (items_[idx].guard.ref())
o << *items_[idx].guard.ref() << ":";
else
o << "default:";
if (items_[idx].statement) {
o << endl;
items_[idx].statement->dump(o, ind+6);
} else {
o << " ;" << endl;
}
}
o << setw(ind) << "" << "endcase" << endl;
}
void NetCondit::dump(ostream&o, unsigned ind) const
{
o << setw(ind) << "" << "if (";
expr_->dump(o);
o << ")" << endl;
1999-02-15 03:06:15 +01:00
if (if_) if_->dump(o, ind+4);
else o << setw(ind+4) << "" << "/* empty */ ;" << endl;
if (else_) {
o << setw(ind) << "" << "else" << endl;
else_->dump(o, ind+4);
}
}
1998-11-04 00:28:49 +01:00
void NetPDelay::dump(ostream&o, unsigned ind) const
{
o << setw(ind) << "" << "#" << delay_ << endl;
statement_->dump(o, ind+2);
}
void NetPEvent::dump(ostream&o, unsigned ind) const
{
o << setw(ind) << "" ;
1998-11-04 00:28:49 +01:00
switch (edge_) {
case NEGEDGE:
o << "@" << "(negedge " << name() << ")";
1998-11-04 00:28:49 +01:00
break;
case POSEDGE:
o << "@" << "(posedge " << name() << ")";
1998-11-04 00:28:49 +01:00
break;
case ANYEDGE:
o << "@" << name();
break;
case POSITIVE:
o << "wait (" << name() << ")";
1998-11-04 00:28:49 +01:00
break;
}
if (statement_) {
o << endl;
statement_->dump(o, ind+2);
} else {
o << " /* noop */;" << endl;
}
1998-11-04 00:28:49 +01:00
}
void NetTask::dump(ostream&o, unsigned ind) const
{
o << setw(ind) << "" << name_;
if (nparms_ > 0) {
o << "(";
if (parms_[0].ref())
1998-11-04 00:28:49 +01:00
parms_[0]->dump(o);
for (unsigned idx = 1 ; idx < nparms_ ; idx += 1) {
o << ", ";
if (parms_[idx].ref())
1998-11-04 00:28:49 +01:00
parms_[idx]->dump(o);
}
o << ")";
}
o << ";" << endl;
}
void NetWhile::dump(ostream&o, unsigned ind) const
{
o << setw(ind) << "" << "while (" << *cond_.ref() << ")" << endl;
proc_->dump(o, ind+3);
}
1998-11-04 00:28:49 +01:00
/* Dump a statement type that someone didn't write a dump for. */
void NetProc::dump(ostream&o, unsigned ind) const
{
o << setw(ind) << "" << "// " << typeid(*this).name() << endl;
}
/* Dump an expression that noone wrote a dump method for. */
void NetExpr::dump(ostream&o) const
{
o << "(?)";
}
void NetEBinary::dump(ostream&o) const
{
o << "(";
left_->dump(o);
o << ")";
switch (op_) {
default:
o << op_;
break;
case 'a':
o << "&&";
break;
case 'e':
o << "==";
break;
case 'n':
o << "!=";
break;
case 'o':
o << "||";
break;
}
o << "(";
right_->dump(o);
o << ")";
}
1998-11-04 00:28:49 +01:00
void NetEConst::dump(ostream&o) const
{
if (value_.is_string())
o << "\"" << value_.as_string() << "\"";
else
o << value_;
}
void NetEIdent::dump(ostream&o) const
{
o << name_;
}
void NetESignal::dump(ostream&o) const
{
o << name();
}
1999-04-25 02:44:10 +02:00
void NetESubSignal::dump(ostream&o) const
{
sig_->dump(o);
o << "[";
idx_->dump(o);
o << "]";
}
void NetEMemory::dump(ostream&o) const
{
o << mem_->name() << "[";
idx_->dump(o);
o << "]";
}
void NetESignal::dump_node(ostream&o, unsigned ind) const
{
o << setw(ind) << "" << "Expression Node: " << name() << endl;
dump_node_pins(o, ind+4);
}
1998-11-04 00:28:49 +01:00
void NetEUnary::dump(ostream&o) const
{
o << op_ << "(";
expr_->dump(o);
o << ")";
}
void Design::dump(ostream&o) const
{
1999-02-21 18:01:57 +01:00
o << "ELABORATED PARAMETERS:" << endl;
{
map<string,NetExpr::REF>::const_iterator pp;
1999-02-21 18:01:57 +01:00
for (pp = parameters_.begin()
; pp != parameters_.end() ; pp ++) {
o << " " << (*pp).first << " = " <<
*(*pp).second.ref() << ";" << endl;
1999-02-21 18:01:57 +01:00
}
}
1998-11-04 00:28:49 +01:00
o << "ELABORATED SIGNALS:" << endl;
// Dump the signals,
{
NetNet*cur = signals_->sig_next_;
do {
cur->dump_net(o, 0);
cur = cur->sig_next_;
} while (cur != signals_->sig_next_);
}
o << "ELABORATED MEMORIES:" << endl;
{
map<string,NetMemory*>::const_iterator pp;
for (pp = memories_.begin()
; pp != memories_.end() ; pp ++) {
(*pp).second->dump(o, 0);
}
}
1998-11-04 00:28:49 +01:00
o << "ELABORATED NODES:" << endl;
// dump the nodes,
{
NetNode*cur = nodes_->node_next_;
do {
cur->dump_node(o, 0);
cur = cur->node_next_;
} while (cur != nodes_->node_next_);
}
o << "ELABORATED PROCESSES:" << endl;
// Dump the processes.
for (const NetProcTop*idx = procs_ ; idx ; idx = idx->next_)
idx->dump(o, 0);
}
/*
* $Log: design_dump.cc,v $
1999-04-25 02:44:10 +02:00
* Revision 1.18 1999/04/25 00:44:10 steve
* Core handles subsignal expressions.
*
* Revision 1.17 1999/04/19 01:59:36 steve
* Add memories to the parse and elaboration phases.
*
* Revision 1.16 1999/03/15 02:43:32 steve
* Support more operators, especially logical.
*
* Revision 1.15 1999/03/01 03:27:53 steve
* Prevent the duplicate allocation of ESignal objects.
*
1999-02-21 18:01:57 +01:00
* Revision 1.14 1999/02/21 17:01:57 steve
* Add support for module parameters.
*
1999-02-15 03:06:15 +01:00
* Revision 1.13 1999/02/15 02:06:15 steve
* Elaborate gate ranges.
*
* Revision 1.12 1999/02/08 02:49:56 steve
* Turn the NetESignal into a NetNode so
* that it can connect to the netlist.
* Implement the case statement.
* Convince t-vvm to output code for
* the case statement.
*
* Revision 1.11 1999/02/03 04:20:11 steve
* Parse and elaborate the Verilog CASE statement.
*
* Revision 1.10 1999/02/01 00:26:48 steve
* Carry some line info to the netlist,
* Dump line numbers for processes.
* Elaborate prints errors about port vector
* width mismatch
* Emit better handles null statements.
*
* Revision 1.9 1998/12/20 02:05:41 steve
* Function to calculate wire initial value.
*
* Revision 1.8 1998/12/14 02:01:34 steve
* Fully elaborate Sequential UDP behavior.
*
* Revision 1.7 1998/12/07 04:53:17 steve
* Generate OBUF or IBUF attributes (and the gates
* to garry them) where a wire is a pad. This involved
* figuring out enough of the netlist to know when such
* was needed, and to generate new gates and signales
* to handle what's missing.
*
* Revision 1.6 1998/12/02 04:37:13 steve
* Add the nobufz function to eliminate bufz objects,
* Object links are marked with direction,
* constant propagation is more careful will wide links,
* Signal folding is aware of attributes, and
* the XNF target can dump UDP objects based on LCA
* attributes.
*
* Revision 1.5 1998/12/01 00:42:13 steve
* Elaborate UDP devices,
* Support UDP type attributes, and
* pass those attributes to nodes that
* are instantiated by elaboration,
* Put modules into a map instead of
* a simple list.
*
* Revision 1.4 1998/11/23 00:20:22 steve
* NetAssign handles lvalues as pin links
* instead of a signal pointer,
* Wire attributes added,
* Ability to parse UDP descriptions added,
* XNF generates EXT records for signals with
* the PAD attribute.
*
* Revision 1.3 1998/11/09 18:55:34 steve
* Add procedural while loops,
* Parse procedural for loops,
* Add procedural wait statements,
* Add constant nodes,
* Add XNOR logic gate,
* Make vvm output look a bit prettier.
*
* Revision 1.2 1998/11/07 17:05:05 steve
* Handle procedural conditional, and some
* of the conditional expressions.
*
* Elaborate signals and identifiers differently,
* allowing the netlist to hold signal information.
*
1998-11-04 00:28:49 +01:00
* Revision 1.1 1998/11/03 23:28:56 steve
* Introduce verilog to CVS.
*
*/