1998-11-04 00:28:49 +01:00
|
|
|
#ifndef __netlist_H
|
|
|
|
|
#define __netlist_H
|
|
|
|
|
/*
|
2000-02-23 03:56:53 +01:00
|
|
|
* Copyright (c) 1998-2000 Stephen Williams (steve@icarus.com)
|
1998-11-04 00:28:49 +01:00
|
|
|
*
|
|
|
|
|
* 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
|
|
|
|
|
*/
|
2000-02-23 03:56:53 +01:00
|
|
|
#if !defined(WINNT) && !defined(macintosh)
|
2001-01-18 04:16:35 +01:00
|
|
|
#ident "$Id: netlist.h,v 1.195 2001/01/18 03:16:35 steve Exp $"
|
1998-11-04 00:28:49 +01:00
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* The netlist types, as described in this header file, are intended
|
|
|
|
|
* to be the output from elaboration of the source design. The design
|
|
|
|
|
* can be passed around in this form to the various stages and design
|
|
|
|
|
* processors.
|
|
|
|
|
*/
|
|
|
|
|
# include <string>
|
1998-11-18 05:25:22 +01:00
|
|
|
# include <map>
|
1998-11-04 00:28:49 +01:00
|
|
|
# include "verinum.h"
|
1999-02-01 01:26:48 +01:00
|
|
|
# include "LineInfo.h"
|
1999-07-03 04:12:51 +02:00
|
|
|
# include "svector.h"
|
2000-12-04 18:37:03 +01:00
|
|
|
# include "Attrib.h"
|
1998-11-04 00:28:49 +01:00
|
|
|
|
2001-01-16 03:44:17 +01:00
|
|
|
#ifdef HAVE_IOSFWD
|
|
|
|
|
# include <iosfwd>
|
|
|
|
|
#else
|
|
|
|
|
class ostream;
|
|
|
|
|
#endif
|
|
|
|
|
|
1999-05-27 06:13:08 +02:00
|
|
|
class Design;
|
2000-05-07 06:37:55 +02:00
|
|
|
class Link;
|
2000-06-25 21:59:41 +02:00
|
|
|
class Nexus;
|
1998-11-04 00:28:49 +01:00
|
|
|
class NetNode;
|
|
|
|
|
class NetProc;
|
|
|
|
|
class NetProcTop;
|
1999-11-27 20:07:57 +01:00
|
|
|
class NetScope;
|
1998-11-04 00:28:49 +01:00
|
|
|
class NetExpr;
|
1999-09-01 00:38:29 +02:00
|
|
|
class NetESignal;
|
1998-11-04 00:28:49 +01:00
|
|
|
|
|
|
|
|
|
|
|
|
|
struct target;
|
1999-07-18 00:01:13 +02:00
|
|
|
struct functor_t;
|
1998-11-04 00:28:49 +01:00
|
|
|
|
|
|
|
|
/* =========
|
|
|
|
|
* A NetObj is anything that has any kind of behavior in the
|
|
|
|
|
* netlist. Nodes can be gates, registers, etc. and are linked
|
|
|
|
|
* together to form a design web.
|
|
|
|
|
*
|
|
|
|
|
* The web of nodes that makes up a circuit is held together by the
|
|
|
|
|
* Link class. There is a link for each pin. All mutually connected
|
|
|
|
|
* pins form a ring of links.
|
1998-12-02 05:37:13 +01:00
|
|
|
*
|
|
|
|
|
* A link can be INPUT, OUTPUT or PASSIVE. An input never drives the
|
|
|
|
|
* signal, and PASSIVE never receives the value of the signal. Wires
|
|
|
|
|
* are PASSIVE, for example.
|
1999-08-01 18:34:50 +02:00
|
|
|
*
|
|
|
|
|
* A NetObj also has delays specified as rise_time, fall_time and
|
|
|
|
|
* decay_time. The rise and fall time are the times to transition to 1
|
|
|
|
|
* or 0 values. The decay_time is the time needed to decay to a 'bz
|
|
|
|
|
* value, or to decay of the net is a trireg. The exact and precise
|
|
|
|
|
* interpretation of the rise/fall/decay times is typically left to
|
|
|
|
|
* the target to properly interpret.
|
1998-11-04 00:28:49 +01:00
|
|
|
*/
|
|
|
|
|
class NetObj {
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
public:
|
|
|
|
|
explicit NetObj(const string&n, unsigned npins);
|
2000-10-07 01:46:50 +02:00
|
|
|
explicit NetObj(NetScope*s, const string&n, unsigned npins);
|
1998-11-04 00:28:49 +01:00
|
|
|
virtual ~NetObj();
|
|
|
|
|
|
2000-10-07 01:46:50 +02:00
|
|
|
NetScope* scope();
|
|
|
|
|
const NetScope* scope() const;
|
|
|
|
|
|
2000-08-27 17:51:50 +02:00
|
|
|
const char* name() const { return name_; }
|
1998-11-04 00:28:49 +01:00
|
|
|
|
|
|
|
|
unsigned pin_count() const { return npins_; }
|
|
|
|
|
|
1999-08-01 18:34:50 +02:00
|
|
|
unsigned rise_time() const { return delay1_; }
|
|
|
|
|
unsigned fall_time() const { return delay2_; }
|
|
|
|
|
unsigned decay_time() const { return delay3_; }
|
1998-11-04 00:28:49 +01:00
|
|
|
|
1999-08-01 18:34:50 +02:00
|
|
|
void rise_time(unsigned d) { delay1_ = d; }
|
|
|
|
|
void fall_time(unsigned d) { delay2_ = d; }
|
|
|
|
|
void decay_time(unsigned d) { delay3_ = d; }
|
1998-11-04 00:28:49 +01:00
|
|
|
|
1998-11-23 01:20:22 +01:00
|
|
|
void set_attributes(const map<string,string>&);
|
|
|
|
|
string attribute(const string&key) const;
|
1998-12-07 05:53:16 +01:00
|
|
|
void attribute(const string&key, const string&value);
|
1998-11-23 01:20:22 +01:00
|
|
|
|
1998-12-02 05:37:13 +01:00
|
|
|
// Return true if this has all the attributes in that and they
|
|
|
|
|
// all have the same values.
|
|
|
|
|
bool has_compat_attributes(const NetObj&that) const;
|
|
|
|
|
|
2000-12-05 07:29:33 +01:00
|
|
|
unsigned nattr() const;
|
|
|
|
|
const char* attr_key(unsigned) const;
|
|
|
|
|
const char* attr_value(unsigned) const;
|
|
|
|
|
|
1999-09-13 05:10:59 +02:00
|
|
|
Link&pin(unsigned idx);
|
|
|
|
|
const Link&pin(unsigned idx) const;
|
1998-11-04 00:28:49 +01:00
|
|
|
|
|
|
|
|
void dump_node_pins(ostream&, unsigned) const;
|
1998-11-23 01:20:22 +01:00
|
|
|
void dump_obj_attr(ostream&, unsigned) const;
|
1998-11-04 00:28:49 +01:00
|
|
|
|
|
|
|
|
private:
|
2000-10-07 01:46:50 +02:00
|
|
|
NetScope*scope_;
|
2000-08-27 17:51:50 +02:00
|
|
|
char* name_;
|
1998-11-04 00:28:49 +01:00
|
|
|
Link*pins_;
|
|
|
|
|
const unsigned npins_;
|
|
|
|
|
unsigned delay1_;
|
|
|
|
|
unsigned delay2_;
|
|
|
|
|
unsigned delay3_;
|
1998-11-13 07:23:17 +01:00
|
|
|
|
2000-12-04 18:37:03 +01:00
|
|
|
Attrib attributes_;
|
1998-11-04 00:28:49 +01:00
|
|
|
};
|
|
|
|
|
|
2000-05-07 06:37:55 +02:00
|
|
|
class Link {
|
2000-06-25 21:59:41 +02:00
|
|
|
|
2000-05-07 06:37:55 +02:00
|
|
|
friend void connect(Link&, Link&);
|
|
|
|
|
friend class NetObj;
|
2000-06-25 21:59:41 +02:00
|
|
|
friend class Nexus;
|
2000-05-07 06:37:55 +02:00
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
enum DIR { PASSIVE, INPUT, OUTPUT };
|
|
|
|
|
|
|
|
|
|
enum strength_t { HIGHZ, WEAK, PULL, STRONG, SUPPLY };
|
|
|
|
|
|
|
|
|
|
Link();
|
|
|
|
|
~Link();
|
|
|
|
|
|
|
|
|
|
// Manipulate the link direction.
|
|
|
|
|
void set_dir(DIR d);
|
|
|
|
|
DIR get_dir() const;
|
|
|
|
|
|
2000-07-14 08:12:56 +02:00
|
|
|
// A link has a drive strength for 0 and 1 values. The drive0
|
|
|
|
|
// strength is for when the link has the value 0, and drive1
|
|
|
|
|
// strength is for when the link has a value 1.
|
2000-05-07 06:37:55 +02:00
|
|
|
void drive0(strength_t);
|
|
|
|
|
void drive1(strength_t);
|
|
|
|
|
|
|
|
|
|
strength_t drive0() const;
|
|
|
|
|
strength_t drive1() const;
|
|
|
|
|
|
2000-07-14 08:12:56 +02:00
|
|
|
// A link has an initial value that is used by the nexus to
|
|
|
|
|
// figure out its initial value. Normally, only the object
|
|
|
|
|
// that contains the link sets the initial value, and only the
|
|
|
|
|
// attached Nexus gets it. The default link value is Vx.
|
|
|
|
|
void set_init(verinum::V val);
|
|
|
|
|
verinum::V get_init() const;
|
|
|
|
|
|
2000-05-07 06:37:55 +02:00
|
|
|
void cur_link(NetObj*&net, unsigned &pin);
|
2000-06-25 00:55:19 +02:00
|
|
|
void cur_link(const NetObj*&net, unsigned &pin) const;
|
2000-05-07 06:37:55 +02:00
|
|
|
|
2000-06-25 21:59:41 +02:00
|
|
|
// Get a pointer to the nexus that represents all the links
|
|
|
|
|
// connected to me.
|
|
|
|
|
Nexus* nexus();
|
|
|
|
|
const Nexus* nexus()const;
|
|
|
|
|
|
|
|
|
|
// Return a pointer to the next link in the nexus.
|
|
|
|
|
Link* next_nlink();
|
|
|
|
|
const Link* next_nlink() const;
|
2000-05-07 06:37:55 +02:00
|
|
|
|
|
|
|
|
// Remove this link from the set of connected pins. The
|
|
|
|
|
// destructor will automatically do this if needed.
|
|
|
|
|
void unlink();
|
|
|
|
|
|
|
|
|
|
// Return true if this link is connected to anything else.
|
|
|
|
|
bool is_linked() const;
|
|
|
|
|
|
|
|
|
|
// Return true if these pins are connected.
|
|
|
|
|
bool is_linked(const Link&that) const;
|
|
|
|
|
|
2000-05-27 21:33:23 +02:00
|
|
|
// Return true if this is the same pin of the same object of
|
|
|
|
|
// that link.
|
|
|
|
|
bool is_equal(const Link&that) const;
|
2000-05-07 06:37:55 +02:00
|
|
|
|
|
|
|
|
// Return information about the object that this link is
|
|
|
|
|
// a part of.
|
|
|
|
|
const NetObj*get_obj() const;
|
|
|
|
|
NetObj*get_obj();
|
|
|
|
|
unsigned get_pin() const;
|
|
|
|
|
|
2000-07-14 08:12:56 +02:00
|
|
|
// A link of an object (sometimes called a "pin") has a
|
|
|
|
|
// name. It is convenient for the name to have a string and an
|
|
|
|
|
// integer part.
|
2000-05-07 06:37:55 +02:00
|
|
|
void set_name(const string&, unsigned inst =0);
|
|
|
|
|
const string& get_name() const;
|
|
|
|
|
unsigned get_inst() const;
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
// The NetNode manages these. They point back to the
|
|
|
|
|
// NetNode so that following the links can get me here.
|
|
|
|
|
NetObj *node_;
|
|
|
|
|
unsigned pin_;
|
|
|
|
|
|
|
|
|
|
DIR dir_;
|
|
|
|
|
strength_t drive0_, drive1_;
|
2000-07-14 08:12:56 +02:00
|
|
|
verinum::V init_;
|
2000-05-07 06:37:55 +02:00
|
|
|
|
|
|
|
|
// These members name the pin of the link. If the name
|
|
|
|
|
// has width, then the ninst_ member is the index of the
|
|
|
|
|
// pin.
|
|
|
|
|
string name_;
|
|
|
|
|
unsigned inst_;
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
Link *next_;
|
2000-06-25 21:59:41 +02:00
|
|
|
Nexus*nexus_;
|
2000-05-07 06:37:55 +02:00
|
|
|
|
|
|
|
|
private: // not implemented
|
|
|
|
|
Link(const Link&);
|
|
|
|
|
Link& operator= (const Link&);
|
|
|
|
|
};
|
|
|
|
|
|
2000-06-25 21:59:41 +02:00
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* The Nexus represents a collection of links that are joined
|
|
|
|
|
* together. Each link has its own properties, this class holds the
|
|
|
|
|
* properties of the group.
|
|
|
|
|
*
|
|
|
|
|
* The links in a nexus are grouped into a singly linked list, with
|
|
|
|
|
* the nexus pointing to the first Link. Each link in turn points to
|
|
|
|
|
* the next link in the nexus, with the last link pointing to 0.
|
2000-10-07 01:46:50 +02:00
|
|
|
*
|
|
|
|
|
* The t_cookie() is a void* that targets can use to store information
|
|
|
|
|
* in a Nexus. ivl guarantees that the t_cookie will be 0 when the
|
|
|
|
|
* target is invoked.
|
2000-06-25 21:59:41 +02:00
|
|
|
*/
|
|
|
|
|
class Nexus {
|
|
|
|
|
|
|
|
|
|
friend void connect(Link&, Link&);
|
|
|
|
|
friend class Link;
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
explicit Nexus();
|
|
|
|
|
~Nexus();
|
|
|
|
|
|
2000-08-26 02:54:03 +02:00
|
|
|
const char* name() const;
|
2000-07-14 08:12:56 +02:00
|
|
|
verinum::V get_init() const;
|
2000-06-25 21:59:41 +02:00
|
|
|
|
|
|
|
|
Link*first_nlink();
|
|
|
|
|
const Link* first_nlink()const;
|
|
|
|
|
|
2000-10-07 01:46:50 +02:00
|
|
|
void* t_cookie() const;
|
|
|
|
|
void* t_cookie(void*) const;
|
|
|
|
|
|
2000-06-25 21:59:41 +02:00
|
|
|
private:
|
|
|
|
|
Link*list_;
|
|
|
|
|
void unlink(Link*);
|
|
|
|
|
void relink(Link*);
|
|
|
|
|
|
2000-08-26 02:54:03 +02:00
|
|
|
mutable char* name_; /* Cache the calculated name for the Nexus. */
|
2000-10-07 01:46:50 +02:00
|
|
|
mutable void* t_cookie_;
|
2000-08-26 02:54:03 +02:00
|
|
|
|
2000-06-25 21:59:41 +02:00
|
|
|
private: // not implemented
|
|
|
|
|
Nexus(const Nexus&);
|
|
|
|
|
Nexus& operator= (const Nexus&);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
1998-11-04 00:28:49 +01:00
|
|
|
/*
|
|
|
|
|
* A NetNode is a device of some sort, where each pin has a different
|
|
|
|
|
* meaning. (i.e. pin(0) is the output to an and gate.) NetNode
|
|
|
|
|
* objects are listed in the nodes_ of the Design object.
|
|
|
|
|
*/
|
|
|
|
|
class NetNode : public NetObj {
|
|
|
|
|
|
|
|
|
|
public:
|
2000-10-07 21:45:42 +02:00
|
|
|
explicit NetNode(NetScope*s, const string&n, unsigned npins);
|
2000-05-27 21:33:23 +02:00
|
|
|
explicit NetNode(const string&n, unsigned npins);
|
1998-11-04 00:28:49 +01:00
|
|
|
|
|
|
|
|
virtual ~NetNode();
|
|
|
|
|
|
2000-05-27 21:33:23 +02:00
|
|
|
// This method locates the next node that has all its pins
|
|
|
|
|
// connected to the same of my own pins.
|
|
|
|
|
NetNode*next_node();
|
|
|
|
|
|
2000-08-14 06:39:56 +02:00
|
|
|
virtual bool emit_node(struct target_t*) const;
|
1998-11-04 00:28:49 +01:00
|
|
|
virtual void dump_node(ostream&, unsigned) const;
|
|
|
|
|
|
2000-07-16 06:56:07 +02:00
|
|
|
// This is used to scan a modifiable netlist, one node at a time.
|
1999-11-01 03:07:40 +01:00
|
|
|
virtual void functor_node(Design*, functor_t*);
|
|
|
|
|
|
1998-11-04 00:28:49 +01:00
|
|
|
private:
|
|
|
|
|
friend class Design;
|
|
|
|
|
NetNode*node_next_, *node_prev_;
|
|
|
|
|
Design*design_;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* NetNet is a special kind of NetObj that doesn't really do anything,
|
2000-05-02 02:58:11 +02:00
|
|
|
* but carries the properties of the wire/reg/trireg, including its
|
|
|
|
|
* name. A scaler wire is a NetNet with one pin, a vector a wider
|
|
|
|
|
* NetNet. NetNet objects also appear as side effects of synthesis or
|
|
|
|
|
* other abstractions.
|
1998-11-04 00:28:49 +01:00
|
|
|
*
|
2001-01-06 03:29:35 +01:00
|
|
|
* Note that there are no INTEGER types. Express a verilog integer as
|
|
|
|
|
* a ``reg signed'' instead. The parser automatically does this for us.
|
|
|
|
|
*
|
2000-05-02 02:58:11 +02:00
|
|
|
* NetNet objects have a name and exist within a scope, so the
|
|
|
|
|
* constructor takes a pointer to the containing scope. The object
|
|
|
|
|
* automatically adds itself to the scope.
|
|
|
|
|
*
|
|
|
|
|
* NetNet objects are located by searching NetScope objects.
|
2000-07-14 08:12:56 +02:00
|
|
|
*
|
|
|
|
|
* All the pins of a NetNet object are PASSIVE: they do not drive
|
|
|
|
|
* anything and they are not a data sink, per se. The pins follow the
|
|
|
|
|
* values on the nexus.
|
1998-11-04 00:28:49 +01:00
|
|
|
*/
|
1999-06-02 17:38:46 +02:00
|
|
|
class NetNet : public NetObj, public LineInfo {
|
1998-11-04 00:28:49 +01:00
|
|
|
|
|
|
|
|
public:
|
1999-07-24 04:11:19 +02:00
|
|
|
enum Type { IMPLICIT, IMPLICIT_REG, WIRE, TRI, TRI1, SUPPLY0,
|
2001-01-06 07:31:58 +01:00
|
|
|
SUPPLY1, WAND, TRIAND, TRI0, WOR, TRIOR, REG };
|
1998-11-04 00:28:49 +01:00
|
|
|
|
|
|
|
|
enum PortType { NOT_A_PORT, PIMPLICIT, PINPUT, POUTPUT, PINOUT };
|
|
|
|
|
|
1999-11-27 20:07:57 +01:00
|
|
|
explicit NetNet(NetScope*s, const string&n, Type t, unsigned npins =1);
|
1998-11-04 00:28:49 +01:00
|
|
|
|
1999-11-27 20:07:57 +01:00
|
|
|
explicit NetNet(NetScope*s, const string&n, Type t, long ms, long ls);
|
1998-11-04 00:28:49 +01:00
|
|
|
|
|
|
|
|
virtual ~NetNet();
|
|
|
|
|
|
2000-09-24 17:44:44 +02:00
|
|
|
Type type() const;
|
1998-11-04 00:28:49 +01:00
|
|
|
|
2000-09-24 17:44:44 +02:00
|
|
|
PortType port_type() const;
|
|
|
|
|
void port_type(PortType t);
|
1998-11-04 00:28:49 +01:00
|
|
|
|
2000-12-11 01:31:43 +01:00
|
|
|
/* If a NetNet is signed, then its value is to be treated as
|
|
|
|
|
signed. Otherwise, it is unsigned. */
|
|
|
|
|
bool get_signed() const;
|
|
|
|
|
void set_signed(bool);
|
|
|
|
|
|
1999-09-13 05:10:59 +02:00
|
|
|
/* These methods return the msb and lsb indices for the most
|
|
|
|
|
significant and least significant bits. These are signed
|
|
|
|
|
longs, and may be different from pin numbers. For example,
|
|
|
|
|
reg [1:8] has 8 bits, msb==1 and lsb==8. */
|
2000-09-24 17:44:44 +02:00
|
|
|
long msb() const;
|
|
|
|
|
long lsb() const;
|
1998-11-04 00:28:49 +01:00
|
|
|
|
1999-09-13 05:10:59 +02:00
|
|
|
/* This method converts a signed index (the type that might be
|
|
|
|
|
found in the verilog source) to a pin number. It accounts
|
|
|
|
|
for variation in the definition of the reg/wire/whatever. */
|
|
|
|
|
unsigned sb_to_idx(long sb) const;
|
1998-11-04 00:28:49 +01:00
|
|
|
|
|
|
|
|
bool local_flag() const { return local_flag_; }
|
|
|
|
|
void local_flag(bool f) { local_flag_ = f; }
|
|
|
|
|
|
1999-11-29 00:42:02 +01:00
|
|
|
/* NetESignal objects may reference this object. Keep a
|
|
|
|
|
reference count so that I keep track of them. */
|
|
|
|
|
void incr_eref();
|
|
|
|
|
void decr_eref();
|
|
|
|
|
unsigned get_eref() const;
|
|
|
|
|
|
1998-12-20 03:05:41 +01:00
|
|
|
|
1998-11-04 00:28:49 +01:00
|
|
|
virtual void dump_net(ostream&, unsigned) const;
|
|
|
|
|
|
|
|
|
|
private:
|
2000-05-02 02:58:11 +02:00
|
|
|
// The NetScope class uses this for listing signals.
|
|
|
|
|
friend class NetScope;
|
1998-11-04 00:28:49 +01:00
|
|
|
NetNet*sig_next_, *sig_prev_;
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
Type type_;
|
|
|
|
|
PortType port_type_;
|
2000-12-11 01:31:43 +01:00
|
|
|
bool signed_;
|
1998-11-04 00:28:49 +01:00
|
|
|
|
|
|
|
|
long msb_, lsb_;
|
|
|
|
|
|
|
|
|
|
bool local_flag_;
|
1999-11-29 00:42:02 +01:00
|
|
|
unsigned eref_count_;
|
1998-11-04 00:28:49 +01:00
|
|
|
};
|
|
|
|
|
|
1999-09-03 06:28:38 +02:00
|
|
|
/*
|
|
|
|
|
* This class implements the LPM_ADD_SUB component as described in the
|
|
|
|
|
* EDIF LPM Version 2 1 0 standard. It is used as a structural
|
|
|
|
|
* implementation of the + and - operators.
|
|
|
|
|
*/
|
|
|
|
|
class NetAddSub : public NetNode {
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
NetAddSub(const string&n, unsigned width);
|
|
|
|
|
~NetAddSub();
|
|
|
|
|
|
|
|
|
|
// Get the width of the device (that is, the width of the
|
|
|
|
|
// operands and results.)
|
|
|
|
|
unsigned width() const;
|
|
|
|
|
|
2000-05-07 06:37:55 +02:00
|
|
|
Link& pin_Aclr();
|
|
|
|
|
Link& pin_Add_Sub();
|
|
|
|
|
Link& pin_Clock();
|
|
|
|
|
Link& pin_Cin();
|
|
|
|
|
Link& pin_Cout();
|
|
|
|
|
Link& pin_Overflow();
|
1999-09-03 06:28:38 +02:00
|
|
|
|
2000-05-07 06:37:55 +02:00
|
|
|
Link& pin_DataA(unsigned idx);
|
|
|
|
|
Link& pin_DataB(unsigned idx);
|
|
|
|
|
Link& pin_Result(unsigned idx);
|
1999-09-03 06:28:38 +02:00
|
|
|
|
2000-05-07 06:37:55 +02:00
|
|
|
const Link& pin_Cout() const;
|
|
|
|
|
const Link& pin_DataA(unsigned idx) const;
|
|
|
|
|
const Link& pin_DataB(unsigned idx) const;
|
|
|
|
|
const Link& pin_Result(unsigned idx) const;
|
1999-10-31 05:11:27 +01:00
|
|
|
|
1999-09-03 06:28:38 +02:00
|
|
|
virtual void dump_node(ostream&, unsigned ind) const;
|
2000-08-14 06:39:56 +02:00
|
|
|
virtual bool emit_node(struct target_t*) const;
|
1999-12-30 05:19:12 +01:00
|
|
|
virtual void functor_node(Design*des, functor_t*fun);
|
1999-09-03 06:28:38 +02:00
|
|
|
};
|
|
|
|
|
|
1999-11-14 21:24:28 +01:00
|
|
|
/*
|
|
|
|
|
* This type represents the LPM_CLSHIFT device.
|
|
|
|
|
*/
|
|
|
|
|
class NetCLShift : public NetNode {
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
NetCLShift(const string&n, unsigned width, unsigned width_dist);
|
|
|
|
|
~NetCLShift();
|
|
|
|
|
|
|
|
|
|
unsigned width() const;
|
|
|
|
|
unsigned width_dist() const;
|
|
|
|
|
|
2000-05-07 06:37:55 +02:00
|
|
|
Link& pin_Direction();
|
|
|
|
|
Link& pin_Underflow();
|
|
|
|
|
Link& pin_Overflow();
|
|
|
|
|
Link& pin_Data(unsigned idx);
|
|
|
|
|
Link& pin_Result(unsigned idx);
|
|
|
|
|
Link& pin_Distance(unsigned idx);
|
1999-11-14 21:24:28 +01:00
|
|
|
|
2000-05-07 06:37:55 +02:00
|
|
|
const Link& pin_Direction() const;
|
|
|
|
|
const Link& pin_Underflow() const;
|
|
|
|
|
const Link& pin_Overflow() const;
|
|
|
|
|
const Link& pin_Data(unsigned idx) const;
|
|
|
|
|
const Link& pin_Result(unsigned idx) const;
|
|
|
|
|
const Link& pin_Distance(unsigned idx) const;
|
1999-11-14 21:24:28 +01:00
|
|
|
|
|
|
|
|
virtual void dump_node(ostream&, unsigned ind) const;
|
2000-08-14 06:39:56 +02:00
|
|
|
virtual bool emit_node(struct target_t*) const;
|
1999-11-14 21:24:28 +01:00
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
unsigned width_;
|
|
|
|
|
unsigned width_dist_;
|
|
|
|
|
};
|
|
|
|
|
|
1999-11-15 00:43:45 +01:00
|
|
|
/*
|
|
|
|
|
* This class supports the LPM_COMPARE device.
|
|
|
|
|
*
|
|
|
|
|
* NOTE: This is not the same as the device used to support case
|
|
|
|
|
* compare. Case comparisons handle Vx and Vz values, whereas this
|
|
|
|
|
* device need not.
|
|
|
|
|
*/
|
|
|
|
|
class NetCompare : public NetNode {
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
NetCompare(const string&n, unsigned width);
|
|
|
|
|
~NetCompare();
|
|
|
|
|
|
|
|
|
|
unsigned width() const;
|
|
|
|
|
|
2000-05-07 06:37:55 +02:00
|
|
|
Link& pin_Aclr();
|
|
|
|
|
Link& pin_Clock();
|
|
|
|
|
Link& pin_AGB();
|
|
|
|
|
Link& pin_AGEB();
|
|
|
|
|
Link& pin_AEB();
|
|
|
|
|
Link& pin_ANEB();
|
|
|
|
|
Link& pin_ALB();
|
|
|
|
|
Link& pin_ALEB();
|
|
|
|
|
|
|
|
|
|
Link& pin_DataA(unsigned idx);
|
|
|
|
|
Link& pin_DataB(unsigned idx);
|
|
|
|
|
|
|
|
|
|
const Link& pin_Aclr() const;
|
|
|
|
|
const Link& pin_Clock() const;
|
|
|
|
|
const Link& pin_AGB() const;
|
|
|
|
|
const Link& pin_AGEB() const;
|
|
|
|
|
const Link& pin_AEB() const;
|
|
|
|
|
const Link& pin_ANEB() const;
|
|
|
|
|
const Link& pin_ALB() const;
|
|
|
|
|
const Link& pin_ALEB() const;
|
|
|
|
|
|
|
|
|
|
const Link& pin_DataA(unsigned idx) const;
|
|
|
|
|
const Link& pin_DataB(unsigned idx) const;
|
1999-11-15 00:43:45 +01:00
|
|
|
|
2000-04-20 02:28:03 +02:00
|
|
|
virtual void functor_node(Design*, functor_t*);
|
1999-11-15 00:43:45 +01:00
|
|
|
virtual void dump_node(ostream&, unsigned ind) const;
|
2000-08-14 06:39:56 +02:00
|
|
|
virtual bool emit_node(struct target_t*) const;
|
1999-11-15 00:43:45 +01:00
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
unsigned width_;
|
|
|
|
|
};
|
|
|
|
|
|
2000-04-01 23:40:22 +02:00
|
|
|
/*
|
|
|
|
|
* This class represents a theoretical (though not necessarily
|
|
|
|
|
* practical) integer divider gate. This is not to represent any real
|
|
|
|
|
* hardware, but to support the / operator in Verilog, when it shows
|
|
|
|
|
* up in structural contexts.
|
|
|
|
|
*
|
|
|
|
|
* The operands of the operation are the DataA<i> and DataB<i> inputs,
|
|
|
|
|
* and the Result<i> output reflects the value DataA/DataB.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
class NetDivide : public NetNode {
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
NetDivide(const string&n, unsigned width, unsigned wa, unsigned wb);
|
|
|
|
|
~NetDivide();
|
|
|
|
|
|
|
|
|
|
unsigned width_r() const;
|
|
|
|
|
unsigned width_a() const;
|
|
|
|
|
unsigned width_b() const;
|
|
|
|
|
|
2000-05-07 06:37:55 +02:00
|
|
|
Link& pin_DataA(unsigned idx);
|
|
|
|
|
Link& pin_DataB(unsigned idx);
|
|
|
|
|
Link& pin_Result(unsigned idx);
|
2000-04-01 23:40:22 +02:00
|
|
|
|
2000-05-07 06:37:55 +02:00
|
|
|
const Link& pin_DataA(unsigned idx) const;
|
|
|
|
|
const Link& pin_DataB(unsigned idx) const;
|
|
|
|
|
const Link& pin_Result(unsigned idx) const;
|
2000-04-01 23:40:22 +02:00
|
|
|
|
|
|
|
|
virtual void dump_node(ostream&, unsigned ind) const;
|
2000-08-14 06:39:56 +02:00
|
|
|
virtual bool emit_node(struct target_t*) const;
|
2000-04-01 23:40:22 +02:00
|
|
|
virtual void functor_node(Design*des, functor_t*fun);
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
unsigned width_r_;
|
|
|
|
|
unsigned width_a_;
|
|
|
|
|
unsigned width_b_;
|
|
|
|
|
};
|
|
|
|
|
|
2000-09-17 23:26:15 +02:00
|
|
|
/*
|
|
|
|
|
* This class represents a theoretical (though not necessarily
|
|
|
|
|
* practical) integer modulo gate. This is not to represent any real
|
|
|
|
|
* hardware, but to support the % operator in Verilog, when it shows
|
|
|
|
|
* up in structural contexts.
|
|
|
|
|
*
|
|
|
|
|
* The operands of the operation are the DataA<i> and DataB<i> inputs,
|
|
|
|
|
* and the Result<i> output reflects the value DataA%DataB.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
class NetModulo : public NetNode {
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
NetModulo(const string&n, unsigned width, unsigned wa, unsigned wb);
|
|
|
|
|
~NetModulo();
|
|
|
|
|
|
|
|
|
|
unsigned width_r() const;
|
|
|
|
|
unsigned width_a() const;
|
|
|
|
|
unsigned width_b() const;
|
|
|
|
|
|
|
|
|
|
Link& pin_DataA(unsigned idx);
|
|
|
|
|
Link& pin_DataB(unsigned idx);
|
|
|
|
|
Link& pin_Result(unsigned idx);
|
|
|
|
|
|
|
|
|
|
const Link& pin_DataA(unsigned idx) const;
|
|
|
|
|
const Link& pin_DataB(unsigned idx) const;
|
|
|
|
|
const Link& pin_Result(unsigned idx) const;
|
|
|
|
|
|
|
|
|
|
virtual void dump_node(ostream&, unsigned ind) const;
|
|
|
|
|
virtual bool emit_node(struct target_t*) const;
|
|
|
|
|
virtual void functor_node(Design*des, functor_t*fun);
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
unsigned width_r_;
|
|
|
|
|
unsigned width_a_;
|
|
|
|
|
unsigned width_b_;
|
|
|
|
|
};
|
|
|
|
|
|
1999-11-01 03:07:40 +01:00
|
|
|
/*
|
|
|
|
|
* This class represents an LPM_FF device. There is no literal gate
|
|
|
|
|
* type in Verilog that maps, but gates of this type can be inferred.
|
|
|
|
|
*/
|
|
|
|
|
class NetFF : public NetNode {
|
|
|
|
|
|
|
|
|
|
public:
|
2000-11-11 01:03:36 +01:00
|
|
|
NetFF(NetScope*s, const string&n, unsigned width);
|
1999-11-01 03:07:40 +01:00
|
|
|
~NetFF();
|
|
|
|
|
|
|
|
|
|
unsigned width() const;
|
|
|
|
|
|
2000-05-07 06:37:55 +02:00
|
|
|
Link& pin_Clock();
|
|
|
|
|
Link& pin_Enable();
|
|
|
|
|
Link& pin_Aload();
|
|
|
|
|
Link& pin_Aset();
|
|
|
|
|
Link& pin_Aclr();
|
|
|
|
|
Link& pin_Sload();
|
|
|
|
|
Link& pin_Sset();
|
|
|
|
|
Link& pin_Sclr();
|
1999-11-01 03:07:40 +01:00
|
|
|
|
2000-05-07 06:37:55 +02:00
|
|
|
Link& pin_Data(unsigned);
|
|
|
|
|
Link& pin_Q(unsigned);
|
1999-11-01 03:07:40 +01:00
|
|
|
|
2000-05-07 06:37:55 +02:00
|
|
|
const Link& pin_Clock() const;
|
|
|
|
|
const Link& pin_Enable() const;
|
|
|
|
|
const Link& pin_Data(unsigned) const;
|
|
|
|
|
const Link& pin_Q(unsigned) const;
|
1999-11-01 03:07:40 +01:00
|
|
|
|
|
|
|
|
virtual void dump_node(ostream&, unsigned ind) const;
|
2000-08-14 06:39:56 +02:00
|
|
|
virtual bool emit_node(struct target_t*) const;
|
1999-11-01 03:07:40 +01:00
|
|
|
virtual void functor_node(Design*des, functor_t*fun);
|
|
|
|
|
};
|
|
|
|
|
|
1999-11-04 04:53:26 +01:00
|
|
|
|
1999-04-19 03:59:36 +02:00
|
|
|
/*
|
|
|
|
|
* This class represents the declared memory object. The parser
|
|
|
|
|
* creates one of these for each declared memory in the elaborated
|
|
|
|
|
* design. A reference to one of these is handled by the NetEMemory
|
1999-08-01 23:48:11 +02:00
|
|
|
* object, which is derived from NetExpr. This is not a node because
|
|
|
|
|
* memory objects can only be accessed by behavioral code.
|
1999-04-19 03:59:36 +02:00
|
|
|
*/
|
|
|
|
|
class NetMemory {
|
|
|
|
|
|
|
|
|
|
public:
|
2000-05-02 05:13:30 +02:00
|
|
|
NetMemory(NetScope*sc, const string&n, long w, long s, long e);
|
|
|
|
|
~NetMemory();
|
1999-04-19 03:59:36 +02:00
|
|
|
|
|
|
|
|
const string&name() const { return name_; }
|
1999-08-01 23:48:11 +02:00
|
|
|
|
|
|
|
|
// This is the width (in bits) of a single memory position.
|
1999-04-19 03:59:36 +02:00
|
|
|
unsigned width() const { return width_; }
|
|
|
|
|
|
2000-05-02 05:13:30 +02:00
|
|
|
NetScope*scope();
|
|
|
|
|
const NetScope*scope() const;
|
|
|
|
|
|
1999-08-01 23:48:11 +02:00
|
|
|
// This is the number of memory positions.
|
|
|
|
|
unsigned count() const;
|
1999-04-22 06:56:58 +02:00
|
|
|
|
1999-08-01 23:48:11 +02:00
|
|
|
// This method returns a 0 based address of a memory entry as
|
|
|
|
|
// indexed by idx. The Verilog source may give index ranges
|
|
|
|
|
// that are not zero based.
|
|
|
|
|
unsigned index_to_address(long idx) const;
|
1999-04-22 06:56:58 +02:00
|
|
|
|
1999-04-19 03:59:36 +02:00
|
|
|
void dump(ostream&o, unsigned lm) const;
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
string name_;
|
|
|
|
|
unsigned width_;
|
|
|
|
|
long idxh_;
|
|
|
|
|
long idxl_;
|
|
|
|
|
|
1999-12-05 03:24:08 +01:00
|
|
|
friend class NetRamDq;
|
|
|
|
|
NetRamDq* ram_list_;
|
2000-05-02 05:13:30 +02:00
|
|
|
|
|
|
|
|
friend class NetScope;
|
|
|
|
|
NetMemory*snext_, *sprev_;
|
|
|
|
|
NetScope*scope_;
|
|
|
|
|
|
|
|
|
|
private: // not implemented
|
|
|
|
|
NetMemory(const NetMemory&);
|
|
|
|
|
NetMemory& operator= (const NetMemory&);
|
1999-04-19 03:59:36 +02:00
|
|
|
};
|
|
|
|
|
|
2000-01-13 04:35:35 +01:00
|
|
|
/*
|
|
|
|
|
* This class implements the LPM_MULT component as described in the
|
|
|
|
|
* EDIF LPM Version 2 1 0 standard. It is used as a structural
|
|
|
|
|
* implementation of the * operator. The device has inputs DataA and
|
|
|
|
|
* DataB that can have independent widths, as can the result. If the
|
|
|
|
|
* result is smaller then the widths of a and b together, then the
|
|
|
|
|
* device drops the least significant bits of the product.
|
|
|
|
|
*/
|
|
|
|
|
class NetMult : public NetNode {
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
NetMult(const string&n, unsigned width, unsigned wa, unsigned wb,
|
|
|
|
|
unsigned width_s =0);
|
|
|
|
|
~NetMult();
|
|
|
|
|
|
|
|
|
|
// Get the width of the device bussed inputs. There are these
|
|
|
|
|
// parameterized widths:
|
|
|
|
|
unsigned width_r() const; // Result
|
|
|
|
|
unsigned width_a() const; // DataA
|
|
|
|
|
unsigned width_b() const; // DataB
|
|
|
|
|
unsigned width_s() const; // Sum (my be 0)
|
|
|
|
|
|
2000-05-07 06:37:55 +02:00
|
|
|
Link& pin_Aclr();
|
|
|
|
|
Link& pin_Clock();
|
2000-01-13 04:35:35 +01:00
|
|
|
|
2000-05-07 06:37:55 +02:00
|
|
|
Link& pin_DataA(unsigned idx);
|
|
|
|
|
Link& pin_DataB(unsigned idx);
|
|
|
|
|
Link& pin_Result(unsigned idx);
|
|
|
|
|
Link& pin_Sum(unsigned idx);
|
2000-01-13 04:35:35 +01:00
|
|
|
|
2000-05-07 06:37:55 +02:00
|
|
|
const Link& pin_Aclr() const;
|
|
|
|
|
const Link& pin_Clock() const;
|
2000-01-13 04:35:35 +01:00
|
|
|
|
2000-05-07 06:37:55 +02:00
|
|
|
const Link& pin_DataA(unsigned idx) const;
|
|
|
|
|
const Link& pin_DataB(unsigned idx) const;
|
|
|
|
|
const Link& pin_Result(unsigned idx) const;
|
|
|
|
|
const Link& pin_Sum(unsigned idx) const;
|
2000-01-13 04:35:35 +01:00
|
|
|
|
|
|
|
|
virtual void dump_node(ostream&, unsigned ind) const;
|
2000-08-14 06:39:56 +02:00
|
|
|
virtual bool emit_node(struct target_t*) const;
|
2000-01-13 04:35:35 +01:00
|
|
|
virtual void functor_node(Design*des, functor_t*fun);
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
unsigned width_r_;
|
|
|
|
|
unsigned width_a_;
|
|
|
|
|
unsigned width_b_;
|
|
|
|
|
unsigned width_s_;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
1999-11-04 04:53:26 +01:00
|
|
|
/*
|
|
|
|
|
* This class represents an LPM_MUX device. This device has some
|
|
|
|
|
* number of Result points (the width of the device) and some number
|
|
|
|
|
* of input choices. There is also a selector of some width. The
|
|
|
|
|
* parameters are:
|
|
|
|
|
*
|
|
|
|
|
* width -- Width of the result and each possible Data input
|
|
|
|
|
* size -- Number of Data input (each of width)
|
|
|
|
|
* selw -- Width in bits of the select input
|
|
|
|
|
*/
|
|
|
|
|
class NetMux : public NetNode {
|
|
|
|
|
|
|
|
|
|
public:
|
2001-01-18 04:16:35 +01:00
|
|
|
NetMux(NetScope*scope, const string&n,
|
|
|
|
|
unsigned width, unsigned size, unsigned selw);
|
1999-11-04 04:53:26 +01:00
|
|
|
~NetMux();
|
|
|
|
|
|
|
|
|
|
unsigned width() const;
|
|
|
|
|
unsigned size() const;
|
|
|
|
|
unsigned sel_width() const;
|
|
|
|
|
|
2000-05-07 06:37:55 +02:00
|
|
|
Link& pin_Aclr();
|
|
|
|
|
Link& pin_Clock();
|
1999-11-04 04:53:26 +01:00
|
|
|
|
2000-05-07 06:37:55 +02:00
|
|
|
Link& pin_Result(unsigned);
|
|
|
|
|
Link& pin_Data(unsigned wi, unsigned si);
|
|
|
|
|
Link& pin_Sel(unsigned);
|
1999-11-04 04:53:26 +01:00
|
|
|
|
2000-05-07 06:37:55 +02:00
|
|
|
const Link& pin_Aclr() const;
|
|
|
|
|
const Link& pin_Clock() const;
|
1999-11-04 04:53:26 +01:00
|
|
|
|
2000-05-07 06:37:55 +02:00
|
|
|
const Link& pin_Result(unsigned) const;
|
|
|
|
|
const Link& pin_Data(unsigned, unsigned) const;
|
|
|
|
|
const Link& pin_Sel(unsigned) const;
|
1999-11-04 04:53:26 +01:00
|
|
|
|
|
|
|
|
virtual void dump_node(ostream&, unsigned ind) const;
|
2000-08-14 06:39:56 +02:00
|
|
|
virtual bool emit_node(struct target_t*) const;
|
2000-07-15 07:13:43 +02:00
|
|
|
virtual void functor_node(Design*des, functor_t*fun);
|
1999-11-04 04:53:26 +01:00
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
unsigned width_;
|
|
|
|
|
unsigned size_;
|
|
|
|
|
unsigned swidth_;
|
|
|
|
|
};
|
|
|
|
|
|
1999-11-21 01:13:08 +01:00
|
|
|
/*
|
|
|
|
|
* This device represents an LPM_RAM_DQ device. The actual content is
|
|
|
|
|
* represented by a NetMemory object allocated elsewhere, but that
|
|
|
|
|
* object fixes the width and size of the device. The pin count of the
|
|
|
|
|
* address input is given in the constructor.
|
|
|
|
|
*/
|
|
|
|
|
class NetRamDq : public NetNode {
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
NetRamDq(const string&name, NetMemory*mem, unsigned awid);
|
|
|
|
|
~NetRamDq();
|
|
|
|
|
|
|
|
|
|
unsigned width() const;
|
|
|
|
|
unsigned awidth() const;
|
|
|
|
|
unsigned size() const;
|
|
|
|
|
const NetMemory*mem() const;
|
|
|
|
|
|
2000-05-07 06:37:55 +02:00
|
|
|
Link& pin_InClock();
|
|
|
|
|
Link& pin_OutClock();
|
|
|
|
|
Link& pin_WE();
|
1999-11-21 01:13:08 +01:00
|
|
|
|
2000-05-07 06:37:55 +02:00
|
|
|
Link& pin_Address(unsigned idx);
|
|
|
|
|
Link& pin_Data(unsigned idx);
|
|
|
|
|
Link& pin_Q(unsigned idx);
|
1999-11-21 01:13:08 +01:00
|
|
|
|
2000-05-07 06:37:55 +02:00
|
|
|
const Link& pin_InClock() const;
|
|
|
|
|
const Link& pin_OutClock() const;
|
|
|
|
|
const Link& pin_WE() const;
|
1999-11-21 01:13:08 +01:00
|
|
|
|
2000-05-07 06:37:55 +02:00
|
|
|
const Link& pin_Address(unsigned idx) const;
|
|
|
|
|
const Link& pin_Data(unsigned idx) const;
|
|
|
|
|
const Link& pin_Q(unsigned idx) const;
|
1999-11-21 01:13:08 +01:00
|
|
|
|
|
|
|
|
virtual void dump_node(ostream&, unsigned ind) const;
|
2000-08-14 06:39:56 +02:00
|
|
|
virtual bool emit_node(struct target_t*) const;
|
1999-11-21 01:13:08 +01:00
|
|
|
|
1999-12-05 03:24:08 +01:00
|
|
|
// Use this method to absorb other NetRamDq objects that are
|
|
|
|
|
// connected to the same memory, and have compatible pin
|
|
|
|
|
// connections.
|
|
|
|
|
void absorb_partners();
|
|
|
|
|
|
1999-12-05 20:30:42 +01:00
|
|
|
// Use this method to count the partners (including myself)
|
|
|
|
|
// that are ports to the attached memory.
|
|
|
|
|
unsigned count_partners() const;
|
|
|
|
|
|
1999-11-21 01:13:08 +01:00
|
|
|
private:
|
|
|
|
|
NetMemory*mem_;
|
|
|
|
|
NetRamDq*next_;
|
|
|
|
|
unsigned awidth_;
|
|
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
1999-03-01 04:27:53 +01:00
|
|
|
/* =========
|
|
|
|
|
* There are cases where expressions need to be represented. The
|
|
|
|
|
* NetExpr class is the root of a heirarchy that serves that purpose.
|
|
|
|
|
*
|
|
|
|
|
* The expr_width() is the width of the expression, that accounts
|
|
|
|
|
* for the widths of the sub-expressions I might have. It is up to the
|
|
|
|
|
* derived classes to properly set the expr width, if need be. The
|
|
|
|
|
* set_width() method is used to compel an expression to have a
|
|
|
|
|
* certain width, and is used particulary when the expression is an
|
|
|
|
|
* rvalue in an assignment statement.
|
|
|
|
|
*/
|
1999-05-16 07:08:42 +02:00
|
|
|
class NetExpr : public LineInfo {
|
1999-03-01 04:27:53 +01:00
|
|
|
public:
|
1999-09-20 04:21:10 +02:00
|
|
|
explicit NetExpr(unsigned w =0);
|
1999-03-01 04:27:53 +01:00
|
|
|
virtual ~NetExpr() =0;
|
|
|
|
|
|
|
|
|
|
virtual void expr_scan(struct expr_scan_t*) const =0;
|
|
|
|
|
virtual void dump(ostream&) const;
|
|
|
|
|
|
1999-05-27 06:13:08 +02:00
|
|
|
// How wide am I?
|
1999-03-01 04:27:53 +01:00
|
|
|
unsigned expr_width() const { return width_; }
|
1999-05-27 06:13:08 +02:00
|
|
|
|
|
|
|
|
// Coerce the expression to have a specific width. If the
|
|
|
|
|
// coersion works, then return true. Otherwise, return false.
|
|
|
|
|
virtual bool set_width(unsigned);
|
1999-03-01 04:27:53 +01:00
|
|
|
|
2000-09-26 07:05:58 +02:00
|
|
|
// This method returns true if the expression is
|
|
|
|
|
// signed. Unsigned expressions return false.
|
|
|
|
|
virtual bool has_sign() const;
|
|
|
|
|
|
|
|
|
|
// This returns true if the expression has a definite
|
|
|
|
|
// width. This is generally true, but in some cases the
|
|
|
|
|
// expression is amorphous and desires a width from its
|
|
|
|
|
// environment.
|
|
|
|
|
virtual bool has_width() const;
|
|
|
|
|
|
1999-06-03 07:16:25 +02:00
|
|
|
// This method evaluates the expression and returns an
|
|
|
|
|
// equivilent expression that is reduced as far as compile
|
|
|
|
|
// time knows how. Essentially, this is designed to fold
|
|
|
|
|
// constants.
|
|
|
|
|
virtual NetExpr*eval_tree();
|
|
|
|
|
|
1999-05-30 03:11:46 +02:00
|
|
|
// Make a duplicate of myself, and subexpressions if I have
|
|
|
|
|
// any. This is a deep copy operation.
|
|
|
|
|
virtual NetExpr*dup_expr() const =0;
|
1999-03-01 04:27:53 +01:00
|
|
|
|
1999-11-02 05:55:34 +01:00
|
|
|
// Return a version of myself that is structural. This is used
|
|
|
|
|
// for converting expressions to gates.
|
|
|
|
|
virtual NetNet*synthesize(Design*);
|
|
|
|
|
|
|
|
|
|
|
1999-03-01 04:27:53 +01:00
|
|
|
protected:
|
|
|
|
|
void expr_width(unsigned w) { width_ = w; }
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
unsigned width_;
|
|
|
|
|
|
|
|
|
|
private: // not implemented
|
|
|
|
|
NetExpr(const NetExpr&);
|
|
|
|
|
NetExpr& operator=(const NetExpr&);
|
|
|
|
|
};
|
|
|
|
|
|
1999-10-11 01:29:37 +02:00
|
|
|
/*
|
|
|
|
|
* The expression constant is slightly special, and is sometimes
|
1999-11-05 05:40:40 +01:00
|
|
|
* returned from other classes that can be evaluated at compile
|
1999-10-11 01:29:37 +02:00
|
|
|
* time. This class represents constant values in expressions.
|
|
|
|
|
*/
|
|
|
|
|
class NetEConst : public NetExpr {
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
explicit NetEConst(const verinum&val);
|
|
|
|
|
~NetEConst();
|
|
|
|
|
|
2000-09-26 07:05:58 +02:00
|
|
|
const verinum&value() const;
|
1999-10-11 01:29:37 +02:00
|
|
|
|
|
|
|
|
virtual bool set_width(unsigned w);
|
2000-09-26 07:05:58 +02:00
|
|
|
|
|
|
|
|
virtual bool has_sign() const;
|
|
|
|
|
virtual bool has_width() const;
|
|
|
|
|
|
1999-10-11 01:29:37 +02:00
|
|
|
virtual void expr_scan(struct expr_scan_t*) const;
|
|
|
|
|
virtual void dump(ostream&) const;
|
|
|
|
|
|
|
|
|
|
virtual NetEConst* dup_expr() const;
|
1999-11-05 05:40:40 +01:00
|
|
|
virtual NetNet*synthesize(Design*);
|
1999-10-11 01:29:37 +02:00
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
verinum value_;
|
|
|
|
|
};
|
|
|
|
|
|
1998-11-04 00:28:49 +01:00
|
|
|
/*
|
|
|
|
|
* The NetTmp object is a network that is only used momentarily by
|
1999-11-18 04:52:19 +01:00
|
|
|
* elaboration to carry links around. A completed netlist should not
|
2000-05-02 02:58:11 +02:00
|
|
|
* have any of these within. This is a kind of wire, so it is NetNet
|
|
|
|
|
* type. The constructor for this class also marks the NetNet as
|
|
|
|
|
* local, so that it is not likely to suppress a real symbol.
|
1998-11-04 00:28:49 +01:00
|
|
|
*/
|
|
|
|
|
class NetTmp : public NetNet {
|
|
|
|
|
|
|
|
|
|
public:
|
2000-05-02 02:58:11 +02:00
|
|
|
explicit NetTmp(NetScope*s, const string&name, unsigned npins =1);
|
1998-11-04 00:28:49 +01:00
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* The NetBUFZ is a magic device that represents the continuous
|
|
|
|
|
* assign, with the output being the target register and the input
|
|
|
|
|
* the logic that feeds it. The netlist preserves the directional
|
|
|
|
|
* nature of that assignment with the BUFZ. The target may elide it if
|
|
|
|
|
* that makes sense for the technology.
|
|
|
|
|
*/
|
|
|
|
|
class NetBUFZ : public NetNode {
|
|
|
|
|
|
|
|
|
|
public:
|
2000-10-07 21:45:42 +02:00
|
|
|
explicit NetBUFZ(NetScope*s, const string&n);
|
1999-10-31 05:11:27 +01:00
|
|
|
~NetBUFZ();
|
1998-11-04 00:28:49 +01:00
|
|
|
|
|
|
|
|
virtual void dump_node(ostream&, unsigned ind) const;
|
2000-08-14 06:39:56 +02:00
|
|
|
virtual bool emit_node(struct target_t*) const;
|
1998-11-04 00:28:49 +01:00
|
|
|
};
|
|
|
|
|
|
1999-10-10 03:59:54 +02:00
|
|
|
/*
|
|
|
|
|
* This node is used to represent case equality in combinational
|
|
|
|
|
* logic. Although this is not normally synthesizeable, it makes sense
|
|
|
|
|
* to support an abstract gate that can compare x and z.
|
|
|
|
|
*
|
|
|
|
|
* This pins are assigned as:
|
|
|
|
|
*
|
|
|
|
|
* 0 -- Output (always returns 0 or 1)
|
|
|
|
|
* 1 -- Input
|
|
|
|
|
* 2 -- Input
|
|
|
|
|
*/
|
|
|
|
|
class NetCaseCmp : public NetNode {
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
explicit NetCaseCmp(const string&n);
|
|
|
|
|
~NetCaseCmp();
|
|
|
|
|
|
|
|
|
|
virtual void dump_node(ostream&, unsigned ind) const;
|
2000-08-14 06:39:56 +02:00
|
|
|
virtual bool emit_node(struct target_t*) const;
|
1999-10-10 03:59:54 +02:00
|
|
|
};
|
|
|
|
|
|
1999-12-17 04:38:46 +01:00
|
|
|
/*
|
|
|
|
|
* This class represents instances of the LPM_CONSTANT device. The
|
|
|
|
|
* node has only outputs and a constant value. The width is available
|
|
|
|
|
* by getting the pin_count(), and the value bits are available one at
|
|
|
|
|
* a time. There is no meaning to the aggregation of bits to form a
|
|
|
|
|
* wide NetConst object, although some targets may have an easier time
|
|
|
|
|
* detecting interesting constructs if they are combined.
|
|
|
|
|
*/
|
1998-11-09 19:55:33 +01:00
|
|
|
class NetConst : public NetNode {
|
|
|
|
|
|
|
|
|
|
public:
|
1999-10-10 03:59:54 +02:00
|
|
|
explicit NetConst(const string&n, verinum::V v);
|
1999-12-17 04:38:46 +01:00
|
|
|
explicit NetConst(const string&n, const verinum&val);
|
1999-10-10 03:59:54 +02:00
|
|
|
~NetConst();
|
1998-11-09 19:55:33 +01:00
|
|
|
|
1999-12-17 04:38:46 +01:00
|
|
|
verinum::V value(unsigned idx) const;
|
1998-11-09 19:55:33 +01:00
|
|
|
|
2000-08-14 06:39:56 +02:00
|
|
|
virtual bool emit_node(struct target_t*) const;
|
1999-12-17 07:18:15 +01:00
|
|
|
virtual void functor_node(Design*, functor_t*);
|
1998-11-09 19:55:33 +01:00
|
|
|
virtual void dump_node(ostream&, unsigned ind) const;
|
|
|
|
|
|
|
|
|
|
private:
|
1999-12-17 04:38:46 +01:00
|
|
|
verinum::V*value_;
|
1998-11-09 19:55:33 +01:00
|
|
|
};
|
|
|
|
|
|
1998-11-04 00:28:49 +01:00
|
|
|
/*
|
1998-12-02 05:37:13 +01:00
|
|
|
* This class represents all manner of logic gates. Pin 0 is OUTPUT and
|
2000-04-23 23:15:07 +02:00
|
|
|
* all the remaining pins are INPUT. The BUFIF[01] gates have the
|
2000-04-23 23:17:31 +02:00
|
|
|
* more specific pinout as follows:
|
|
|
|
|
*
|
|
|
|
|
* bufif<N>
|
|
|
|
|
* 0 -- output
|
|
|
|
|
* 1 -- input data
|
|
|
|
|
* 2 -- enable
|
1998-11-04 00:28:49 +01:00
|
|
|
*/
|
|
|
|
|
class NetLogic : public NetNode {
|
|
|
|
|
|
|
|
|
|
public:
|
2000-11-11 02:52:09 +01:00
|
|
|
enum TYPE { AND, BUF, BUFIF0, BUFIF1, NAND, NMOS, NOR, NOT, NOTIF0,
|
|
|
|
|
NOTIF1, OR, RNMOS, RPMOS, PMOS, XNOR, XOR };
|
1998-11-04 00:28:49 +01:00
|
|
|
|
2000-10-07 21:45:42 +02:00
|
|
|
explicit NetLogic(NetScope*s, const string&n, unsigned pins, TYPE t);
|
1998-11-04 00:28:49 +01:00
|
|
|
|
|
|
|
|
TYPE type() const { return type_; }
|
|
|
|
|
|
|
|
|
|
virtual void dump_node(ostream&, unsigned ind) const;
|
2000-08-14 06:39:56 +02:00
|
|
|
virtual bool emit_node(struct target_t*) const;
|
1999-12-17 07:18:15 +01:00
|
|
|
virtual void functor_node(Design*, functor_t*);
|
1998-11-04 00:28:49 +01:00
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
const TYPE type_;
|
|
|
|
|
};
|
|
|
|
|
|
1998-12-01 01:42:13 +01:00
|
|
|
/*
|
|
|
|
|
* The UDP is a User Defined Primitive from the Verilog source. Do not
|
|
|
|
|
* expand it out any further then this in the netlist, as this can be
|
|
|
|
|
* used to represent target device primitives.
|
1998-12-14 03:01:34 +01:00
|
|
|
*
|
1999-08-18 06:00:02 +02:00
|
|
|
* The UDP can be combinational or sequential. The sequential UDP
|
1998-12-14 03:01:34 +01:00
|
|
|
* includes the current output in the truth table, and supports edges,
|
|
|
|
|
* whereas the combinational does not and is entirely level sensitive.
|
|
|
|
|
* In any case, pin 0 is an output, and all the remaining pins are
|
|
|
|
|
* inputs.
|
|
|
|
|
*
|
1999-11-04 02:12:41 +01:00
|
|
|
* The sequential truth table is canonically represented as a finite state
|
1998-12-14 03:01:34 +01:00
|
|
|
* machine with the current state representing the inputs and the
|
|
|
|
|
* current output, and the next state carrying the new output value to
|
|
|
|
|
* use. All the outgoing transitions from a state represent a single
|
|
|
|
|
* edge.
|
|
|
|
|
*
|
|
|
|
|
* Set_table takes as input a string with one letter per pin. The
|
1998-12-18 06:16:25 +01:00
|
|
|
* parser translates the written sequences to one of these. The
|
1998-12-14 03:01:34 +01:00
|
|
|
* valid characters are:
|
|
|
|
|
*
|
|
|
|
|
* 0, 1, x -- The levels
|
|
|
|
|
* r -- (01)
|
|
|
|
|
* R -- (x1)
|
|
|
|
|
* f -- (10)
|
|
|
|
|
* F -- (x0)
|
|
|
|
|
* P -- (0x)
|
|
|
|
|
* N -- (1x)
|
|
|
|
|
*
|
1998-12-18 06:16:25 +01:00
|
|
|
* It also takes one of the following glob letters to represent more
|
|
|
|
|
* then one item.
|
|
|
|
|
*
|
|
|
|
|
* p -- 01, 0x or x1
|
|
|
|
|
* n -- 10, 1x or x0
|
|
|
|
|
* ? -- 0, 1, or x
|
|
|
|
|
* * -- any edge
|
|
|
|
|
* + -- 01 or x1
|
|
|
|
|
* _ -- 10 or x0 (Note that this is not the output '-'.)
|
|
|
|
|
* % -- 0x or 1x
|
|
|
|
|
*
|
1999-11-04 02:12:41 +01:00
|
|
|
* SEQUENTIAL
|
|
|
|
|
* These objects have a single bit of memory. The logic table includes
|
|
|
|
|
* an entry for the current value, and allows edges on the inputs. In
|
|
|
|
|
* canonical form, inly then entries that generate 0, 1 or - (no change)
|
|
|
|
|
* are listed.
|
|
|
|
|
*
|
1998-12-14 03:01:34 +01:00
|
|
|
* COMBINATIONAL
|
|
|
|
|
* The logic table is a map between the input levels and the
|
|
|
|
|
* output. Each input pin can have the value 0, 1 or x and the output
|
|
|
|
|
* can have the values 0 or 1. If the input matches nothing, the
|
|
|
|
|
* output is x. In canonical form, only the entries that generate 0 or
|
|
|
|
|
* 1 are listed.
|
|
|
|
|
*
|
1998-12-01 01:42:13 +01:00
|
|
|
*/
|
2000-11-04 07:36:24 +01:00
|
|
|
class NetUDP_COMB : public NetNode {
|
1998-12-01 01:42:13 +01:00
|
|
|
|
|
|
|
|
public:
|
2000-11-04 07:36:24 +01:00
|
|
|
explicit NetUDP_COMB(const string&n, unsigned pins, bool sequ = false);
|
|
|
|
|
|
|
|
|
|
virtual bool emit_node(struct target_t*) const;
|
|
|
|
|
virtual void dump_node(ostream&, unsigned ind) const;
|
|
|
|
|
|
|
|
|
|
/* append a new truth table row. */
|
|
|
|
|
bool set_table(const string&input, char output);
|
|
|
|
|
|
|
|
|
|
/* After the primitive is built up, this method is called to
|
|
|
|
|
clean up redundancies, and possibly optimize the table. */
|
|
|
|
|
void cleanup_table();
|
|
|
|
|
|
|
|
|
|
/* Use these methods to scan the truth table of the
|
|
|
|
|
device. "first" returns the first item in the table, and
|
|
|
|
|
"next" returns the next item in the table. The method will
|
|
|
|
|
return false when the scan is done. */
|
|
|
|
|
bool first(string&inp, char&out) const;
|
|
|
|
|
bool next(string&inp, char&out) const;
|
|
|
|
|
|
|
|
|
|
bool is_sequential() const { return sequential_; }
|
|
|
|
|
|
|
|
|
|
protected:
|
|
|
|
|
|
|
|
|
|
// A combinational primitive is more simply represented as a
|
|
|
|
|
// simple map of input signals to a single output.
|
|
|
|
|
typedef map<string,char> CM_;
|
|
|
|
|
CM_ cm_;
|
|
|
|
|
|
|
|
|
|
private:
|
1998-12-01 01:42:13 +01:00
|
|
|
|
2000-11-04 07:36:24 +01:00
|
|
|
bool sequential_;
|
|
|
|
|
|
|
|
|
|
mutable CM_::const_iterator idx_;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class NetUDP : public NetUDP_COMB {
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
explicit NetUDP(const string&n, unsigned pins, bool sequ = true)
|
|
|
|
|
: NetUDP_COMB(n, pins, sequ), init_('x') {};
|
|
|
|
|
|
2000-08-14 06:39:56 +02:00
|
|
|
virtual bool emit_node( struct target_t*) const;
|
1998-12-01 01:42:13 +01:00
|
|
|
virtual void dump_node(ostream&, unsigned ind) const;
|
1998-12-14 03:01:34 +01:00
|
|
|
|
|
|
|
|
/* return false if the entry conflicts with an existing
|
|
|
|
|
entry. In any case, the new output overrides. */
|
|
|
|
|
bool set_table(const string&input, char output);
|
|
|
|
|
void cleanup_table();
|
|
|
|
|
|
1998-12-18 00:54:58 +01:00
|
|
|
/* Return the next output from the passed state. Each letter
|
|
|
|
|
of the input string represents the pin of the same
|
|
|
|
|
position. */
|
|
|
|
|
char table_lookup(const string&from, char to, unsigned pin) const;
|
|
|
|
|
|
1998-12-14 03:01:34 +01:00
|
|
|
void set_initial(char);
|
1998-12-18 00:54:58 +01:00
|
|
|
char get_initial() const { return init_; }
|
1998-12-14 03:01:34 +01:00
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
char init_;
|
|
|
|
|
|
|
|
|
|
struct state_t_;
|
|
|
|
|
struct pin_t_ {
|
|
|
|
|
state_t_*zer;
|
|
|
|
|
state_t_*one;
|
|
|
|
|
state_t_*xxx;
|
|
|
|
|
|
|
|
|
|
explicit pin_t_() : zer(0), one(0), xxx(0) { }
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
struct state_t_ {
|
|
|
|
|
char out;
|
|
|
|
|
pin_t_*pins;
|
|
|
|
|
|
|
|
|
|
state_t_(unsigned n) : out(0), pins(new pin_t_[n]) {}
|
|
|
|
|
~state_t_() { delete[]pins; }
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
typedef map<string,state_t_*> FSM_;
|
|
|
|
|
FSM_ fsm_;
|
|
|
|
|
bool set_sequ_(const string&in, char out);
|
|
|
|
|
bool sequ_glob_(string, char out);
|
|
|
|
|
|
|
|
|
|
state_t_*find_state_(const string&);
|
|
|
|
|
|
|
|
|
|
void dump_sequ_(ostream&o, unsigned ind) const;
|
|
|
|
|
void dump_comb_(ostream&o, unsigned ind) const;
|
1998-12-01 01:42:13 +01:00
|
|
|
};
|
|
|
|
|
|
1998-11-04 00:28:49 +01:00
|
|
|
/* =========
|
|
|
|
|
* A process is a behavioral-model description. A process is a
|
|
|
|
|
* statement that may be compound. the various statement types may
|
|
|
|
|
* refer to places in a netlist (by pointing to nodes) but is not
|
|
|
|
|
* linked into the netlist. However, elaborating a process may cause
|
|
|
|
|
* special nodes to be created to handle things like events.
|
|
|
|
|
*/
|
2000-04-15 21:51:30 +02:00
|
|
|
class NetProc : public LineInfo {
|
1998-11-04 00:28:49 +01:00
|
|
|
|
|
|
|
|
public:
|
1999-09-29 20:36:02 +02:00
|
|
|
explicit NetProc();
|
1998-11-04 00:28:49 +01:00
|
|
|
virtual ~NetProc();
|
|
|
|
|
|
1999-09-22 18:57:23 +02:00
|
|
|
// This method is called to emit the statement to the
|
|
|
|
|
// target. The target returns true if OK, false for errors.
|
2000-08-08 03:50:42 +02:00
|
|
|
virtual bool emit_proc(struct target_t*) const;
|
1999-09-22 18:57:23 +02:00
|
|
|
|
1999-12-01 07:06:16 +01:00
|
|
|
// This method is called by functors that want to scan a
|
|
|
|
|
// process in search of matchable patterns.
|
|
|
|
|
virtual int match_proc(struct proc_match_t*);
|
|
|
|
|
|
1998-11-04 00:28:49 +01:00
|
|
|
virtual void dump(ostream&, unsigned ind) const;
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
friend class NetBlock;
|
|
|
|
|
NetProc*next_;
|
2000-05-12 01:37:26 +02:00
|
|
|
|
|
|
|
|
private: // not implemented
|
|
|
|
|
NetProc(const NetProc&);
|
|
|
|
|
NetProc& operator= (const NetProc&);
|
1998-11-04 00:28:49 +01:00
|
|
|
};
|
|
|
|
|
|
1999-03-15 03:43:32 +01:00
|
|
|
/*
|
2000-09-02 22:54:20 +02:00
|
|
|
* Procedural assignment is broken into a suite of classes. These
|
|
|
|
|
* classes represent the various aspects of the assignment statement
|
|
|
|
|
* in behavioral code. (The continuous assignment is *not*
|
|
|
|
|
* represented here.)
|
|
|
|
|
*
|
|
|
|
|
* The NetAssignBase carries the common aspects of an assignment,
|
|
|
|
|
* including the r-value. This class has no cares of blocking vs
|
|
|
|
|
* non-blocking, however it carries nearly all the other properties
|
|
|
|
|
* of the assignment statement. It is abstract because it does not
|
|
|
|
|
* differentiate the virtual behaviors.
|
|
|
|
|
*
|
|
|
|
|
* The NetAssign and NetAssignNB classes are the concrete classes that
|
|
|
|
|
* give the assignment its final, precise meaning. These classes fill
|
|
|
|
|
* in the NetProc behaviors.
|
|
|
|
|
*
|
|
|
|
|
* The l-value of the assignment is a collection of NetAssign_
|
2000-09-07 02:06:53 +02:00
|
|
|
* objects that are connected to the structural netlist where the
|
|
|
|
|
* assignment has its effect. The NetAssign_ class is not to be
|
|
|
|
|
* derived from.
|
1999-09-08 06:05:30 +02:00
|
|
|
*
|
2000-09-10 04:18:16 +02:00
|
|
|
* The collection is arranged from lsb up to msb, and represents the
|
|
|
|
|
* concatenation of l-values. The elaborator may collapse some
|
|
|
|
|
* concatenations into a single NetAssign_. The "more" member of the
|
|
|
|
|
* NetAssign_ object points to the next most significant bits of l-value.
|
|
|
|
|
*
|
1999-09-08 06:05:30 +02:00
|
|
|
* NOTE: The elaborator will make an effort to match the width of the
|
2000-09-02 22:54:20 +02:00
|
|
|
* r-value to the with of the l-value, but targets and functions
|
1999-09-08 06:05:30 +02:00
|
|
|
* should know that this is not a guarantee.
|
1999-03-15 03:43:32 +01:00
|
|
|
*/
|
1999-06-13 18:30:06 +02:00
|
|
|
|
2000-09-02 22:54:20 +02:00
|
|
|
class NetAssign_ : public NetNode {
|
1999-06-13 18:30:06 +02:00
|
|
|
|
1999-10-06 07:06:16 +02:00
|
|
|
public:
|
2000-09-02 22:54:20 +02:00
|
|
|
NetAssign_(const string&n, unsigned w);
|
|
|
|
|
~NetAssign_();
|
1999-10-06 07:06:16 +02:00
|
|
|
|
1999-10-07 07:25:33 +02:00
|
|
|
// If this expression exists, then only a single bit is to be
|
|
|
|
|
// set from the rval, and the value of this expression selects
|
|
|
|
|
// the pin that gets the value.
|
|
|
|
|
const NetExpr*bmux() const;
|
|
|
|
|
|
|
|
|
|
void set_bmux(NetExpr*);
|
1999-10-06 07:06:16 +02:00
|
|
|
|
2000-09-07 02:06:53 +02:00
|
|
|
// Get the width of the r-value that this node expects. This
|
|
|
|
|
// method accounts for the presence of the mux, so it not
|
|
|
|
|
// nexessarily the same as the pin_count().
|
|
|
|
|
unsigned lwidth() const;
|
|
|
|
|
|
2000-09-02 22:54:20 +02:00
|
|
|
virtual bool emit_node(struct target_t*) const;
|
|
|
|
|
virtual void dump_node(ostream&, unsigned ind) const;
|
|
|
|
|
|
2000-09-10 04:18:16 +02:00
|
|
|
// This pointer is for keeping simple lists.
|
|
|
|
|
NetAssign_* more;
|
|
|
|
|
|
1999-10-06 07:06:16 +02:00
|
|
|
private:
|
1999-10-07 07:25:33 +02:00
|
|
|
NetExpr*bmux_;
|
1999-06-13 18:30:06 +02:00
|
|
|
};
|
|
|
|
|
|
2000-09-02 22:54:20 +02:00
|
|
|
class NetAssignBase : public NetProc {
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
NetAssignBase(NetAssign_*lv, NetExpr*rv);
|
|
|
|
|
virtual ~NetAssignBase() =0;
|
|
|
|
|
|
|
|
|
|
// This is the (procedural) value that is to be assigned when
|
|
|
|
|
// the assignment is executed.
|
|
|
|
|
NetExpr*rval();
|
|
|
|
|
const NetExpr*rval() const;
|
|
|
|
|
|
|
|
|
|
void set_rval(NetExpr*);
|
|
|
|
|
|
|
|
|
|
NetAssign_* l_val(unsigned);
|
|
|
|
|
const NetAssign_* l_val(unsigned) const;
|
2000-10-18 22:04:39 +02:00
|
|
|
unsigned l_val_count() const;
|
2000-09-02 22:54:20 +02:00
|
|
|
|
2000-09-07 02:06:53 +02:00
|
|
|
// This returns the total width of the accumulated l-value. It
|
|
|
|
|
// accounts for any grouping of NetAssign_ objects that might happen.
|
|
|
|
|
unsigned lwidth() const;
|
|
|
|
|
|
2000-09-10 04:18:16 +02:00
|
|
|
void dump_lval(ostream&) const;
|
|
|
|
|
|
2000-09-02 22:54:20 +02:00
|
|
|
private:
|
|
|
|
|
NetAssign_*lval_;
|
|
|
|
|
NetExpr *rval_;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
class NetAssign : public NetAssignBase {
|
|
|
|
|
|
1998-11-04 00:28:49 +01:00
|
|
|
public:
|
2000-09-03 01:40:12 +02:00
|
|
|
explicit NetAssign(NetAssign_*lv, NetExpr*rv);
|
1998-11-04 00:28:49 +01:00
|
|
|
~NetAssign();
|
|
|
|
|
|
2000-08-08 03:50:42 +02:00
|
|
|
virtual bool emit_proc(struct target_t*) const;
|
1999-12-01 07:06:16 +01:00
|
|
|
virtual int match_proc(struct proc_match_t*);
|
1998-11-04 00:28:49 +01:00
|
|
|
virtual void dump(ostream&, unsigned ind) const;
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
};
|
|
|
|
|
|
2000-09-02 22:54:20 +02:00
|
|
|
class NetAssignNB : public NetAssignBase {
|
1999-06-06 22:45:38 +02:00
|
|
|
public:
|
2000-09-03 01:40:12 +02:00
|
|
|
explicit NetAssignNB(NetAssign_*lv, NetExpr*rv);
|
1999-06-06 22:45:38 +02:00
|
|
|
~NetAssignNB();
|
|
|
|
|
|
|
|
|
|
|
2000-08-08 03:50:42 +02:00
|
|
|
virtual bool emit_proc(struct target_t*) const;
|
2000-08-01 04:48:41 +02:00
|
|
|
virtual int match_proc(struct proc_match_t*);
|
1999-06-06 22:45:38 +02:00
|
|
|
virtual void dump(ostream&, unsigned ind) const;
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
};
|
|
|
|
|
|
1999-05-10 02:16:57 +02:00
|
|
|
/*
|
|
|
|
|
* Assignment to memory is handled separately because memory is
|
1999-09-15 03:55:06 +02:00
|
|
|
* not a node. There are blocking and non-blocking variants, just like
|
|
|
|
|
* regular assign, and the NetAssignMem_ base class takes care of all
|
|
|
|
|
* the common stuff.
|
1999-05-10 02:16:57 +02:00
|
|
|
*/
|
1999-09-29 20:36:02 +02:00
|
|
|
class NetAssignMem_ : public NetProc {
|
1999-05-10 02:16:57 +02:00
|
|
|
|
|
|
|
|
public:
|
2000-06-13 05:24:48 +02:00
|
|
|
explicit NetAssignMem_(NetMemory*, NetExpr*idx, NetExpr*rv);
|
1999-09-15 03:55:06 +02:00
|
|
|
~NetAssignMem_();
|
1999-05-10 02:16:57 +02:00
|
|
|
|
1999-12-05 03:24:08 +01:00
|
|
|
NetMemory*memory() { return mem_; }
|
2000-06-13 05:24:48 +02:00
|
|
|
NetExpr*index() { return index_; }
|
1999-12-09 07:00:00 +01:00
|
|
|
NetExpr*rval() { return rval_; }
|
1999-12-05 03:24:08 +01:00
|
|
|
|
1999-05-12 06:03:19 +02:00
|
|
|
const NetMemory*memory()const { return mem_; }
|
2000-06-13 05:24:48 +02:00
|
|
|
const NetExpr*index()const { return index_; }
|
1999-12-05 03:24:08 +01:00
|
|
|
const NetExpr*rval()const { return rval_; }
|
1999-05-12 06:03:19 +02:00
|
|
|
|
1999-05-10 02:16:57 +02:00
|
|
|
private:
|
|
|
|
|
NetMemory*mem_;
|
2000-06-13 05:24:48 +02:00
|
|
|
NetExpr* index_;
|
1999-05-30 03:11:46 +02:00
|
|
|
NetExpr* rval_;
|
1999-05-10 02:16:57 +02:00
|
|
|
};
|
|
|
|
|
|
1999-09-15 03:55:06 +02:00
|
|
|
class NetAssignMem : public NetAssignMem_ {
|
|
|
|
|
|
|
|
|
|
public:
|
2000-06-13 05:24:48 +02:00
|
|
|
explicit NetAssignMem(NetMemory*, NetExpr*idx, NetExpr*rv);
|
1999-09-15 03:55:06 +02:00
|
|
|
~NetAssignMem();
|
|
|
|
|
|
1999-12-05 03:24:08 +01:00
|
|
|
virtual int match_proc(struct proc_match_t*);
|
2000-08-08 03:50:42 +02:00
|
|
|
virtual bool emit_proc(struct target_t*) const;
|
1999-09-15 03:55:06 +02:00
|
|
|
virtual void dump(ostream&, unsigned ind) const;
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
class NetAssignMemNB : public NetAssignMem_ {
|
|
|
|
|
|
|
|
|
|
public:
|
2000-06-13 05:24:48 +02:00
|
|
|
explicit NetAssignMemNB(NetMemory*, NetExpr*idx, NetExpr*rv);
|
1999-09-15 03:55:06 +02:00
|
|
|
~NetAssignMemNB();
|
|
|
|
|
|
2000-08-01 04:48:41 +02:00
|
|
|
virtual int match_proc(struct proc_match_t*);
|
2000-08-08 03:50:42 +02:00
|
|
|
virtual bool emit_proc(struct target_t*) const;
|
1999-09-15 03:55:06 +02:00
|
|
|
virtual void dump(ostream&, unsigned ind) const;
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
};
|
|
|
|
|
|
2000-04-15 21:51:30 +02:00
|
|
|
/*
|
|
|
|
|
* A block is stuff like begin-end blocks, that contain an ordered
|
|
|
|
|
* list of NetProc statements.
|
|
|
|
|
*
|
|
|
|
|
* NOTE: The emit method calls the target->proc_block function but
|
|
|
|
|
* does not recurse. It is up to the target-supplied proc_block
|
|
|
|
|
* function to call emit_recurse.
|
|
|
|
|
*/
|
1998-11-04 00:28:49 +01:00
|
|
|
class NetBlock : public NetProc {
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
enum Type { SEQU, PARA };
|
|
|
|
|
|
|
|
|
|
NetBlock(Type t) : type_(t), last_(0) { }
|
|
|
|
|
~NetBlock();
|
|
|
|
|
|
|
|
|
|
const Type type() const { return type_; }
|
|
|
|
|
|
|
|
|
|
void append(NetProc*);
|
|
|
|
|
|
2000-04-15 21:51:30 +02:00
|
|
|
const NetProc*proc_first() const;
|
|
|
|
|
const NetProc*proc_next(const NetProc*cur) const;
|
|
|
|
|
|
|
|
|
|
// This version of emit_recurse scans all the statements of
|
|
|
|
|
// the begin-end block sequentially. It is typically of use
|
|
|
|
|
// for sequential blocks.
|
2000-08-08 03:50:42 +02:00
|
|
|
void emit_recurse(struct target_t*) const;
|
2000-04-15 21:51:30 +02:00
|
|
|
|
2000-08-08 03:50:42 +02:00
|
|
|
virtual bool emit_proc(struct target_t*) const;
|
2000-02-13 05:35:43 +01:00
|
|
|
virtual int match_proc(struct proc_match_t*);
|
1998-11-04 00:28:49 +01:00
|
|
|
virtual void dump(ostream&, unsigned ind) const;
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
const Type type_;
|
|
|
|
|
|
|
|
|
|
NetProc*last_;
|
|
|
|
|
};
|
|
|
|
|
|
1999-09-29 20:36:02 +02:00
|
|
|
/*
|
|
|
|
|
* A CASE statement in the verilog source leads, eventually, to one of
|
|
|
|
|
* these. This is different from a simple conditional because of the
|
|
|
|
|
* way the comparisons are performed. Also, it is likely that the
|
|
|
|
|
* target may be able to optimize differently.
|
|
|
|
|
*
|
2000-12-02 06:08:04 +01:00
|
|
|
* Case can be one of three types:
|
1999-09-29 20:36:02 +02:00
|
|
|
* EQ -- All bits must exactly match
|
|
|
|
|
* EQZ -- z bits are don't care
|
|
|
|
|
* EQX -- x and z bits are don't care.
|
|
|
|
|
*/
|
1999-02-03 05:20:11 +01:00
|
|
|
class NetCase : public NetProc {
|
|
|
|
|
|
|
|
|
|
public:
|
1999-09-29 20:36:02 +02:00
|
|
|
enum TYPE { EQ, EQX, EQZ };
|
|
|
|
|
NetCase(TYPE c, NetExpr*ex, unsigned cnt);
|
1999-02-03 05:20:11 +01:00
|
|
|
~NetCase();
|
|
|
|
|
|
|
|
|
|
void set_case(unsigned idx, NetExpr*ex, NetProc*st);
|
|
|
|
|
|
1999-09-29 20:36:02 +02:00
|
|
|
TYPE type() const;
|
1999-05-30 03:11:46 +02:00
|
|
|
const NetExpr*expr() const { return expr_; }
|
1999-02-08 03:49:56 +01:00
|
|
|
unsigned nitems() const { return nitems_; }
|
|
|
|
|
|
1999-05-30 03:11:46 +02:00
|
|
|
const NetExpr*expr(unsigned idx) const { return items_[idx].guard;}
|
1999-02-08 03:49:56 +01:00
|
|
|
const NetProc*stat(unsigned idx) const { return items_[idx].statement; }
|
|
|
|
|
|
2000-08-08 03:50:42 +02:00
|
|
|
virtual bool emit_proc(struct target_t*) const;
|
1999-02-03 05:20:11 +01:00
|
|
|
virtual void dump(ostream&, unsigned ind) const;
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
|
1999-09-29 20:36:02 +02:00
|
|
|
TYPE type_;
|
|
|
|
|
|
1999-02-03 05:20:11 +01:00
|
|
|
struct Item {
|
1999-05-30 03:11:46 +02:00
|
|
|
NetExpr*guard;
|
1999-02-03 05:20:11 +01:00
|
|
|
NetProc*statement;
|
|
|
|
|
};
|
|
|
|
|
|
1999-05-30 03:11:46 +02:00
|
|
|
NetExpr* expr_;
|
1999-02-03 05:20:11 +01:00
|
|
|
unsigned nitems_;
|
|
|
|
|
Item*items_;
|
|
|
|
|
};
|
|
|
|
|
|
2000-05-12 01:37:26 +02:00
|
|
|
/*
|
|
|
|
|
* The cassign statement causes the r-val net to be forced onto the
|
|
|
|
|
* l-val reg when it is executed. The code generator is expected to
|
|
|
|
|
* know what that means. All the expressions are structural and behave
|
|
|
|
|
* like nets.
|
|
|
|
|
*
|
|
|
|
|
* This class is a NetProc because it it turned on by procedural
|
|
|
|
|
* behavior. However, it is also a NetNode because it connects to
|
|
|
|
|
* nets, and when activated follows the net values.
|
|
|
|
|
*/
|
|
|
|
|
class NetCAssign : public NetProc, public NetNode {
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
explicit NetCAssign(const string&n, NetNet*l);
|
|
|
|
|
~NetCAssign();
|
|
|
|
|
|
|
|
|
|
const Link& lval_pin(unsigned) const;
|
|
|
|
|
|
|
|
|
|
virtual void dump(ostream&, unsigned ind) const;
|
2000-08-08 03:50:42 +02:00
|
|
|
virtual bool emit_proc(struct target_t*) const;
|
2000-05-12 01:37:26 +02:00
|
|
|
virtual void dump_node(ostream&, unsigned ind) const;
|
2000-08-14 06:39:56 +02:00
|
|
|
virtual bool emit_node(struct target_t*) const;
|
2000-05-12 01:37:26 +02:00
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
NetNet*lval_;
|
|
|
|
|
|
|
|
|
|
private: // not implemented
|
|
|
|
|
NetCAssign(const NetCAssign&);
|
|
|
|
|
NetCAssign& operator= (const NetCAssign&);
|
|
|
|
|
};
|
|
|
|
|
|
1999-02-03 05:20:11 +01:00
|
|
|
|
1998-11-07 18:05:05 +01:00
|
|
|
/* A condit represents a conditional. It has an expression to test,
|
|
|
|
|
and a pair of statements to select from. */
|
|
|
|
|
class NetCondit : public NetProc {
|
|
|
|
|
|
|
|
|
|
public:
|
1999-06-24 06:24:18 +02:00
|
|
|
explicit NetCondit(NetExpr*ex, NetProc*i, NetProc*e);
|
1999-07-18 23:17:50 +02:00
|
|
|
~NetCondit();
|
|
|
|
|
|
|
|
|
|
const NetExpr*expr() const;
|
|
|
|
|
NetExpr*expr();
|
|
|
|
|
|
|
|
|
|
NetProc* if_clause();
|
|
|
|
|
NetProc* else_clause();
|
1998-11-07 18:05:05 +01:00
|
|
|
|
2000-04-17 01:32:18 +02:00
|
|
|
// Replace the condition expression.
|
|
|
|
|
void set_expr(NetExpr*ex);
|
|
|
|
|
|
2000-08-08 03:50:42 +02:00
|
|
|
void emit_recurse_if(struct target_t*) const;
|
|
|
|
|
void emit_recurse_else(struct target_t*) const;
|
1998-11-07 18:05:05 +01:00
|
|
|
|
2000-08-08 03:50:42 +02:00
|
|
|
virtual bool emit_proc(struct target_t*) const;
|
1999-12-01 07:06:16 +01:00
|
|
|
virtual int match_proc(struct proc_match_t*);
|
1998-11-07 18:05:05 +01:00
|
|
|
virtual void dump(ostream&, unsigned ind) const;
|
|
|
|
|
|
|
|
|
|
private:
|
1999-05-30 03:11:46 +02:00
|
|
|
NetExpr* expr_;
|
1998-11-07 18:05:05 +01:00
|
|
|
NetProc*if_;
|
|
|
|
|
NetProc*else_;
|
|
|
|
|
};
|
|
|
|
|
|
2000-05-12 01:37:26 +02:00
|
|
|
/*
|
|
|
|
|
* The procedural deassign statement (the opposite of assign) releases
|
|
|
|
|
* any assign expressions attached to the bits of the reg. The
|
|
|
|
|
* lval is the expression of the "deassign <expr>;" statement with the
|
|
|
|
|
* expr elaborated to a net.
|
|
|
|
|
*/
|
|
|
|
|
class NetDeassign : public NetProc {
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
explicit NetDeassign(NetNet*l);
|
|
|
|
|
~NetDeassign();
|
|
|
|
|
|
|
|
|
|
const NetNet*lval() const;
|
|
|
|
|
|
2000-08-08 03:50:42 +02:00
|
|
|
virtual bool emit_proc(struct target_t*) const;
|
2000-05-12 01:37:26 +02:00
|
|
|
virtual void dump(ostream&, unsigned ind) const;
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
NetNet*lval_;
|
|
|
|
|
|
|
|
|
|
private: // not implemented
|
|
|
|
|
NetDeassign(const NetDeassign&);
|
|
|
|
|
NetDeassign& operator= (const NetDeassign&);
|
|
|
|
|
};
|
|
|
|
|
|
2000-07-27 07:13:44 +02:00
|
|
|
/*
|
|
|
|
|
* This node represents the behavioral disable statement. The Verilog
|
|
|
|
|
* source that produces it looks like:
|
|
|
|
|
*
|
|
|
|
|
* disable <scope>;
|
|
|
|
|
*
|
|
|
|
|
* Where the scope is a named block or a task. It cannot be a module
|
|
|
|
|
* instance scope because module instances cannot be disabled.
|
|
|
|
|
*/
|
|
|
|
|
class NetDisable : public NetProc {
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
explicit NetDisable(NetScope*tgt);
|
|
|
|
|
~NetDisable();
|
|
|
|
|
|
|
|
|
|
const NetScope*target() const;
|
|
|
|
|
|
2000-08-08 03:50:42 +02:00
|
|
|
virtual bool emit_proc(struct target_t*) const;
|
2000-07-27 07:13:44 +02:00
|
|
|
virtual void dump(ostream&, unsigned ind) const;
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
NetScope*target_;
|
|
|
|
|
|
|
|
|
|
private: // not implemented
|
|
|
|
|
NetDisable(const NetDisable&);
|
|
|
|
|
NetDisable& operator= (const NetDisable&);
|
|
|
|
|
};
|
|
|
|
|
|
2000-04-04 05:20:15 +02:00
|
|
|
/*
|
|
|
|
|
* A NetEvent is an object that represents an event object, that is
|
|
|
|
|
* objects declared like so in Verilog:
|
|
|
|
|
*
|
|
|
|
|
* event foo;
|
|
|
|
|
*
|
|
|
|
|
* Once an object of this type exists, behavioral code can wait on the
|
|
|
|
|
* event or trigger the event. Event waits refer to this object, as do
|
|
|
|
|
* the event trigger statements.
|
|
|
|
|
*
|
|
|
|
|
* The NetEvWait class represents a thread wait for an event. When
|
|
|
|
|
* this statement is executed, it starts waiting on the
|
|
|
|
|
* event. Conceptually, it puts itself on the event list for the
|
|
|
|
|
* referenced event. When the event is triggered, the wit ends its
|
|
|
|
|
* block and starts the associated statement.
|
|
|
|
|
*
|
|
|
|
|
* The NetEvTrig class represents trigger statements. Executing this
|
|
|
|
|
* statement causes the referenced event to be triggered, which it
|
2000-04-17 01:32:18 +02:00
|
|
|
* turn awakens the waiting threads. Each NetEvTrig object references
|
|
|
|
|
* exactly one event object.
|
2000-04-10 07:26:05 +02:00
|
|
|
*
|
|
|
|
|
* The NetEvProbe class is the structural equivilent of the NetEvTrig,
|
|
|
|
|
* in that it is a node and watches bit values that it receives. It
|
|
|
|
|
* checks for edges then if appropriate triggers the associated
|
2000-04-17 01:32:18 +02:00
|
|
|
* NetEvent. Each NetEvProbe references exactly one event object, and
|
|
|
|
|
* the NetEvent objects have a list of NetEvProbe objects that
|
|
|
|
|
* reference it.
|
2000-04-04 05:20:15 +02:00
|
|
|
*/
|
|
|
|
|
class NetEvent : public LineInfo {
|
|
|
|
|
|
|
|
|
|
friend class NetScope;
|
2000-04-12 22:02:52 +02:00
|
|
|
friend class NetEvProbe;
|
2000-04-17 01:32:18 +02:00
|
|
|
friend class NetEvTrig;
|
|
|
|
|
friend class NetEvWait;
|
2000-04-04 05:20:15 +02:00
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
explicit NetEvent (const string&n);
|
|
|
|
|
~NetEvent();
|
|
|
|
|
|
2000-10-04 18:30:39 +02:00
|
|
|
const char* name() const;
|
2000-04-04 05:20:15 +02:00
|
|
|
string full_name() const;
|
|
|
|
|
|
2000-04-12 22:02:52 +02:00
|
|
|
// Get information about probes connected to me.
|
|
|
|
|
unsigned nprobe() const;
|
|
|
|
|
NetEvProbe* probe(unsigned);
|
|
|
|
|
|
2000-04-17 01:32:18 +02:00
|
|
|
// Return the number of NetEvWait nodes that reference me.
|
|
|
|
|
unsigned nwait() const;
|
|
|
|
|
|
2000-04-18 06:50:19 +02:00
|
|
|
unsigned ntrig() const;
|
|
|
|
|
|
2000-04-04 05:20:15 +02:00
|
|
|
NetScope* scope();
|
|
|
|
|
const NetScope* scope() const;
|
|
|
|
|
|
2000-05-31 04:26:49 +02:00
|
|
|
// Locate the first event that matches my behavior and
|
|
|
|
|
// monitors the same signals.
|
2000-05-27 21:33:23 +02:00
|
|
|
NetEvent* find_similar_event();
|
|
|
|
|
|
2000-05-31 04:26:49 +02:00
|
|
|
// This method replaces pointers to me with pointers to
|
|
|
|
|
// that. It is typically used to replace similar events
|
|
|
|
|
// located by the find_similar_event method.
|
|
|
|
|
void replace_event(NetEvent*that);
|
|
|
|
|
|
2000-04-04 05:20:15 +02:00
|
|
|
private:
|
2000-10-04 18:30:39 +02:00
|
|
|
char* name_;
|
2000-04-04 05:20:15 +02:00
|
|
|
|
|
|
|
|
// The NetScope class uses these to list the events.
|
|
|
|
|
NetScope*scope_;
|
|
|
|
|
NetEvent*snext_;
|
|
|
|
|
|
2000-04-12 22:02:52 +02:00
|
|
|
// Use these methods to list the probes attached to me.
|
|
|
|
|
NetEvProbe*probes_;
|
|
|
|
|
|
2000-04-17 01:32:18 +02:00
|
|
|
// Use these methods to list the triggers attached to me.
|
|
|
|
|
NetEvTrig* trig_;
|
|
|
|
|
|
|
|
|
|
// Use This member to count references by NetEvWait objects.
|
|
|
|
|
unsigned waitref_;
|
2000-05-31 04:26:49 +02:00
|
|
|
struct wcell_ {
|
|
|
|
|
NetEvWait*obj;
|
|
|
|
|
struct wcell_*next;
|
|
|
|
|
};
|
|
|
|
|
struct wcell_ *wlist_;
|
2000-04-17 01:32:18 +02:00
|
|
|
|
2000-04-04 05:20:15 +02:00
|
|
|
private: // not implemented
|
|
|
|
|
NetEvent(const NetEvent&);
|
|
|
|
|
NetEvent& operator= (const NetEvent&);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
class NetEvTrig : public NetProc {
|
|
|
|
|
|
2000-04-18 06:50:19 +02:00
|
|
|
friend class NetEvent;
|
|
|
|
|
|
2000-04-04 05:20:15 +02:00
|
|
|
public:
|
|
|
|
|
explicit NetEvTrig(NetEvent*tgt);
|
|
|
|
|
~NetEvTrig();
|
|
|
|
|
|
|
|
|
|
const NetEvent*event() const;
|
|
|
|
|
|
2000-08-08 03:50:42 +02:00
|
|
|
virtual bool emit_proc(struct target_t*) const;
|
2000-04-04 05:20:15 +02:00
|
|
|
virtual void dump(ostream&, unsigned ind) const;
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
NetEvent*event_;
|
2000-04-17 01:32:18 +02:00
|
|
|
// This is used to place me in the NetEvents lists of triggers.
|
|
|
|
|
NetEvTrig*enext_;
|
2000-04-04 05:20:15 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
class NetEvWait : public NetProc {
|
|
|
|
|
|
|
|
|
|
public:
|
2000-04-12 06:23:57 +02:00
|
|
|
explicit NetEvWait(NetProc*st);
|
2000-04-04 05:20:15 +02:00
|
|
|
~NetEvWait();
|
|
|
|
|
|
2000-04-12 06:23:57 +02:00
|
|
|
void add_event(NetEvent*tgt);
|
2000-05-31 04:26:49 +02:00
|
|
|
void replace_event(NetEvent*orig, NetEvent*repl);
|
2000-04-12 06:23:57 +02:00
|
|
|
|
|
|
|
|
unsigned nevents() const;
|
|
|
|
|
const NetEvent*event(unsigned) const;
|
2000-04-12 22:02:52 +02:00
|
|
|
NetEvent*event(unsigned);
|
|
|
|
|
|
|
|
|
|
NetProc*statement();
|
2000-04-04 05:20:15 +02:00
|
|
|
|
2000-08-08 03:50:42 +02:00
|
|
|
virtual bool emit_proc(struct target_t*) const;
|
|
|
|
|
bool emit_recurse(struct target_t*) const;
|
2000-04-12 22:02:52 +02:00
|
|
|
virtual int match_proc(struct proc_match_t*);
|
2000-04-04 05:20:15 +02:00
|
|
|
virtual void dump(ostream&, unsigned ind) const;
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
NetProc*statement_;
|
2000-04-12 06:23:57 +02:00
|
|
|
|
|
|
|
|
unsigned nevents_;
|
|
|
|
|
NetEvent**events_;
|
2000-04-04 05:20:15 +02:00
|
|
|
};
|
|
|
|
|
|
2000-04-10 07:26:05 +02:00
|
|
|
class NetEvProbe : public NetNode {
|
|
|
|
|
|
2000-04-12 22:02:52 +02:00
|
|
|
friend class NetEvent;
|
|
|
|
|
|
2000-04-10 07:26:05 +02:00
|
|
|
public:
|
|
|
|
|
enum edge_t { ANYEDGE, POSEDGE, NEGEDGE };
|
|
|
|
|
|
|
|
|
|
explicit NetEvProbe(const string&n, NetEvent*tgt,
|
|
|
|
|
edge_t t, unsigned p);
|
|
|
|
|
~NetEvProbe();
|
|
|
|
|
|
|
|
|
|
edge_t edge() const;
|
2000-05-27 21:33:23 +02:00
|
|
|
NetEvent* event();
|
2000-04-10 07:26:05 +02:00
|
|
|
const NetEvent* event() const;
|
|
|
|
|
|
2000-08-14 06:39:56 +02:00
|
|
|
virtual bool emit_node(struct target_t*) const;
|
2000-04-10 07:26:05 +02:00
|
|
|
virtual void dump_node(ostream&, unsigned ind) const;
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
NetEvent*event_;
|
|
|
|
|
edge_t edge_;
|
2000-04-12 22:02:52 +02:00
|
|
|
// The NetEvent class uses this to list me.
|
|
|
|
|
NetEvProbe*enext_;
|
2000-04-10 07:26:05 +02:00
|
|
|
};
|
|
|
|
|
|
2000-04-22 06:20:19 +02:00
|
|
|
/*
|
|
|
|
|
* The force statement causes the r-val net to be forced onto the
|
|
|
|
|
* l-val net when it is executed. The code generator is expected to
|
|
|
|
|
* know what that means. All the expressions are structural and behave
|
|
|
|
|
* like nets.
|
|
|
|
|
*
|
|
|
|
|
* This class is a NetProc because it it turned on by procedural
|
|
|
|
|
* behavior. However, it is also a NetNode because it connects to
|
|
|
|
|
* nets, and when activated follows the net values.
|
|
|
|
|
*/
|
|
|
|
|
class NetForce : public NetProc, public NetNode {
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
explicit NetForce(const string&n, NetNet*l);
|
|
|
|
|
~NetForce();
|
|
|
|
|
|
2000-05-07 06:37:55 +02:00
|
|
|
const Link& lval_pin(unsigned) const;
|
2000-04-22 06:20:19 +02:00
|
|
|
|
|
|
|
|
virtual void dump(ostream&, unsigned ind) const;
|
2000-08-08 03:50:42 +02:00
|
|
|
virtual bool emit_proc(struct target_t*) const;
|
2000-04-22 06:20:19 +02:00
|
|
|
virtual void dump_node(ostream&, unsigned ind) const;
|
2000-08-14 06:39:56 +02:00
|
|
|
virtual bool emit_node(struct target_t*) const;
|
2000-04-22 06:20:19 +02:00
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
NetNet*lval_;
|
|
|
|
|
};
|
|
|
|
|
|
1999-06-19 23:06:16 +02:00
|
|
|
/*
|
|
|
|
|
* A forever statement is executed over and over again forever. Or
|
|
|
|
|
* until its block is disabled.
|
|
|
|
|
*/
|
|
|
|
|
class NetForever : public NetProc {
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
explicit NetForever(NetProc*s);
|
|
|
|
|
~NetForever();
|
|
|
|
|
|
2000-08-08 03:50:42 +02:00
|
|
|
void emit_recurse(struct target_t*) const;
|
1999-06-19 23:06:16 +02:00
|
|
|
|
2000-08-08 03:50:42 +02:00
|
|
|
virtual bool emit_proc(struct target_t*) const;
|
1999-06-19 23:06:16 +02:00
|
|
|
virtual void dump(ostream&, unsigned ind) const;
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
NetProc*statement_;
|
|
|
|
|
};
|
|
|
|
|
|
1999-09-01 00:38:29 +02:00
|
|
|
/*
|
|
|
|
|
* A funciton definition is elaborated just like a task, though by now
|
|
|
|
|
* it is certain that the first parameter (a phantom parameter) is the
|
|
|
|
|
* output and all the remaining parameters are the inputs. This makes
|
|
|
|
|
* for easy code generation in targets that support behavioral descriptions.
|
|
|
|
|
*/
|
1999-08-26 00:22:41 +02:00
|
|
|
class NetFuncDef {
|
|
|
|
|
|
|
|
|
|
public:
|
2000-03-08 05:36:53 +01:00
|
|
|
NetFuncDef(NetScope*, const svector<NetNet*>&po);
|
1999-08-26 00:22:41 +02:00
|
|
|
~NetFuncDef();
|
|
|
|
|
|
1999-09-01 22:46:19 +02:00
|
|
|
void set_proc(NetProc*st);
|
|
|
|
|
|
2000-03-08 05:36:53 +01:00
|
|
|
const string name() const;
|
1999-09-01 00:38:29 +02:00
|
|
|
const NetProc*proc() const;
|
2000-03-08 05:36:53 +01:00
|
|
|
NetScope*scope();
|
1999-09-01 00:38:29 +02:00
|
|
|
|
1999-09-01 22:46:19 +02:00
|
|
|
unsigned port_count() const;
|
|
|
|
|
const NetNet*port(unsigned idx) const;
|
|
|
|
|
|
1999-08-26 00:22:41 +02:00
|
|
|
virtual void dump(ostream&, unsigned ind) const;
|
|
|
|
|
|
|
|
|
|
private:
|
2000-03-08 05:36:53 +01:00
|
|
|
NetScope*scope_;
|
1999-08-26 00:22:41 +02:00
|
|
|
NetProc*statement_;
|
1999-09-01 00:38:29 +02:00
|
|
|
svector<NetNet*>ports_;
|
1999-08-26 00:22:41 +02:00
|
|
|
};
|
|
|
|
|
|
2000-07-07 06:53:53 +02:00
|
|
|
/*
|
|
|
|
|
* This class represents delay statements of the form:
|
|
|
|
|
*
|
|
|
|
|
* #<expr> <statement>
|
|
|
|
|
*
|
|
|
|
|
* Where the statement may be null. The delay is evaluated at
|
|
|
|
|
* elaboration time to make a constant unsigned long that is the delay
|
|
|
|
|
* in simulation ticks.
|
|
|
|
|
*
|
|
|
|
|
* If the delay expression is non-constant, construct the NetPDelay
|
|
|
|
|
* object with a NetExpr* instead of the d value, and use th expr()
|
|
|
|
|
* method to get the expression. If expr() returns 0, use the delay()
|
|
|
|
|
* method to get the constant delay.
|
|
|
|
|
*/
|
1998-11-04 00:28:49 +01:00
|
|
|
class NetPDelay : public NetProc {
|
|
|
|
|
|
|
|
|
|
public:
|
2000-07-07 06:53:53 +02:00
|
|
|
NetPDelay(unsigned long d, NetProc*st);
|
|
|
|
|
NetPDelay(NetExpr* d, NetProc*st);
|
|
|
|
|
~NetPDelay();
|
1998-11-04 00:28:49 +01:00
|
|
|
|
2000-07-07 06:53:53 +02:00
|
|
|
unsigned long delay() const;
|
|
|
|
|
const NetExpr*expr() const;
|
1998-11-04 00:28:49 +01:00
|
|
|
|
2000-08-08 03:50:42 +02:00
|
|
|
virtual bool emit_proc(struct target_t*) const;
|
1998-11-04 00:28:49 +01:00
|
|
|
virtual void dump(ostream&, unsigned ind) const;
|
|
|
|
|
|
2000-08-08 03:50:42 +02:00
|
|
|
bool emit_proc_recurse(struct target_t*) const;
|
1998-11-04 00:28:49 +01:00
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
unsigned long delay_;
|
2000-07-07 06:53:53 +02:00
|
|
|
NetExpr*expr_;
|
1998-11-04 00:28:49 +01:00
|
|
|
NetProc*statement_;
|
|
|
|
|
};
|
|
|
|
|
|
1999-06-19 23:06:16 +02:00
|
|
|
/*
|
|
|
|
|
* A repeat statement is executed some fixed number of times.
|
|
|
|
|
*/
|
|
|
|
|
class NetRepeat : public NetProc {
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
explicit NetRepeat(NetExpr*e, NetProc*s);
|
|
|
|
|
~NetRepeat();
|
|
|
|
|
|
|
|
|
|
const NetExpr*expr() const;
|
2000-08-08 03:50:42 +02:00
|
|
|
void emit_recurse(struct target_t*) const;
|
1999-06-19 23:06:16 +02:00
|
|
|
|
2000-08-08 03:50:42 +02:00
|
|
|
virtual bool emit_proc(struct target_t*) const;
|
1999-06-19 23:06:16 +02:00
|
|
|
virtual void dump(ostream&, unsigned ind) const;
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
NetExpr*expr_;
|
|
|
|
|
NetProc*statement_;
|
|
|
|
|
};
|
|
|
|
|
|
2000-04-23 05:45:24 +02:00
|
|
|
/*
|
|
|
|
|
* The procedural release statement (the opposite of force) releases
|
|
|
|
|
* any force expressions attached to the bits of the wire or reg. The
|
|
|
|
|
* lval is the expression of the "release <expr>;" statement with the
|
|
|
|
|
* expr elaborated to a net.
|
|
|
|
|
*/
|
|
|
|
|
class NetRelease : public NetProc {
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
explicit NetRelease(NetNet*l);
|
|
|
|
|
~NetRelease();
|
|
|
|
|
|
|
|
|
|
const NetNet*lval() const;
|
|
|
|
|
|
2000-08-08 03:50:42 +02:00
|
|
|
virtual bool emit_proc(struct target_t*) const;
|
2000-04-23 05:45:24 +02:00
|
|
|
virtual void dump(ostream&, unsigned ind) const;
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
NetNet*lval_;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
1999-07-03 04:12:51 +02:00
|
|
|
/*
|
|
|
|
|
* The NetSTask class is a call to a system task. These kinds of tasks
|
|
|
|
|
* are generally handled very simply in the target. They certainly are
|
|
|
|
|
* handled differently from user defined tasks because ivl knows all
|
|
|
|
|
* about the user defined tasks.
|
|
|
|
|
*/
|
|
|
|
|
class NetSTask : public NetProc {
|
1998-11-04 00:28:49 +01:00
|
|
|
|
|
|
|
|
public:
|
1999-07-03 04:12:51 +02:00
|
|
|
NetSTask(const string&na, const svector<NetExpr*>&);
|
|
|
|
|
~NetSTask();
|
1998-11-04 00:28:49 +01:00
|
|
|
|
2000-09-22 05:58:30 +02:00
|
|
|
const char* name() const;
|
1998-11-04 00:28:49 +01:00
|
|
|
|
2000-09-22 05:58:30 +02:00
|
|
|
unsigned nparms() const;
|
1998-11-04 00:28:49 +01:00
|
|
|
|
1999-07-03 04:12:51 +02:00
|
|
|
const NetExpr* parm(unsigned idx) const;
|
1998-11-04 00:28:49 +01:00
|
|
|
|
2000-08-08 03:50:42 +02:00
|
|
|
virtual bool emit_proc(struct target_t*) const;
|
1998-11-04 00:28:49 +01:00
|
|
|
virtual void dump(ostream&, unsigned ind) const;
|
|
|
|
|
|
|
|
|
|
private:
|
2000-09-22 05:58:30 +02:00
|
|
|
char* name_;
|
1999-07-03 04:12:51 +02:00
|
|
|
svector<NetExpr*>parms_;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* This class represents an elaborated class definition. NetUTask
|
|
|
|
|
* classes may refer to objects of this type to get the meaning of the
|
|
|
|
|
* defined task.
|
2000-04-18 03:02:53 +02:00
|
|
|
*
|
|
|
|
|
* The task also introduces a scope, and the parameters are actually
|
|
|
|
|
* reg objects in the new scope. The task is called by the calling
|
|
|
|
|
* thread assigning (blocking assignment) to the in and inout
|
|
|
|
|
* paramters, then invoking the thread, and finally assigning out the
|
|
|
|
|
* output and inout variables. The variables accessable as ports are
|
|
|
|
|
* also elaborated and accessible as ordinary reg objects.
|
1999-07-03 04:12:51 +02:00
|
|
|
*/
|
|
|
|
|
class NetTaskDef {
|
|
|
|
|
|
|
|
|
|
public:
|
1999-09-30 23:28:34 +02:00
|
|
|
NetTaskDef(const string&n, const svector<NetNet*>&po);
|
1999-07-03 04:12:51 +02:00
|
|
|
~NetTaskDef();
|
|
|
|
|
|
1999-09-30 23:28:34 +02:00
|
|
|
void set_proc(NetProc*p);
|
|
|
|
|
|
2000-04-18 03:02:53 +02:00
|
|
|
const string& name() const;
|
|
|
|
|
const NetProc*proc() const;
|
1999-07-03 04:12:51 +02:00
|
|
|
|
2000-04-18 03:02:53 +02:00
|
|
|
unsigned port_count() const;
|
1999-07-24 04:11:19 +02:00
|
|
|
NetNet*port(unsigned idx);
|
|
|
|
|
|
1999-07-03 04:12:51 +02:00
|
|
|
void dump(ostream&, unsigned) const;
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
string name_;
|
|
|
|
|
NetProc*proc_;
|
1999-07-24 04:11:19 +02:00
|
|
|
svector<NetNet*>ports_;
|
1999-07-03 04:12:51 +02:00
|
|
|
|
|
|
|
|
private: // not implemented
|
|
|
|
|
NetTaskDef(const NetTaskDef&);
|
|
|
|
|
NetTaskDef& operator= (const NetTaskDef&);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/*
|
1999-09-01 00:38:29 +02:00
|
|
|
* This node represents a function call in an expression. The object
|
|
|
|
|
* contains a pointer to the function definition, which is used to
|
|
|
|
|
* locate the value register and input expressions.
|
|
|
|
|
*
|
|
|
|
|
* The NetNet parameter to the constructor is the *register* NetNet
|
|
|
|
|
* that receives the result of the function, and the NetExpr list is
|
|
|
|
|
* the paraneters passed to the function.
|
|
|
|
|
*/
|
|
|
|
|
class NetEUFunc : public NetExpr {
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
NetEUFunc(NetFuncDef*, NetESignal*, svector<NetExpr*>&);
|
|
|
|
|
~NetEUFunc();
|
|
|
|
|
|
2000-03-08 05:36:53 +01:00
|
|
|
const string name() const;
|
1999-09-01 00:38:29 +02:00
|
|
|
|
|
|
|
|
const NetESignal*result() const;
|
1999-09-01 22:46:19 +02:00
|
|
|
unsigned parm_count() const;
|
|
|
|
|
const NetExpr* parm(unsigned idx) const;
|
|
|
|
|
|
|
|
|
|
const NetFuncDef* definition() const;
|
1999-09-01 00:38:29 +02:00
|
|
|
|
|
|
|
|
virtual bool set_width(unsigned);
|
|
|
|
|
virtual void dump(ostream&) const;
|
|
|
|
|
|
|
|
|
|
virtual void expr_scan(struct expr_scan_t*) const;
|
|
|
|
|
virtual NetEUFunc*dup_expr() const;
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
NetFuncDef*func_;
|
|
|
|
|
NetESignal*result_;
|
|
|
|
|
svector<NetExpr*> parms_;
|
|
|
|
|
|
|
|
|
|
private: // not implemented
|
|
|
|
|
NetEUFunc(const NetEUFunc&);
|
|
|
|
|
NetEUFunc& operator= (const NetEUFunc&);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* A call to a user defined task is elaborated into this object. This
|
|
|
|
|
* contains a pointer to the elaborated task definition, but is a
|
|
|
|
|
* NetProc object so that it can be linked into statements.
|
1999-07-03 04:12:51 +02:00
|
|
|
*/
|
|
|
|
|
class NetUTask : public NetProc {
|
|
|
|
|
|
|
|
|
|
public:
|
1999-07-24 04:11:19 +02:00
|
|
|
NetUTask(NetTaskDef*);
|
1999-07-03 04:12:51 +02:00
|
|
|
~NetUTask();
|
|
|
|
|
|
1999-07-07 06:20:57 +02:00
|
|
|
const string& name() const { return task_->name(); }
|
1999-07-03 04:12:51 +02:00
|
|
|
|
2000-08-08 03:50:42 +02:00
|
|
|
virtual bool emit_proc(struct target_t*) const;
|
1999-07-03 04:12:51 +02:00
|
|
|
virtual void dump(ostream&, unsigned ind) const;
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
NetTaskDef*task_;
|
1998-11-04 00:28:49 +01:00
|
|
|
};
|
|
|
|
|
|
1998-11-09 19:55:33 +01:00
|
|
|
/*
|
|
|
|
|
* The while statement is a condition that is tested in the front of
|
|
|
|
|
* each iteration, and a statement (a NetProc) that is executed as
|
|
|
|
|
* long as the condition is true.
|
|
|
|
|
*/
|
|
|
|
|
class NetWhile : public NetProc {
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
NetWhile(NetExpr*c, NetProc*p)
|
|
|
|
|
: cond_(c), proc_(p) { }
|
|
|
|
|
|
1999-05-30 03:11:46 +02:00
|
|
|
const NetExpr*expr() const { return cond_; }
|
1998-11-09 19:55:33 +01:00
|
|
|
|
2000-08-08 03:50:42 +02:00
|
|
|
void emit_proc_recurse(struct target_t*) const;
|
1998-11-09 19:55:33 +01:00
|
|
|
|
2000-08-08 03:50:42 +02:00
|
|
|
virtual bool emit_proc(struct target_t*) const;
|
1998-11-09 19:55:33 +01:00
|
|
|
virtual void dump(ostream&, unsigned ind) const;
|
|
|
|
|
|
|
|
|
|
private:
|
1999-05-30 03:11:46 +02:00
|
|
|
NetExpr* cond_;
|
1998-11-09 19:55:33 +01:00
|
|
|
NetProc*proc_;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
1999-09-22 18:57:23 +02:00
|
|
|
/*
|
|
|
|
|
* The is the top of any process. It carries the type (initial or
|
|
|
|
|
* always) and a pointer to the statement, probably a block, that
|
|
|
|
|
* makes up the process.
|
|
|
|
|
*/
|
1999-02-01 01:26:48 +01:00
|
|
|
class NetProcTop : public LineInfo {
|
1998-11-04 00:28:49 +01:00
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
enum Type { KINITIAL, KALWAYS };
|
|
|
|
|
|
2000-10-28 02:51:41 +02:00
|
|
|
NetProcTop(NetScope*s, Type t, class NetProc*st);
|
1999-07-18 07:52:46 +02:00
|
|
|
~NetProcTop();
|
1998-11-04 00:28:49 +01:00
|
|
|
|
|
|
|
|
Type type() const { return type_; }
|
1999-07-18 23:17:50 +02:00
|
|
|
NetProc*statement();
|
|
|
|
|
const NetProc*statement() const;
|
1998-11-04 00:28:49 +01:00
|
|
|
|
2000-11-11 01:03:36 +01:00
|
|
|
NetScope*scope();
|
2000-10-28 02:51:41 +02:00
|
|
|
const NetScope*scope() const;
|
|
|
|
|
|
1998-11-04 00:28:49 +01:00
|
|
|
void dump(ostream&, unsigned ind) const;
|
2000-08-08 03:50:42 +02:00
|
|
|
bool emit(struct target_t*tgt) const;
|
1998-11-04 00:28:49 +01:00
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
const Type type_;
|
|
|
|
|
NetProc*const statement_;
|
|
|
|
|
|
2000-10-28 02:51:41 +02:00
|
|
|
NetScope*scope_;
|
1998-11-04 00:28:49 +01:00
|
|
|
friend class Design;
|
|
|
|
|
NetProcTop*next_;
|
|
|
|
|
};
|
|
|
|
|
|
1999-03-15 03:43:32 +01:00
|
|
|
/*
|
|
|
|
|
* This class represents a binary operator, with the left and right
|
|
|
|
|
* operands and a single character for the operator. The operator
|
|
|
|
|
* values are:
|
|
|
|
|
*
|
|
|
|
|
* ^ -- Bit-wise exclusive OR
|
|
|
|
|
* + -- Arithmetic add
|
1999-05-16 07:08:42 +02:00
|
|
|
* - -- Arithmetic minus
|
|
|
|
|
* * -- Arithmetic multiply
|
|
|
|
|
* / -- Arithmetic divide
|
|
|
|
|
* % -- Arithmetic modulus
|
1999-03-15 03:43:32 +01:00
|
|
|
* & -- Bit-wise AND
|
|
|
|
|
* | -- Bit-wise OR
|
1999-07-31 05:16:54 +02:00
|
|
|
* < -- Less then
|
|
|
|
|
* > -- Greater then
|
1999-03-15 03:43:32 +01:00
|
|
|
* e -- Logical equality (==)
|
|
|
|
|
* E -- Case equality (===)
|
1999-05-16 07:08:42 +02:00
|
|
|
* L -- Less or equal
|
|
|
|
|
* G -- Greater or equal
|
1999-03-15 03:43:32 +01:00
|
|
|
* n -- Logical inequality (!=)
|
|
|
|
|
* N -- Case inequality (!==)
|
|
|
|
|
* a -- Logical AND (&&)
|
|
|
|
|
* o -- Logical OR (||)
|
1999-09-30 04:43:01 +02:00
|
|
|
* O -- Bit-wise NOR
|
1999-05-16 07:08:42 +02:00
|
|
|
* l -- Left shift (<<)
|
|
|
|
|
* r -- Right shift (>>)
|
1999-09-30 04:43:01 +02:00
|
|
|
* X -- Bitwise exclusive NOR (~^)
|
1999-03-15 03:43:32 +01:00
|
|
|
*/
|
1998-11-07 18:05:05 +01:00
|
|
|
class NetEBinary : public NetExpr {
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
NetEBinary(char op, NetExpr*l, NetExpr*r);
|
|
|
|
|
~NetEBinary();
|
|
|
|
|
|
1999-05-30 03:11:46 +02:00
|
|
|
const NetExpr*left() const { return left_; }
|
|
|
|
|
const NetExpr*right() const { return right_; }
|
1998-11-07 18:05:05 +01:00
|
|
|
|
|
|
|
|
char op() const { return op_; }
|
|
|
|
|
|
1999-05-27 06:13:08 +02:00
|
|
|
virtual bool set_width(unsigned w);
|
1998-11-07 20:17:10 +01:00
|
|
|
|
1999-05-30 03:11:46 +02:00
|
|
|
virtual NetEBinary* dup_expr() const;
|
|
|
|
|
|
1998-11-07 18:05:05 +01:00
|
|
|
virtual void expr_scan(struct expr_scan_t*) const;
|
|
|
|
|
virtual void dump(ostream&) const;
|
|
|
|
|
|
1999-07-31 05:16:54 +02:00
|
|
|
protected:
|
1998-11-07 18:05:05 +01:00
|
|
|
char op_;
|
1999-05-30 03:11:46 +02:00
|
|
|
NetExpr* left_;
|
|
|
|
|
NetExpr* right_;
|
1999-09-18 03:53:08 +02:00
|
|
|
|
|
|
|
|
virtual void eval_sub_tree_();
|
1998-11-07 18:05:05 +01:00
|
|
|
};
|
|
|
|
|
|
1999-07-31 05:16:54 +02:00
|
|
|
/*
|
|
|
|
|
* The addition operators have slightly more complex width
|
|
|
|
|
* calculations because there is the optional carry bit that can be
|
|
|
|
|
* used. The operators covered by this class are:
|
|
|
|
|
* + -- Arithmetic add
|
|
|
|
|
* - -- Arithmetic minus
|
|
|
|
|
*/
|
|
|
|
|
class NetEBAdd : public NetEBinary {
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
NetEBAdd(char op, NetExpr*l, NetExpr*r);
|
|
|
|
|
~NetEBAdd();
|
|
|
|
|
|
|
|
|
|
virtual bool set_width(unsigned w);
|
1999-10-11 01:29:37 +02:00
|
|
|
virtual NetEBAdd* dup_expr() const;
|
|
|
|
|
virtual NetEConst* eval_tree();
|
1999-11-05 05:40:40 +01:00
|
|
|
virtual NetNet* synthesize(Design*);
|
1999-07-31 05:16:54 +02:00
|
|
|
};
|
|
|
|
|
|
2000-04-28 20:43:23 +02:00
|
|
|
/*
|
|
|
|
|
* This class represents the integer division operators.
|
|
|
|
|
* / -- Divide
|
|
|
|
|
* % -- Modulus
|
|
|
|
|
*/
|
|
|
|
|
class NetEBDiv : public NetEBinary {
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
NetEBDiv(char op, NetExpr*l, NetExpr*r);
|
|
|
|
|
~NetEBDiv();
|
|
|
|
|
|
|
|
|
|
virtual bool set_width(unsigned w);
|
|
|
|
|
virtual NetEBDiv* dup_expr() const;
|
|
|
|
|
virtual NetEConst* eval_tree();
|
|
|
|
|
virtual NetNet* synthesize(Design*);
|
|
|
|
|
};
|
|
|
|
|
|
1999-07-31 05:16:54 +02:00
|
|
|
/*
|
|
|
|
|
* The bitwise binary operators are represented by this class. This is
|
|
|
|
|
* a specialization of the binary operator, so is derived from
|
|
|
|
|
* NetEBinary. The particular constraints on these operators are that
|
|
|
|
|
* operand and result widths match exactly, and each bit slice of the
|
|
|
|
|
* operation can be represented by a simple gate. The operators
|
|
|
|
|
* covered by this class are:
|
|
|
|
|
*
|
|
|
|
|
* ^ -- Bit-wise exclusive OR
|
|
|
|
|
* & -- Bit-wise AND
|
|
|
|
|
* | -- Bit-wise OR
|
1999-09-30 04:43:01 +02:00
|
|
|
* O -- Bit-wise NOR
|
|
|
|
|
* X -- Bit-wise XNOR (~^)
|
1999-07-31 05:16:54 +02:00
|
|
|
*/
|
|
|
|
|
class NetEBBits : public NetEBinary {
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
NetEBBits(char op, NetExpr*l, NetExpr*r);
|
|
|
|
|
~NetEBBits();
|
|
|
|
|
|
|
|
|
|
virtual bool set_width(unsigned w);
|
1999-10-11 01:29:37 +02:00
|
|
|
virtual NetEBBits* dup_expr() const;
|
2001-01-02 04:23:40 +01:00
|
|
|
virtual NetEConst* eval_tree();
|
1999-11-02 05:55:34 +01:00
|
|
|
|
|
|
|
|
virtual NetNet* synthesize(Design*);
|
1999-07-31 05:16:54 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* The binary comparison operators are handled by this class. This
|
|
|
|
|
* this case the bit width of the expression is 1 bit, and the
|
|
|
|
|
* operands take their natural widths. The supported operators are:
|
|
|
|
|
*
|
|
|
|
|
* < -- Less then
|
|
|
|
|
* > -- Greater then
|
|
|
|
|
* e -- Logical equality (==)
|
|
|
|
|
* E -- Case equality (===)
|
|
|
|
|
* L -- Less or equal (<=)
|
|
|
|
|
* G -- Greater or equal (>=)
|
|
|
|
|
* n -- Logical inequality (!=)
|
|
|
|
|
* N -- Case inequality (!==)
|
|
|
|
|
*/
|
|
|
|
|
class NetEBComp : public NetEBinary {
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
NetEBComp(char op, NetExpr*l, NetExpr*r);
|
|
|
|
|
~NetEBComp();
|
|
|
|
|
|
|
|
|
|
virtual bool set_width(unsigned w);
|
1999-10-11 01:29:37 +02:00
|
|
|
virtual NetEBComp* dup_expr() const;
|
|
|
|
|
virtual NetEConst* eval_tree();
|
1999-09-18 03:53:08 +02:00
|
|
|
|
2000-04-17 01:32:18 +02:00
|
|
|
virtual NetNet* synthesize(Design*);
|
|
|
|
|
|
1999-09-18 03:53:08 +02:00
|
|
|
private:
|
1999-10-11 01:29:37 +02:00
|
|
|
NetEConst*eval_eqeq_();
|
|
|
|
|
NetEConst*eval_leeq_();
|
2000-09-29 06:42:56 +02:00
|
|
|
NetEConst*eval_neeq_();
|
2001-01-04 17:49:50 +01:00
|
|
|
NetEConst*eval_eqeqeq_();
|
|
|
|
|
NetEConst*eval_neeqeq_();
|
1999-07-31 05:16:54 +02:00
|
|
|
};
|
|
|
|
|
|
1999-09-23 02:21:54 +02:00
|
|
|
/*
|
|
|
|
|
* The binary logical operators are those that return boolean
|
|
|
|
|
* results. The supported operators are:
|
|
|
|
|
*
|
|
|
|
|
* a -- Logical AND (&&)
|
2000-11-29 03:09:52 +01:00
|
|
|
* o -- Logical OR (||)
|
1999-09-23 02:21:54 +02:00
|
|
|
*/
|
|
|
|
|
class NetEBLogic : public NetEBinary {
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
NetEBLogic(char op, NetExpr*l, NetExpr*r);
|
|
|
|
|
~NetEBLogic();
|
|
|
|
|
|
|
|
|
|
virtual bool set_width(unsigned w);
|
1999-10-11 01:29:37 +02:00
|
|
|
virtual NetEBLogic* dup_expr() const;
|
|
|
|
|
virtual NetEConst* eval_tree();
|
2000-11-29 03:09:52 +01:00
|
|
|
virtual NetNet* synthesize(Design*);
|
1999-09-23 02:21:54 +02:00
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
2000-01-13 04:35:35 +01:00
|
|
|
/*
|
|
|
|
|
* Support the binary multiplication (*) operator.
|
|
|
|
|
*/
|
|
|
|
|
class NetEBMult : public NetEBinary {
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
NetEBMult(char op, NetExpr*l, NetExpr*r);
|
|
|
|
|
~NetEBMult();
|
|
|
|
|
|
|
|
|
|
virtual bool set_width(unsigned w);
|
|
|
|
|
virtual NetEBMult* dup_expr() const;
|
|
|
|
|
virtual NetEConst* eval_tree();
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
1999-09-23 05:56:57 +02:00
|
|
|
/*
|
|
|
|
|
* The binary logical operators are those that return boolean
|
|
|
|
|
* results. The supported operators are:
|
|
|
|
|
*
|
|
|
|
|
* l -- left shift (<<)
|
|
|
|
|
* r -- right shift (>>)
|
|
|
|
|
*/
|
|
|
|
|
class NetEBShift : public NetEBinary {
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
NetEBShift(char op, NetExpr*l, NetExpr*r);
|
|
|
|
|
~NetEBShift();
|
|
|
|
|
|
|
|
|
|
virtual bool set_width(unsigned w);
|
1999-10-11 01:29:37 +02:00
|
|
|
virtual NetEBShift* dup_expr() const;
|
|
|
|
|
virtual NetEConst* eval_tree();
|
1999-09-23 05:56:57 +02:00
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
1999-06-09 05:00:05 +02:00
|
|
|
/*
|
|
|
|
|
* This expression node supports the concat expression. This is an
|
|
|
|
|
* operator that just glues the results of many expressions into a
|
|
|
|
|
* single value.
|
|
|
|
|
*
|
|
|
|
|
* Note that the class stores the parameter expressions in source code
|
|
|
|
|
* order. That is, the parm(0) is placed in the most significant
|
|
|
|
|
* position of the result.
|
|
|
|
|
*/
|
|
|
|
|
class NetEConcat : public NetExpr {
|
|
|
|
|
|
|
|
|
|
public:
|
1999-09-16 06:18:15 +02:00
|
|
|
NetEConcat(unsigned cnt, unsigned repeat =1);
|
1999-06-09 05:00:05 +02:00
|
|
|
~NetEConcat();
|
|
|
|
|
|
|
|
|
|
// Manipulate the parameters.
|
|
|
|
|
void set(unsigned idx, NetExpr*e);
|
|
|
|
|
|
1999-09-16 06:18:15 +02:00
|
|
|
unsigned repeat() const { return repeat_; }
|
1999-06-09 05:00:05 +02:00
|
|
|
unsigned nparms() const { return parms_.count() ; }
|
|
|
|
|
NetExpr* parm(unsigned idx) const { return parms_[idx]; }
|
|
|
|
|
|
|
|
|
|
virtual bool set_width(unsigned w);
|
|
|
|
|
virtual NetEConcat* dup_expr() const;
|
2000-12-16 20:03:30 +01:00
|
|
|
virtual NetEConst* eval_tree();
|
2000-01-01 07:18:00 +01:00
|
|
|
virtual NetNet*synthesize(Design*);
|
1999-06-09 05:00:05 +02:00
|
|
|
virtual void expr_scan(struct expr_scan_t*) const;
|
|
|
|
|
virtual void dump(ostream&) const;
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
svector<NetExpr*>parms_;
|
1999-09-16 06:18:15 +02:00
|
|
|
unsigned repeat_;
|
1999-06-09 05:00:05 +02:00
|
|
|
};
|
|
|
|
|
|
1999-09-20 04:21:10 +02:00
|
|
|
/*
|
|
|
|
|
* This clas is a placeholder for a parameter expression. When
|
|
|
|
|
* parameters are first created, an instance of this object is used to
|
|
|
|
|
* hold the place where the parameter exression goes. Then, when the
|
|
|
|
|
* parameters are resolved, these objects are removed.
|
|
|
|
|
*
|
|
|
|
|
* If the parameter object is created with a path and name, then the
|
|
|
|
|
* object represents a reference to a parameter that is known to exist.
|
|
|
|
|
*/
|
|
|
|
|
class NetEParam : public NetExpr {
|
|
|
|
|
public:
|
|
|
|
|
NetEParam();
|
2000-03-08 05:36:53 +01:00
|
|
|
NetEParam(class Design*des, NetScope*scope, const string&name);
|
1999-09-20 04:21:10 +02:00
|
|
|
~NetEParam();
|
|
|
|
|
|
|
|
|
|
virtual bool set_width(unsigned w);
|
|
|
|
|
virtual void expr_scan(struct expr_scan_t*) const;
|
1999-09-21 02:13:40 +02:00
|
|
|
virtual NetExpr* eval_tree();
|
1999-09-20 04:21:10 +02:00
|
|
|
virtual NetEParam* dup_expr() const;
|
|
|
|
|
|
|
|
|
|
virtual void dump(ostream&) const;
|
|
|
|
|
|
|
|
|
|
private:
|
1999-09-21 02:13:40 +02:00
|
|
|
Design*des_;
|
2000-03-08 05:36:53 +01:00
|
|
|
NetScope*scope_;
|
1999-09-20 04:21:10 +02:00
|
|
|
string name_;
|
|
|
|
|
};
|
|
|
|
|
|
1999-11-27 20:07:57 +01:00
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* This class is a special (and magical) expression node type that
|
|
|
|
|
* represents scope names. These can only be found as parameters to
|
|
|
|
|
* NetSTask objects.
|
|
|
|
|
*/
|
|
|
|
|
class NetEScope : public NetExpr {
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
NetEScope(NetScope*);
|
|
|
|
|
~NetEScope();
|
|
|
|
|
|
|
|
|
|
const NetScope* scope() const;
|
|
|
|
|
|
|
|
|
|
virtual void expr_scan(struct expr_scan_t*) const;
|
|
|
|
|
virtual NetEScope* dup_expr() const;
|
|
|
|
|
|
|
|
|
|
virtual void dump(ostream&os) const;
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
NetScope*scope_;
|
|
|
|
|
};
|
|
|
|
|
|
1999-09-25 04:57:29 +02:00
|
|
|
/*
|
|
|
|
|
* This node represents a system function call in an expression. The
|
|
|
|
|
* object contains the name of the system function, which the backend
|
2000-05-07 20:20:07 +02:00
|
|
|
* uses to do VPI matching.
|
1999-09-25 04:57:29 +02:00
|
|
|
*/
|
|
|
|
|
class NetESFunc : public NetExpr {
|
|
|
|
|
|
|
|
|
|
public:
|
2000-05-07 20:20:07 +02:00
|
|
|
NetESFunc(const string&name, unsigned width, unsigned nprms);
|
1999-09-25 04:57:29 +02:00
|
|
|
~NetESFunc();
|
|
|
|
|
|
2000-10-05 07:03:01 +02:00
|
|
|
const char* name() const;
|
1999-09-25 04:57:29 +02:00
|
|
|
|
2000-05-07 20:20:07 +02:00
|
|
|
unsigned nparms() const;
|
|
|
|
|
void parm(unsigned idx, NetExpr*expr);
|
|
|
|
|
NetExpr* parm(unsigned idx);
|
|
|
|
|
const NetExpr* parm(unsigned idx) const;
|
|
|
|
|
|
1999-09-25 04:57:29 +02:00
|
|
|
virtual bool set_width(unsigned);
|
|
|
|
|
virtual void dump(ostream&) const;
|
|
|
|
|
|
|
|
|
|
virtual void expr_scan(struct expr_scan_t*) const;
|
|
|
|
|
virtual NetESFunc*dup_expr() const;
|
|
|
|
|
|
|
|
|
|
private:
|
2000-10-05 07:03:01 +02:00
|
|
|
char* name_;
|
2000-05-07 20:20:07 +02:00
|
|
|
unsigned nparms_;
|
|
|
|
|
NetExpr**parms_;
|
1999-09-25 04:57:29 +02:00
|
|
|
|
|
|
|
|
private: // not implemented
|
|
|
|
|
NetESFunc(const NetESFunc&);
|
|
|
|
|
NetESFunc& operator= (const NetESFunc&);
|
|
|
|
|
};
|
|
|
|
|
|
1999-03-15 03:43:32 +01:00
|
|
|
/*
|
1999-07-17 21:50:59 +02:00
|
|
|
* This class represents the ternary (?:) operator. It has 3
|
|
|
|
|
* expressions, one of which is a condition used to select which of
|
|
|
|
|
* the other two expressions is the result.
|
|
|
|
|
*/
|
|
|
|
|
class NetETernary : public NetExpr {
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
NetETernary(NetExpr*c, NetExpr*t, NetExpr*f);
|
|
|
|
|
~NetETernary();
|
|
|
|
|
|
|
|
|
|
virtual bool set_width(unsigned w);
|
|
|
|
|
|
1999-09-11 06:43:17 +02:00
|
|
|
const NetExpr*cond_expr() const;
|
|
|
|
|
const NetExpr*true_expr() const;
|
|
|
|
|
const NetExpr*false_expr() const;
|
|
|
|
|
|
1999-07-17 21:50:59 +02:00
|
|
|
virtual NetETernary* dup_expr() const;
|
2000-12-16 20:03:30 +01:00
|
|
|
virtual NetExpr* eval_tree();
|
1999-07-17 21:50:59 +02:00
|
|
|
|
|
|
|
|
virtual void expr_scan(struct expr_scan_t*) const;
|
|
|
|
|
virtual void dump(ostream&) const;
|
1999-11-04 04:53:26 +01:00
|
|
|
virtual NetNet*synthesize(Design*);
|
1999-07-17 21:50:59 +02:00
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
NetExpr*cond_;
|
|
|
|
|
NetExpr*true_val_;
|
|
|
|
|
NetExpr*false_val_;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* This class represents a unary operator, with the single operand
|
1999-03-15 03:43:32 +01:00
|
|
|
* and a single character for the operator. The operator values are:
|
|
|
|
|
*
|
|
|
|
|
* ~ -- Bit-wise negation
|
|
|
|
|
* ! -- Logical negation
|
|
|
|
|
* & -- Reduction AND
|
1999-06-13 19:30:23 +02:00
|
|
|
* | -- Reduction OR
|
|
|
|
|
* ^ -- Reduction XOR
|
|
|
|
|
* + --
|
|
|
|
|
* - --
|
1999-11-04 04:53:26 +01:00
|
|
|
* A -- Reduction NAND (~&)
|
|
|
|
|
* N -- Reduction NOR (~|)
|
|
|
|
|
* X -- Reduction NXOR (~^ or ^~)
|
1999-03-15 03:43:32 +01:00
|
|
|
*/
|
1998-11-04 00:28:49 +01:00
|
|
|
class NetEUnary : public NetExpr {
|
|
|
|
|
|
|
|
|
|
public:
|
1999-09-28 05:11:29 +02:00
|
|
|
NetEUnary(char op, NetExpr*ex);
|
1998-11-07 20:17:10 +01:00
|
|
|
~NetEUnary();
|
1998-11-04 00:28:49 +01:00
|
|
|
|
|
|
|
|
char op() const { return op_; }
|
1999-05-30 03:11:46 +02:00
|
|
|
const NetExpr* expr() const { return expr_; }
|
1998-11-04 00:28:49 +01:00
|
|
|
|
1999-05-27 06:13:08 +02:00
|
|
|
virtual bool set_width(unsigned w);
|
1998-11-07 20:17:10 +01:00
|
|
|
|
1999-05-30 03:11:46 +02:00
|
|
|
virtual NetEUnary* dup_expr() const;
|
2000-07-07 06:53:53 +02:00
|
|
|
virtual NetEConst* eval_tree();
|
1999-05-30 03:11:46 +02:00
|
|
|
|
1998-11-04 00:28:49 +01:00
|
|
|
virtual void expr_scan(struct expr_scan_t*) const;
|
|
|
|
|
virtual void dump(ostream&) const;
|
|
|
|
|
|
1999-11-04 04:53:26 +01:00
|
|
|
protected:
|
1998-11-04 00:28:49 +01:00
|
|
|
char op_;
|
1999-05-30 03:11:46 +02:00
|
|
|
NetExpr* expr_;
|
2001-01-02 05:21:13 +01:00
|
|
|
|
|
|
|
|
void eval_expr_();
|
1998-11-04 00:28:49 +01:00
|
|
|
};
|
|
|
|
|
|
1999-11-04 04:53:26 +01:00
|
|
|
class NetEUBits : public NetEUnary {
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
NetEUBits(char op, NetExpr*ex);
|
|
|
|
|
~NetEUBits();
|
|
|
|
|
|
|
|
|
|
virtual NetNet* synthesize(Design*);
|
|
|
|
|
|
2001-01-02 04:23:40 +01:00
|
|
|
virtual NetEConst* eval_tree();
|
1999-11-04 04:53:26 +01:00
|
|
|
};
|
|
|
|
|
|
2000-11-29 06:24:00 +01:00
|
|
|
class NetEUReduce : public NetEUnary {
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
NetEUReduce(char op, NetExpr*ex);
|
|
|
|
|
~NetEUReduce();
|
|
|
|
|
|
|
|
|
|
virtual NetNet* synthesize(Design*);
|
2001-01-02 05:21:13 +01:00
|
|
|
virtual NetEConst* eval_tree();
|
2000-11-29 06:24:00 +01:00
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
1999-04-19 03:59:36 +02:00
|
|
|
/*
|
1999-12-12 07:03:14 +01:00
|
|
|
* A reference to a memory is represented by this expression. If the
|
|
|
|
|
* index is not supplied, then the node is only valid in certain
|
|
|
|
|
* specific contexts.
|
1999-04-19 03:59:36 +02:00
|
|
|
*/
|
|
|
|
|
class NetEMemory : public NetExpr {
|
|
|
|
|
|
|
|
|
|
public:
|
1999-12-12 07:03:14 +01:00
|
|
|
NetEMemory(NetMemory*mem, NetExpr*idx =0);
|
1999-04-19 03:59:36 +02:00
|
|
|
virtual ~NetEMemory();
|
|
|
|
|
|
1999-04-22 06:56:58 +02:00
|
|
|
const string& name () const { return mem_->name(); }
|
1999-05-30 03:11:46 +02:00
|
|
|
const NetExpr* index() const { return idx_; }
|
1999-04-22 06:56:58 +02:00
|
|
|
|
1999-05-27 06:13:08 +02:00
|
|
|
virtual bool set_width(unsigned);
|
1999-05-30 03:11:46 +02:00
|
|
|
|
|
|
|
|
virtual NetEMemory*dup_expr() const;
|
|
|
|
|
|
1999-04-19 03:59:36 +02:00
|
|
|
virtual void expr_scan(struct expr_scan_t*) const;
|
|
|
|
|
virtual void dump(ostream&) const;
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
NetMemory*mem_;
|
1999-05-30 03:11:46 +02:00
|
|
|
NetExpr* idx_;
|
1999-04-19 03:59:36 +02:00
|
|
|
};
|
|
|
|
|
|
1999-03-01 04:27:53 +01:00
|
|
|
/*
|
|
|
|
|
* When a signal shows up in an expression, this type represents
|
|
|
|
|
* it. From this the expression can get any kind of access to the
|
|
|
|
|
* structural signal.
|
|
|
|
|
*
|
|
|
|
|
* A signal shows up as a node in the netlist so that structural
|
|
|
|
|
* activity can invoke the expression.
|
|
|
|
|
*/
|
1999-11-29 00:42:02 +01:00
|
|
|
class NetESignal : public NetExpr {
|
1998-11-07 18:05:05 +01:00
|
|
|
|
|
|
|
|
public:
|
1999-02-08 03:49:56 +01:00
|
|
|
NetESignal(NetNet*n);
|
1998-11-07 20:17:10 +01:00
|
|
|
~NetESignal();
|
1998-11-07 18:05:05 +01:00
|
|
|
|
2000-12-11 01:31:43 +01:00
|
|
|
// a NetESignal expression is signed if the NetNet that it
|
|
|
|
|
// refers to is signed.
|
|
|
|
|
bool has_sign() const;
|
|
|
|
|
|
2000-08-27 17:51:50 +02:00
|
|
|
string name() const;
|
1999-05-27 06:13:08 +02:00
|
|
|
virtual bool set_width(unsigned);
|
1998-11-07 20:17:10 +01:00
|
|
|
|
1999-05-30 03:11:46 +02:00
|
|
|
virtual NetESignal* dup_expr() const;
|
1999-11-02 05:55:34 +01:00
|
|
|
NetNet* synthesize(Design*des);
|
|
|
|
|
|
1999-11-29 00:42:02 +01:00
|
|
|
// These methods actually reference the properties of the
|
|
|
|
|
// NetNet object that I point to.
|
|
|
|
|
unsigned pin_count() const;
|
2000-05-07 06:37:55 +02:00
|
|
|
Link& pin(unsigned idx);
|
1999-11-29 00:42:02 +01:00
|
|
|
|
1998-11-07 18:05:05 +01:00
|
|
|
virtual void expr_scan(struct expr_scan_t*) const;
|
|
|
|
|
virtual void dump(ostream&) const;
|
|
|
|
|
|
|
|
|
|
private:
|
1999-11-29 00:42:02 +01:00
|
|
|
NetNet*net_;
|
1998-11-07 18:05:05 +01:00
|
|
|
};
|
|
|
|
|
|
1999-04-25 02:44:10 +02:00
|
|
|
/*
|
|
|
|
|
* An expression that takes a portion of a signal is represented as
|
|
|
|
|
* one of these. For example, ``foo[x+5]'' is a signal and x+5 is an
|
|
|
|
|
* expression to select a single bit from that signal. I can't just
|
|
|
|
|
* make a new NetESignal node connected to the single net because the
|
|
|
|
|
* expression may vary during execution, so the structure is not known
|
|
|
|
|
* at compile (elaboration) time.
|
|
|
|
|
*/
|
|
|
|
|
class NetESubSignal : public NetExpr {
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
NetESubSignal(NetESignal*sig, NetExpr*ex);
|
|
|
|
|
~NetESubSignal();
|
|
|
|
|
|
2000-08-27 17:51:50 +02:00
|
|
|
string name() const;
|
1999-05-30 03:11:46 +02:00
|
|
|
const NetExpr*index() const { return idx_; }
|
|
|
|
|
|
1999-07-16 06:33:41 +02:00
|
|
|
virtual bool set_width(unsigned);
|
|
|
|
|
|
1999-05-30 03:11:46 +02:00
|
|
|
NetESubSignal* dup_expr() const;
|
1999-04-26 00:52:32 +02:00
|
|
|
|
1999-04-25 02:44:10 +02:00
|
|
|
virtual void expr_scan(struct expr_scan_t*) const;
|
|
|
|
|
virtual void dump(ostream&) const;
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
// For now, only support single-bit selects of a signal.
|
|
|
|
|
NetESignal*sig_;
|
1999-05-30 03:11:46 +02:00
|
|
|
NetExpr* idx_;
|
1999-04-25 02:44:10 +02:00
|
|
|
};
|
|
|
|
|
|
1999-11-24 05:01:58 +01:00
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* This object type is used to contain a logical scope within a
|
1999-11-27 20:07:57 +01:00
|
|
|
* design. The scope doesn't represent any executable hardware, but is
|
|
|
|
|
* just a handle that netlist processors can use to grab at the design.
|
1999-11-24 05:01:58 +01:00
|
|
|
*/
|
|
|
|
|
class NetScope {
|
|
|
|
|
|
|
|
|
|
public:
|
2000-03-08 05:36:53 +01:00
|
|
|
enum TYPE { MODULE, TASK, FUNC, BEGIN_END, FORK_JOIN };
|
2000-01-10 02:35:23 +01:00
|
|
|
NetScope(NetScope*up, const string&name, TYPE t);
|
1999-11-24 05:01:58 +01:00
|
|
|
~NetScope();
|
|
|
|
|
|
2000-03-08 05:36:53 +01:00
|
|
|
/* Parameters exist within a scope, and these methods allow
|
|
|
|
|
one to manipulate the set. In these cases, the name is the
|
|
|
|
|
*simple* name of the paramter, the heirarchy is implicit in
|
|
|
|
|
the scope. The return value from set_parameter is the
|
|
|
|
|
previous expression, if there was one. */
|
|
|
|
|
|
|
|
|
|
NetExpr* set_parameter(const string&name, NetExpr*val);
|
2000-03-12 18:09:40 +01:00
|
|
|
NetExpr* set_localparam(const string&name, NetExpr*val);
|
2000-03-08 05:36:53 +01:00
|
|
|
const NetExpr*get_parameter(const string&name) const;
|
|
|
|
|
|
2000-04-04 05:20:15 +02:00
|
|
|
/* These methods set or access events that live in this
|
|
|
|
|
scope. */
|
|
|
|
|
|
|
|
|
|
void add_event(NetEvent*);
|
2000-04-18 06:50:19 +02:00
|
|
|
void rem_event(NetEvent*);
|
2000-04-04 05:20:15 +02:00
|
|
|
NetEvent*find_event(const string&name);
|
2000-03-08 05:36:53 +01:00
|
|
|
|
2000-05-02 02:58:11 +02:00
|
|
|
|
|
|
|
|
/* These methods manage signals. The add_ and rem_signal
|
|
|
|
|
methods are used by the NetNet objects to make themselves
|
|
|
|
|
available to the scope, and the find_signal method can be
|
|
|
|
|
used to locate signals within a scope. */
|
|
|
|
|
|
|
|
|
|
void add_signal(NetNet*);
|
|
|
|
|
void rem_signal(NetNet*);
|
|
|
|
|
|
|
|
|
|
NetNet* find_signal(const string&name);
|
|
|
|
|
|
2000-05-02 05:13:30 +02:00
|
|
|
|
|
|
|
|
/* ... and these methods manage memory the same way as signals
|
|
|
|
|
are managed above. */
|
|
|
|
|
|
|
|
|
|
void add_memory(NetMemory*);
|
|
|
|
|
void rem_memory(NetMemory*);
|
|
|
|
|
|
|
|
|
|
NetMemory* find_memory(const string&name);
|
|
|
|
|
|
|
|
|
|
|
2000-03-08 05:36:53 +01:00
|
|
|
/* The parent and child() methods allow users of NetScope
|
|
|
|
|
objects to locate nearby scopes. */
|
2000-03-10 07:20:48 +01:00
|
|
|
NetScope* parent();
|
2000-03-08 05:36:53 +01:00
|
|
|
NetScope* child(const string&name);
|
|
|
|
|
const NetScope* parent() const;
|
|
|
|
|
const NetScope* child(const string&name) const;
|
|
|
|
|
|
1999-11-27 20:07:57 +01:00
|
|
|
TYPE type() const;
|
2000-05-02 02:58:11 +02:00
|
|
|
|
2000-07-30 20:25:43 +02:00
|
|
|
void set_task_def(NetTaskDef*);
|
|
|
|
|
void set_func_def(NetFuncDef*);
|
2000-12-16 02:45:47 +01:00
|
|
|
void set_module_name(const char*);
|
2000-07-30 20:25:43 +02:00
|
|
|
|
|
|
|
|
NetTaskDef* task_def();
|
|
|
|
|
NetFuncDef* func_def();
|
|
|
|
|
|
|
|
|
|
const NetTaskDef* task_def() const;
|
|
|
|
|
const NetFuncDef* func_def() const;
|
2000-12-16 02:45:47 +01:00
|
|
|
const char*module_name() const;
|
2000-07-30 20:25:43 +02:00
|
|
|
|
2000-07-23 00:09:03 +02:00
|
|
|
/* Scopes have their own time units and time precision. The
|
|
|
|
|
unit and precision are given as power of 10, i.e. -3 is
|
|
|
|
|
units of milliseconds.
|
|
|
|
|
|
|
|
|
|
If a NetScope is created with a parent scope, the new scope
|
|
|
|
|
will initially inherit the unit and precision of the
|
|
|
|
|
parent scope. */
|
|
|
|
|
|
|
|
|
|
void time_unit(int);
|
|
|
|
|
void time_precision(int);
|
|
|
|
|
|
|
|
|
|
int time_unit() const;
|
|
|
|
|
int time_precision() const;
|
|
|
|
|
|
2000-05-02 02:58:11 +02:00
|
|
|
/* The name of the scope is the fully qualified hierarchical
|
|
|
|
|
name, whereas the basename is just my name within my parent
|
|
|
|
|
scope. */
|
2000-08-27 17:51:50 +02:00
|
|
|
const char* basename() const;
|
1999-11-24 05:01:58 +01:00
|
|
|
string name() const;
|
2000-03-08 05:36:53 +01:00
|
|
|
|
|
|
|
|
void run_defparams(class Design*);
|
|
|
|
|
void evaluate_parameters(class Design*);
|
1999-11-24 05:01:58 +01:00
|
|
|
|
2000-04-10 07:26:05 +02:00
|
|
|
/* This method generates a non-hierarchical name that is
|
|
|
|
|
guaranteed to be unique within this scope. */
|
|
|
|
|
string local_symbol();
|
|
|
|
|
|
1999-11-24 05:01:58 +01:00
|
|
|
void dump(ostream&) const;
|
2000-08-08 03:50:42 +02:00
|
|
|
void emit_scope(struct target_t*tgt) const;
|
|
|
|
|
void emit_defs(struct target_t*tgt) const;
|
2000-03-08 05:36:53 +01:00
|
|
|
|
2000-04-18 06:50:19 +02:00
|
|
|
/* This method runs the functor on me. Recurse through the
|
|
|
|
|
children of this node as well. */
|
|
|
|
|
void run_functor(Design*des, functor_t*fun);
|
|
|
|
|
|
2000-03-08 05:36:53 +01:00
|
|
|
|
|
|
|
|
/* This member is used during elaboration to pass defparam
|
|
|
|
|
assignments from the scope pass to the parameter evaluation
|
|
|
|
|
step. After that, it is not used. */
|
|
|
|
|
|
|
|
|
|
map<string,NetExpr*>defparams;
|
1999-11-24 05:01:58 +01:00
|
|
|
|
|
|
|
|
private:
|
1999-11-27 20:07:57 +01:00
|
|
|
TYPE type_;
|
2000-08-27 17:51:50 +02:00
|
|
|
char* name_;
|
2000-03-08 05:36:53 +01:00
|
|
|
|
2000-07-23 00:09:03 +02:00
|
|
|
signed char time_unit_, time_prec_;
|
|
|
|
|
|
2000-03-08 05:36:53 +01:00
|
|
|
map<string,NetExpr*>parameters_;
|
2000-03-12 18:09:40 +01:00
|
|
|
map<string,NetExpr*>localparams_;
|
2000-03-08 05:36:53 +01:00
|
|
|
|
2000-05-02 05:13:30 +02:00
|
|
|
NetEvent *events_;
|
|
|
|
|
NetNet *signals_;
|
|
|
|
|
NetMemory*memories_;
|
2000-04-04 05:20:15 +02:00
|
|
|
|
2000-07-30 20:25:43 +02:00
|
|
|
union {
|
|
|
|
|
NetTaskDef*task_;
|
|
|
|
|
NetFuncDef*func_;
|
2000-12-16 02:45:47 +01:00
|
|
|
char*module_name_;
|
2000-07-30 20:25:43 +02:00
|
|
|
};
|
|
|
|
|
|
2000-01-10 02:35:23 +01:00
|
|
|
NetScope*up_;
|
2000-03-08 05:36:53 +01:00
|
|
|
NetScope*sib_;
|
|
|
|
|
NetScope*sub_;
|
2000-04-10 07:26:05 +02:00
|
|
|
|
|
|
|
|
unsigned lcounter_;
|
1999-11-24 05:01:58 +01:00
|
|
|
};
|
|
|
|
|
|
1998-11-04 00:28:49 +01:00
|
|
|
/*
|
|
|
|
|
* This class contains an entire design. It includes processes and a
|
|
|
|
|
* netlist, and can be passed around from function to function.
|
|
|
|
|
*/
|
|
|
|
|
class Design {
|
|
|
|
|
|
|
|
|
|
public:
|
1999-11-24 05:01:58 +01:00
|
|
|
Design();
|
|
|
|
|
~Design();
|
|
|
|
|
|
1998-11-04 00:28:49 +01:00
|
|
|
|
1998-11-18 05:25:22 +01:00
|
|
|
/* The flags are a generic way of accepting command line
|
|
|
|
|
parameters/flags and passing them to the processing steps
|
|
|
|
|
that deal with the design. The compilation driver sets the
|
|
|
|
|
entire flags map after elaboration is done. Subsequent
|
|
|
|
|
steps can then use the get_flag() function to get the value
|
|
|
|
|
of an interesting key. */
|
|
|
|
|
|
|
|
|
|
void set_flags(const map<string,string>&f) { flags_ = f; }
|
|
|
|
|
|
|
|
|
|
string get_flag(const string&key) const;
|
|
|
|
|
|
1999-11-27 20:07:57 +01:00
|
|
|
NetScope* make_root_scope(const string&name);
|
2000-05-02 02:58:11 +02:00
|
|
|
NetScope* find_root_scope();
|
2000-03-10 07:20:48 +01:00
|
|
|
|
2000-08-26 02:54:03 +02:00
|
|
|
const NetScope* find_root_scope() const;
|
|
|
|
|
|
2000-07-23 00:09:03 +02:00
|
|
|
|
|
|
|
|
/* Attempt to set the precision to the specified value. If the
|
|
|
|
|
precision is already more precise, the keep the precise
|
|
|
|
|
setting. This is intended to hold the simulation precision
|
|
|
|
|
for use throughout the entire design. */
|
|
|
|
|
|
|
|
|
|
void set_precision(int val);
|
|
|
|
|
int get_precision() const;
|
|
|
|
|
|
|
|
|
|
/* This function takes a delay value and a scope, and returns
|
|
|
|
|
the delay value scaled to the precision of the design. */
|
|
|
|
|
unsigned long scale_to_precision(unsigned long, const NetScope*)const;
|
|
|
|
|
|
2000-03-10 07:20:48 +01:00
|
|
|
/* look up a scope. If no starting scope is passed, then the
|
|
|
|
|
path name string is taken as an absolute scope
|
|
|
|
|
name. Otherwise, the scope is located starting at the
|
|
|
|
|
passed scope and working up if needed. */
|
|
|
|
|
NetScope* find_scope(const string&path) const;
|
|
|
|
|
NetScope* find_scope(NetScope*, const string&path) const;
|
1998-11-04 00:28:49 +01:00
|
|
|
|
1999-02-21 18:01:57 +01:00
|
|
|
// PARAMETERS
|
2000-03-08 05:36:53 +01:00
|
|
|
|
|
|
|
|
/* This method searches for a parameter, starting in the given
|
|
|
|
|
scope. This method handles the upward searches that the
|
|
|
|
|
NetScope class itself does not support. */
|
|
|
|
|
const NetExpr*find_parameter(const NetScope*, const string&name) const;
|
|
|
|
|
|
|
|
|
|
void run_defparams();
|
|
|
|
|
void evaluate_parameters();
|
1999-02-21 18:01:57 +01:00
|
|
|
|
2000-05-02 02:58:11 +02:00
|
|
|
/* This method locates a signal, starting at a given
|
|
|
|
|
scope. The name parameter may be partially hierarchical, so
|
|
|
|
|
this method, unlike the NetScope::find_signal method,
|
|
|
|
|
handles global name binding. */
|
|
|
|
|
|
2000-05-02 05:13:30 +02:00
|
|
|
NetNet*find_signal(NetScope*scope, const string&name);
|
1998-11-04 00:28:49 +01:00
|
|
|
|
1999-04-19 03:59:36 +02:00
|
|
|
// Memories
|
2000-05-02 05:13:30 +02:00
|
|
|
NetMemory* find_memory(NetScope*scope, const string&name);
|
1999-04-19 03:59:36 +02:00
|
|
|
|
2000-04-28 18:50:53 +02:00
|
|
|
/* This is a more general lookup that finds the named signal
|
|
|
|
|
or memory, whichever is first in the search path. */
|
2000-05-02 02:58:11 +02:00
|
|
|
void find_symbol(NetScope*,const string&key,
|
2000-04-28 18:50:53 +02:00
|
|
|
NetNet*&sig, NetMemory*&mem);
|
|
|
|
|
|
1999-08-26 00:22:41 +02:00
|
|
|
// Functions
|
2000-09-24 19:41:13 +02:00
|
|
|
NetFuncDef* find_function(NetScope*scope, const string&key);
|
1999-09-01 22:46:19 +02:00
|
|
|
NetFuncDef* find_function(const string&path);
|
1999-08-26 00:22:41 +02:00
|
|
|
|
1999-07-03 04:12:51 +02:00
|
|
|
// Tasks
|
2000-09-24 19:41:13 +02:00
|
|
|
NetTaskDef* find_task(NetScope*scope, const string&name);
|
1999-07-03 04:12:51 +02:00
|
|
|
NetTaskDef* find_task(const string&key);
|
|
|
|
|
|
1998-11-04 00:28:49 +01:00
|
|
|
// NODES
|
|
|
|
|
void add_node(NetNode*);
|
|
|
|
|
void del_node(NetNode*);
|
|
|
|
|
|
|
|
|
|
// PROCESSES
|
|
|
|
|
void add_process(NetProcTop*);
|
1999-07-18 07:52:46 +02:00
|
|
|
void delete_process(NetProcTop*);
|
1998-11-04 00:28:49 +01:00
|
|
|
|
|
|
|
|
// Iterate over the design...
|
|
|
|
|
void dump(ostream&) const;
|
1999-07-18 00:01:13 +02:00
|
|
|
void functor(struct functor_t*);
|
2000-08-09 05:43:45 +02:00
|
|
|
bool emit(struct target_t*) const;
|
1998-11-04 00:28:49 +01:00
|
|
|
|
1999-02-01 01:26:48 +01:00
|
|
|
// This is incremented by elaboration when an error is
|
|
|
|
|
// detected. It prevents code being emitted.
|
|
|
|
|
unsigned errors;
|
1998-12-07 05:53:16 +01:00
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
string local_symbol(const string&path);
|
|
|
|
|
|
1998-11-04 00:28:49 +01:00
|
|
|
private:
|
2000-03-08 05:36:53 +01:00
|
|
|
// Keep a tree of scopes. The NetScope class handles the wide
|
|
|
|
|
// tree and per-hop searches for me.
|
|
|
|
|
NetScope*root_scope_;
|
1999-02-21 18:01:57 +01:00
|
|
|
|
1998-11-04 00:28:49 +01:00
|
|
|
// List the nodes in the design
|
|
|
|
|
NetNode*nodes_;
|
|
|
|
|
|
|
|
|
|
// List the processes in the design.
|
|
|
|
|
NetProcTop*procs_;
|
1999-07-18 07:52:46 +02:00
|
|
|
NetProcTop*procs_idx_;
|
1998-11-04 00:28:49 +01:00
|
|
|
|
1998-11-18 05:25:22 +01:00
|
|
|
map<string,string> flags_;
|
|
|
|
|
|
2000-07-23 00:09:03 +02:00
|
|
|
int des_precision_;
|
|
|
|
|
|
1998-12-07 05:53:16 +01:00
|
|
|
unsigned lcounter_;
|
|
|
|
|
|
1998-11-04 00:28:49 +01:00
|
|
|
private: // not implemented
|
|
|
|
|
Design(const Design&);
|
|
|
|
|
Design& operator= (const Design&);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* =======
|
|
|
|
|
*/
|
|
|
|
|
|
2000-05-07 06:37:55 +02:00
|
|
|
inline bool operator == (const Link&l, const Link&r)
|
1998-11-23 01:20:22 +01:00
|
|
|
{ return l.is_equal(r); }
|
|
|
|
|
|
2000-05-07 06:37:55 +02:00
|
|
|
inline bool operator != (const Link&l, const Link&r)
|
1998-11-23 01:20:22 +01:00
|
|
|
{ return ! l.is_equal(r); }
|
1998-11-04 00:28:49 +01:00
|
|
|
|
|
|
|
|
/* Connect the pins of two nodes together. Either may already be
|
|
|
|
|
connected to other things, connect is transitive. */
|
2000-05-07 06:37:55 +02:00
|
|
|
extern void connect(Link&, Link&);
|
1998-11-04 00:28:49 +01:00
|
|
|
|
1998-12-02 05:37:13 +01:00
|
|
|
/* Return true if l and r are connected. */
|
2000-05-07 06:37:55 +02:00
|
|
|
inline bool connected(const Link&l, const Link&r)
|
1998-11-23 01:20:22 +01:00
|
|
|
{ return l.is_linked(r); }
|
|
|
|
|
|
1998-12-07 05:53:16 +01:00
|
|
|
/* return the number of links in the ring that are of the specified
|
|
|
|
|
type. */
|
2000-05-07 06:37:55 +02:00
|
|
|
extern unsigned count_inputs(const Link&pin);
|
|
|
|
|
extern unsigned count_outputs(const Link&pin);
|
|
|
|
|
extern unsigned count_signals(const Link&pin);
|
1998-12-02 05:37:13 +01:00
|
|
|
|
1999-11-19 04:02:25 +01:00
|
|
|
/* Find the next link that is an output into the nexus. */
|
2000-05-07 06:37:55 +02:00
|
|
|
extern Link* find_next_output(Link*lnk);
|
1999-11-19 04:02:25 +01:00
|
|
|
|
1998-11-04 00:28:49 +01:00
|
|
|
/* Find the signal connected to the given node pin. There should
|
|
|
|
|
always be exactly one signal. The bidx parameter get filled with
|
|
|
|
|
the signal index of the Net, in case it is a vector. */
|
|
|
|
|
const NetNet* find_link_signal(const NetObj*net, unsigned pin,
|
|
|
|
|
unsigned&bidx);
|
|
|
|
|
|
|
|
|
|
inline ostream& operator << (ostream&o, const NetExpr&exp)
|
|
|
|
|
{ exp.dump(o); return o; }
|
|
|
|
|
|
1998-12-01 01:42:13 +01:00
|
|
|
extern ostream& operator << (ostream&, NetNet::Type);
|
|
|
|
|
|
1998-11-04 00:28:49 +01:00
|
|
|
/*
|
|
|
|
|
* $Log: netlist.h,v $
|
2001-01-18 04:16:35 +01:00
|
|
|
* Revision 1.195 2001/01/18 03:16:35 steve
|
|
|
|
|
* NetMux needs a scope. (PR#115)
|
|
|
|
|
*
|
2001-01-16 03:44:17 +01:00
|
|
|
* Revision 1.194 2001/01/16 02:44:18 steve
|
|
|
|
|
* Use the iosfwd header if available.
|
|
|
|
|
*
|
2001-01-06 07:31:58 +01:00
|
|
|
* Revision 1.193 2001/01/06 06:31:58 steve
|
|
|
|
|
* declaration initialization for time variables.
|
|
|
|
|
*
|
2001-01-06 03:29:35 +01:00
|
|
|
* Revision 1.192 2001/01/06 02:29:36 steve
|
|
|
|
|
* Support arrays of integers.
|
|
|
|
|
*
|
2001-01-04 17:49:50 +01:00
|
|
|
* Revision 1.191 2001/01/04 16:49:50 steve
|
|
|
|
|
* Evaluate constant === and !== expressions.
|
|
|
|
|
*
|
2001-01-02 05:21:13 +01:00
|
|
|
* Revision 1.190 2001/01/02 04:21:14 steve
|
|
|
|
|
* Support a bunch of unary operators in parameter expressions.
|
|
|
|
|
*
|
2001-01-02 04:23:40 +01:00
|
|
|
* Revision 1.189 2001/01/02 03:23:40 steve
|
|
|
|
|
* Evaluate constant &, | and unary ~.
|
|
|
|
|
*
|
2000-12-16 20:03:30 +01:00
|
|
|
* Revision 1.188 2000/12/16 19:03:30 steve
|
|
|
|
|
* Evaluate <= and ?: in parameter expressions (PR#81)
|
|
|
|
|
*
|
2000-12-16 02:45:47 +01:00
|
|
|
* Revision 1.187 2000/12/16 01:45:48 steve
|
|
|
|
|
* Detect recursive instantiations (PR#2)
|
|
|
|
|
*
|
2000-12-11 01:31:43 +01:00
|
|
|
* Revision 1.186 2000/12/11 00:31:43 steve
|
|
|
|
|
* Add support for signed reg variables,
|
|
|
|
|
* simulate in t-vvm signed comparisons.
|
|
|
|
|
*
|
2000-12-05 07:29:33 +01:00
|
|
|
* Revision 1.185 2000/12/05 06:29:33 steve
|
|
|
|
|
* Make signal attributes available to ivl_target API.
|
|
|
|
|
*
|
2000-12-04 18:37:03 +01:00
|
|
|
* Revision 1.184 2000/12/04 17:37:04 steve
|
|
|
|
|
* Add Attrib class for holding NetObj attributes.
|
|
|
|
|
*
|
2000-12-02 06:08:04 +01:00
|
|
|
* Revision 1.183 2000/12/02 05:08:04 steve
|
|
|
|
|
* Spelling error in comment.
|
|
|
|
|
*
|
2000-11-29 06:24:00 +01:00
|
|
|
* Revision 1.182 2000/11/29 05:24:00 steve
|
|
|
|
|
* synthesis for unary reduction ! and N operators.
|
|
|
|
|
*
|
2000-11-29 03:09:52 +01:00
|
|
|
* Revision 1.181 2000/11/29 02:09:53 steve
|
|
|
|
|
* Add support for || synthesis (PR#53)
|
|
|
|
|
*
|
2000-11-20 01:58:40 +01:00
|
|
|
* Revision 1.180 2000/11/20 00:58:40 steve
|
|
|
|
|
* Add support for supply nets (PR#17)
|
|
|
|
|
*
|
2000-11-11 02:52:09 +01:00
|
|
|
* Revision 1.179 2000/11/11 01:52:09 steve
|
|
|
|
|
* change set for support of nmos, pmos, rnmos, rpmos, notif0, and notif1
|
|
|
|
|
* change set to correct behavior of bufif0 and bufif1
|
|
|
|
|
* (Tim Leight)
|
|
|
|
|
*
|
|
|
|
|
* Also includes fix for PR#27
|
|
|
|
|
*
|
2000-11-11 01:03:36 +01:00
|
|
|
* Revision 1.178 2000/11/11 00:03:36 steve
|
|
|
|
|
* Add support for the t-dll backend grabing flip-flops.
|
|
|
|
|
*
|
2000-11-04 07:36:24 +01:00
|
|
|
* Revision 1.177 2000/11/04 06:36:24 steve
|
|
|
|
|
* Apply sequential UDP rework from Stephan Boettcher (PR#39)
|
|
|
|
|
*
|
2000-10-31 18:49:02 +01:00
|
|
|
* Revision 1.176 2000/10/31 17:49:02 steve
|
|
|
|
|
* Support time variables.
|
|
|
|
|
*
|
2000-10-28 02:51:41 +02:00
|
|
|
* Revision 1.175 2000/10/28 00:51:42 steve
|
|
|
|
|
* Add scope to threads in vvm, pass that scope
|
|
|
|
|
* to vpi sysTaskFunc objects, and add vpi calls
|
|
|
|
|
* to access that information.
|
|
|
|
|
*
|
|
|
|
|
* $display displays scope in %m (PR#1)
|
|
|
|
|
*
|
2000-10-18 22:04:39 +02:00
|
|
|
* Revision 1.174 2000/10/18 20:04:39 steve
|
|
|
|
|
* Add ivl_lval_t and support for assignment l-values.
|
|
|
|
|
*
|
2000-10-07 21:45:42 +02:00
|
|
|
* Revision 1.173 2000/10/07 19:45:43 steve
|
|
|
|
|
* Put logic devices into scopes.
|
|
|
|
|
*
|
2000-10-07 01:46:50 +02:00
|
|
|
* Revision 1.172 2000/10/06 23:46:50 steve
|
|
|
|
|
* ivl_target updates, including more complete
|
|
|
|
|
* handling of ivl_nexus_t objects. Much reduced
|
|
|
|
|
* dependencies on pointers to netlist objects.
|
|
|
|
|
*
|
2000-10-05 07:03:01 +02:00
|
|
|
* Revision 1.171 2000/10/05 05:03:01 steve
|
|
|
|
|
* xor and constant devices.
|
|
|
|
|
*
|
2000-10-04 18:30:39 +02:00
|
|
|
* Revision 1.170 2000/10/04 16:30:39 steve
|
|
|
|
|
* Use char8 instead of string to store name.
|
|
|
|
|
*
|
2000-09-29 06:42:56 +02:00
|
|
|
* Revision 1.169 2000/09/29 04:43:09 steve
|
|
|
|
|
* Cnstant evaluation of NE.
|
|
|
|
|
*
|
2000-09-26 07:05:58 +02:00
|
|
|
* Revision 1.168 2000/09/26 05:05:58 steve
|
|
|
|
|
* Detect indefinite widths where definite widths are required.
|
|
|
|
|
*
|
2000-09-26 03:35:42 +02:00
|
|
|
* Revision 1.167 2000/09/26 01:35:42 steve
|
|
|
|
|
* Remove the obsolete NetEIdent class.
|
|
|
|
|
*
|
2000-09-24 19:41:13 +02:00
|
|
|
* Revision 1.166 2000/09/24 17:41:13 steve
|
|
|
|
|
* fix null pointer when elaborating undefined task.
|
|
|
|
|
*
|
2000-09-24 17:44:44 +02:00
|
|
|
* Revision 1.165 2000/09/24 15:44:44 steve
|
|
|
|
|
* Move some NetNet method out of the header file.
|
|
|
|
|
*
|
2000-09-22 05:58:30 +02:00
|
|
|
* Revision 1.164 2000/09/22 03:58:30 steve
|
|
|
|
|
* Access to the name of a system task call.
|
|
|
|
|
*
|
2000-09-17 23:26:15 +02:00
|
|
|
* Revision 1.163 2000/09/17 21:26:15 steve
|
|
|
|
|
* Add support for modulus (Eric Aardoom)
|
|
|
|
|
*
|
2000-09-10 04:18:16 +02:00
|
|
|
* Revision 1.162 2000/09/10 02:18:16 steve
|
|
|
|
|
* elaborate complex l-values
|
|
|
|
|
*
|
2000-09-07 02:06:53 +02:00
|
|
|
* Revision 1.161 2000/09/07 00:06:53 steve
|
|
|
|
|
* encapsulate access to the l-value expected width.
|
|
|
|
|
*
|
2000-09-03 01:40:12 +02:00
|
|
|
* Revision 1.160 2000/09/02 23:40:13 steve
|
|
|
|
|
* Pull NetAssign_ creation out of constructors.
|
|
|
|
|
*
|
2000-09-02 22:54:20 +02:00
|
|
|
* Revision 1.159 2000/09/02 20:54:20 steve
|
|
|
|
|
* Rearrange NetAssign to make NetAssign_ separate.
|
|
|
|
|
*
|
2000-08-27 17:51:50 +02:00
|
|
|
* Revision 1.158 2000/08/27 15:51:50 steve
|
|
|
|
|
* t-dll iterates signals, and passes them to the
|
|
|
|
|
* target module.
|
|
|
|
|
*
|
|
|
|
|
* Some of NetObj should return char*, not string.
|
|
|
|
|
*
|
2000-08-26 02:54:03 +02:00
|
|
|
* Revision 1.157 2000/08/26 00:54:03 steve
|
|
|
|
|
* Get at gate information for ivl_target interface.
|
|
|
|
|
*
|
2000-08-14 06:39:56 +02:00
|
|
|
* Revision 1.156 2000/08/14 04:39:57 steve
|
|
|
|
|
* add th t-dll functions for net_const, net_bufz and processes.
|
|
|
|
|
*
|
2000-08-09 05:43:45 +02:00
|
|
|
* Revision 1.155 2000/08/09 03:43:45 steve
|
|
|
|
|
* Move all file manipulation out of target class.
|
1998-11-04 00:28:49 +01:00
|
|
|
*/
|
|
|
|
|
#endif
|