/* * Copyright (c) 2000 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) && !defined(macintosh) #ident "$Id: elab_sig.cc,v 1.1 2000/05/02 16:27:38 steve Exp $" #endif # include "Module.h" # include "PExpr.h" # include "PGate.h" # include "PWire.h" # include "netlist.h" # include "util.h" bool Module::elaborate_sig(Design*des, NetScope*scope) const { bool flag = true; // Get all the explicitly declared wires of the module and // start the signals list with them. const map&wl = get_wires(); for (map::const_iterator wt = wl.begin() ; wt != wl.end() ; wt ++ ) { (*wt).second->elaborate_sig(des, scope); } // Get all the gates of the module and elaborate them by // connecting them to the signals. The gate may be simple or // complex. What we are looking for is gates that are modules // that can create scopes and signals. const list&gl = get_gates(); for (list::const_iterator gt = gl.begin() ; gt != gl.end() ; gt ++ ) { flag &= (*gt)->elaborate_sig(des, scope); } return flag; } bool PGModule::elaborate_sig_mod_(Design*des, NetScope*scope, Module*rmod) const { // Missing module instance names have already been rejected. assert(get_name() != ""); if (msb_) { cerr << get_line() << ": sorry: Module instantiation arrays " "are not yet supported." << endl; des->errors += 1; return false; } // I know a priori that the elaborate_scope created the scope // already, so just look it up as a child of the current scope. NetScope*my_scope = scope->child(get_name()); assert(my_scope); return rmod->elaborate_sig(des, my_scope); } bool PGate::elaborate_sig(Design*des, NetScope*scope) const { return true; } /* * Elaborate a source wire. The "wire" is the declaration of wires, * registers, ports and memories. The parser has already merged the * multiple properties of a wire (i.e. "input wire") so come the * elaboration this creates an object in the design that represent the * defined item. */ void PWire::elaborate_sig(Design*des, NetScope*scope) const { /* The parser may produce hierarchical names for wires. I here follow the scopes down to the base where I actually want to elaborate the NetNet object. */ string basename = name_; for (;;) { string p = parse_first_name(basename); if (basename == "") { basename = p; break; } scope = scope->child(p); assert(scope); } const string path = scope->name(); NetNet::Type wtype = type_; if (wtype == NetNet::IMPLICIT) wtype = NetNet::WIRE; if (wtype == NetNet::IMPLICIT_REG) wtype = NetNet::REG; unsigned wid = 1; long lsb = 0, msb = 0; if (msb_.count()) { svectormnum (msb_.count()); svectorlnum (msb_.count()); /* There may be multiple declarations of ranges, because the symbol may have its range declared in i.e. input and reg declarations. Calculate *all* the numbers here. I will resolve the values later. */ for (unsigned idx = 0 ; idx < msb_.count() ; idx += 1) { verinum*mval = msb_[idx]->eval_const(des,path); if (mval == 0) { cerr << msb_[idx]->get_line() << ": error: " "Unable to evaluate constant expression ``" << *msb_[idx] << "''." << endl; des->errors += 1; return; } verinum*lval = lsb_[idx]->eval_const(des, path); if (mval == 0) { cerr << lsb_[idx]->get_line() << ": error: " "Unable to evaluate constant expression ``" << *lsb_[idx] << "''." << endl; des->errors += 1; return; } mnum[idx] = mval->as_long(); lnum[idx] = lval->as_long(); delete mval; delete lval; } /* Make sure all the values for msb and lsb match by value. If not, report an error. */ for (unsigned idx = 1 ; idx < msb_.count() ; idx += 1) { if ((mnum[idx] != mnum[0]) || (lnum[idx] != lnum[0])) { cerr << get_line() << ": error: Inconsistent width, " "[" << mnum[idx] << ":" << lnum[idx] << "]" " vs. [" << mnum[0] << ":" << lnum[0] << "]" " for signal ``" << basename << "''" << endl; des->errors += 1; return; } } lsb = lnum[0]; msb = mnum[0]; if (mnum[0] > lnum[0]) wid = mnum[0] - lnum[0] + 1; else wid = lnum[0] - mnum[0] + 1; } if (lidx_ || ridx_) { assert(lidx_ && ridx_); // If the register has indices, then this is a // memory. Create the memory object. verinum*lval = lidx_->eval_const(des, path); assert(lval); verinum*rval = ridx_->eval_const(des, path); assert(rval); long lnum = lval->as_long(); long rnum = rval->as_long(); delete lval; delete rval; NetMemory*sig = new NetMemory(scope, path+"."+basename, wid, lnum, rnum); sig->set_attributes(attributes); } else { NetNet*sig = new NetNet(scope, path + "." +basename, wtype, msb, lsb); sig->set_line(*this); sig->port_type(port_type_); sig->set_attributes(attributes); verinum::V iv = verinum::Vz; if (wtype == NetNet::REG) iv = verinum::Vx; for (unsigned idx = 0 ; idx < wid ; idx += 1) sig->set_ival(idx, iv); } } /* * $Log: elab_sig.cc,v $ * Revision 1.1 2000/05/02 16:27:38 steve * Move signal elaboration to a seperate pass. * */