Create a branch object to be the argument to the access function.

The NetBranch object is connected, but not like an object, so the
NetPins object base class is factored out from NetObj to handle the
connectivity, and the NetBranch class uses the NetPins to connect a
branch.

Also, account for the fact that nets with a discipline are by default
real-valued.
This commit is contained in:
Stephen Williams 2008-08-04 20:54:05 -07:00
parent c14987aa18
commit b292a5fc05
16 changed files with 199 additions and 57 deletions

View File

@ -897,7 +897,7 @@ void cprop_dc_functor::lpm_const(Design*des, NetConst*obj)
for (Link*clnk = nex->first_nlink()
; clnk ; clnk = clnk->next_nlink()) {
NetObj*cur;
NetPins*cur;
unsigned pin;
clnk->cur_link(cur, pin);
@ -923,7 +923,7 @@ void cprop_dc_functor::lpm_const(Design*des, NetConst*obj)
for (Link*clnk = nex->first_nlink()
; clnk ; clnk = clnk->next_nlink()) {
NetObj*cur;
NetPins*cur;
unsigned pin;
clnk->cur_link(cur, pin);

View File

@ -188,6 +188,10 @@ void NetNet::dump_net(ostream&o, unsigned ind) const
o << " inout";
break;
}
if (discipline_t*dis = get_discipline())
o << " discipline=" << dis->name();
o << " (eref=" << peek_eref() << ", lref=" << peek_lref() << ")";
if (scope())
o << " scope=" << scope_path(scope());
@ -237,7 +241,7 @@ void NetNode::dump_node(ostream&o, unsigned ind) const
/* This is the generic dumping of all the signals connected to each
pin of the object. The "this" object is not printed, only the
signals connected to this. */
void NetObj::dump_node_pins(ostream&o, unsigned ind) const
void NetPins::dump_node_pins(ostream&o, unsigned ind) const
{
for (unsigned idx = 0 ; idx < pin_count() ; idx += 1) {
o << setw(ind) << "" << idx << " " << pin(idx).get_name()
@ -1186,6 +1190,12 @@ void NetExpr::dump(ostream&o) const
void NetEAccess::dump(ostream&o) const
{
o << nature_->name() << "." << nature_->access() << "(";
assert(branch_);
if (branch_->pin(0).is_linked())
o << branch_->pin(0).nexus()->name();
o << ", ";
if (branch_->pin(1).is_linked())
o << branch_->pin(1).nexus()->name();
o << ")";
}

View File

@ -25,7 +25,7 @@
NetEAccess* NetEAccess::dup_expr() const
{
NetEAccess*tmp = new NetEAccess(nature_);
NetEAccess*tmp = new NetEAccess(branch_, nature_);
ivl_assert(*this, tmp);
tmp->set_line(*this);
return tmp;

View File

@ -616,7 +616,36 @@ NetExpr* PECallFunction::elaborate_access_func_(Design*des, NetScope*scope,
if (nature == 0)
return 0;
NetEAccess*tmp = new NetEAccess(nature);
// An access function must have 1 or 2 arguments.
ivl_assert(*this, parms_.size()==2 || parms_.size()==1);
NetBranch*branch = 0;
if (parms_.size() == 1) {
PExpr*arg1 = parms_[0];
PEIdent*arg_ident = dynamic_cast<PEIdent*> (arg1);
ivl_assert(*this, arg_ident);
const pform_name_t&path = arg_ident->path();
ivl_assert(*this, path.size()==1);
perm_string name = peek_tail_name(path);
NetNet*sig = scope->find_signal(name);
ivl_assert(*this, sig);
discipline_t*dis = sig->get_discipline();
ivl_assert(*this, dis);
ivl_assert(*this, nature == dis->potential() || nature == dis->flow());
branch = new NetBranch(dis);
branch->set_line(*this);
connect(branch->pin(0), sig->pin(0));
} else {
ivl_assert(*this, 0);
}
NetEAccess*tmp = new NetEAccess(branch, nature);
tmp->set_line(*this);
return tmp;

View File

@ -1029,6 +1029,10 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
sig->set_signed(get_signed());
sig->set_isint(get_isint());
if (discipline_t*dis = get_discipline()) {
sig->set_discipline(dis);
}
if (pull)
connect(sig->pin(0), pull->pin(0));

View File

@ -193,6 +193,7 @@ typedef enum ivl_drive_e {
typedef enum ivl_expr_type_e {
IVL_EX_NONE = 0,
IVL_EX_ARRAY = 18,
IVL_EX_BACCESS= 19,
IVL_EX_BINARY = 2,
IVL_EX_CONCAT = 3,
IVL_EX_EVENT = 17,

View File

@ -60,8 +60,9 @@ bool Nexus::drivers_constant() const
if (cur_dir == Link::PASSIVE) {
const NetObj*obj = cur->get_obj();
if (obj->scope()->parent() != 0)
const NetPins*obj = cur->get_obj();
const NetObj*as_obj = dynamic_cast<const NetObj*>(obj);
if (as_obj == 0 || as_obj->scope()->parent() != 0)
continue;
sig = dynamic_cast<const NetNet*>(cur->get_obj());

View File

@ -299,7 +299,7 @@ void NetEvProbe::find_similar_probes(list<NetEvProbe*>&plist)
Nexus*nex = pin(0).nexus();
for (Link*lcur = nex->first_nlink(); lcur; lcur = lcur->next_nlink()) {
NetObj*obj = lcur->get_obj();
NetPins*obj = lcur->get_obj();
if (obj->pin_count() != pin_count())
continue;

View File

@ -589,8 +589,8 @@ ivl_variable_type_t NetESFunc::expr_type() const
return type_;
}
NetEAccess::NetEAccess(nature_t*nat)
: nature_(nat)
NetEAccess::NetEAccess(NetBranch*br, nature_t*nat)
: branch_(br), nature_(nat)
{
}

View File

@ -134,13 +134,13 @@ verinum::V Link::get_init() const
}
void Link::cur_link(NetObj*&net, unsigned &pin)
void Link::cur_link(NetPins*&net, unsigned &pin)
{
net = node_;
pin = pin_;
}
void Link::cur_link(const NetObj*&net, unsigned &pin) const
void Link::cur_link(const NetPins*&net, unsigned &pin) const
{
net = node_;
pin = pin_;
@ -186,12 +186,12 @@ const Link* Link::next_nlink() const
return next_;
}
const NetObj*Link::get_obj() const
const NetPins*Link::get_obj() const
{
return node_;
}
NetObj*Link::get_obj()
NetPins*Link::get_obj()
{
return node_;
}
@ -253,7 +253,10 @@ void Nexus::drivers_delays(NetExpr*rise, NetExpr*fall, NetExpr*decay)
if (cur->get_dir() != Link::OUTPUT)
continue;
NetObj*obj = cur->get_obj();
NetObj*obj = dynamic_cast<NetObj*>(cur->get_obj());
if (obj == 0)
continue;
obj->rise_time(rise);
obj->fall_time(fall);
obj->decay_time(decay);
@ -397,7 +400,7 @@ const char* Nexus::name() const
if (sig == 0) {
const Link*lnk = first_nlink();
const NetObj*obj = lnk->get_obj();
const NetObj*obj = dynamic_cast<const NetObj*>(lnk->get_obj());
pin = lnk->get_pin();
cerr << "internal error: No signal for nexus of " <<
obj->name() << " pin " << pin << "(" <<

View File

@ -100,8 +100,12 @@ void join_island(NetObj*obj)
Nexus*nex = obj->pin(idx).nexus();
for (Link*cur = nex->first_nlink() ; cur ; cur = cur->next_nlink()) {
unsigned pin;
NetObj*tmp;
cur->cur_link(tmp, pin);
NetPins*tmp_pins;
cur->cur_link(tmp_pins, pin);
NetObj*tmp = dynamic_cast<NetObj*> (tmp_pins);
if (tmp == 0)
continue;
// Skip self.
if (tmp == obj)

View File

@ -91,7 +91,7 @@ unsigned count_inputs(const Link&pin)
const Nexus*nex = pin.nexus();
for (const Link*clnk = nex->first_nlink()
; clnk ; clnk = clnk->next_nlink()) {
const NetObj*cur;
const NetPins*cur;
unsigned cpin;
clnk->cur_link(cur, cpin);
if (cur->pin(cpin).get_dir() == Link::INPUT)
@ -108,7 +108,7 @@ unsigned count_outputs(const Link&pin)
const Nexus*nex = pin.nexus();
for (const Link*clnk = nex->first_nlink()
; clnk ; clnk = clnk->next_nlink()) {
const NetObj*cur;
const NetPins*cur;
unsigned cpin;
clnk->cur_link(cur, cpin);
if (cur->pin(cpin).get_dir() == Link::OUTPUT)
@ -125,7 +125,7 @@ unsigned count_signals(const Link&pin)
const Nexus*nex = pin.nexus();
for (const Link*clnk = nex->first_nlink()
; clnk ; clnk = clnk->next_nlink()) {
const NetObj*cur;
const NetPins*cur;
unsigned cpin;
clnk->cur_link(cur, cpin);
if (dynamic_cast<const NetNet*>(cur))
@ -142,7 +142,7 @@ const NetNet* find_link_signal(const NetObj*net, unsigned pin, unsigned&bidx)
for (const Link*clnk = nex->first_nlink()
; clnk ; clnk = clnk->next_nlink()) {
const NetObj*cur;
const NetPins*cur;
unsigned cpin;
clnk->cur_link(cur, cpin);
@ -171,8 +171,8 @@ Link* find_next_output(Link*lnk)
return 0;
}
NetObj::NetObj(NetScope*s, perm_string n, unsigned np)
: scope_(s), name_(n), npins_(np), delay1_(0), delay2_(0), delay3_(0)
NetPins::NetPins(unsigned npins)
: npins_(npins)
{
pins_ = new Link[npins_];
for (unsigned idx = 0 ; idx < npins_ ; idx += 1) {
@ -181,22 +181,12 @@ NetObj::NetObj(NetScope*s, perm_string n, unsigned np)
}
}
NetObj::~NetObj()
NetPins::~NetPins()
{
delete[]pins_;
}
NetScope* NetObj::scope()
{
return scope_;
}
const NetScope* NetObj::scope() const
{
return scope_;
}
Link& NetObj::pin(unsigned idx)
Link& NetPins::pin(unsigned idx)
{
if (idx >= npins_) {
cerr << get_fileline() << ": internal error: pin("<<idx<<")"
@ -209,12 +199,31 @@ Link& NetObj::pin(unsigned idx)
return pins_[idx];
}
const Link& NetObj::pin(unsigned idx) const
const Link& NetPins::pin(unsigned idx) const
{
assert(idx < npins_);
return pins_[idx];
}
NetObj::NetObj(NetScope*s, perm_string n, unsigned np)
: NetPins(np), scope_(s), name_(n), delay1_(0), delay2_(0), delay3_(0)
{
}
NetObj::~NetObj()
{
}
NetScope* NetObj::scope()
{
return scope_;
}
const NetScope* NetObj::scope() const
{
return scope_;
}
NetNode::NetNode(NetScope*s, perm_string n, unsigned npins)
: NetObj(s, n, npins), node_next_(0), node_prev_(0), design_(0)
{
@ -226,6 +235,19 @@ NetNode::~NetNode()
design_->del_node(this);
}
NetBranch::NetBranch(discipline_t*dis)
: NetPins(2), discipline_(dis)
{
pin(0).set_name(perm_string::literal("A"), 0);
pin(0).set_dir(Link::PASSIVE);
pin(1).set_name(perm_string::literal("B"), 0);
pin(1).set_dir(Link::PASSIVE);
}
NetBranch::~NetBranch()
{
}
NetBus::NetBus(NetScope*s, unsigned pin_count)
: NetObj(s, perm_string::literal(""), pin_count)
{
@ -622,6 +644,17 @@ void NetNet::set_isint(bool flag)
isint_ = flag;
}
discipline_t* NetNet::get_discipline() const
{
return discipline_;
}
void NetNet::set_discipline(discipline_t*dis)
{
ivl_assert(*this, discipline_ == 0);
discipline_ = dis;
}
long NetNet::lsb() const
{
return lsb_;

View File

@ -69,6 +69,7 @@ class NetEvTrig;
class NetEvWait;
class nature_t;
class discipline_t;
struct target;
struct functor_t;
@ -77,6 +78,24 @@ ostream& operator << (ostream&o, ivl_variable_type_t val);
extern void join_island(NetObj*obj);
class NetPins : public LineInfo {
public:
explicit NetPins(unsigned npins);
virtual ~NetPins();
unsigned pin_count() const { return npins_; }
Link&pin(unsigned idx);
const Link&pin(unsigned idx) const;
void dump_node_pins(ostream&, unsigned) const;
private:
Link*pins_;
const unsigned npins_;
};
/* =========
* A NetObj is anything that has any kind of behavior in the
* netlist. Nodes can be gates, registers, etc. and are linked
@ -97,7 +116,7 @@ extern void join_island(NetObj*obj);
* interpretation of the rise/fall/decay times is typically left to
* the target to properly interpret.
*/
class NetObj : public Attrib, public virtual LineInfo {
class NetObj : public NetPins, public Attrib {
public:
public:
@ -111,8 +130,6 @@ class NetObj : public Attrib, public virtual LineInfo {
perm_string name() const { return name_; }
unsigned pin_count() const { return npins_; }
const NetExpr* rise_time() const { return delay1_; }
const NetExpr* fall_time() const { return delay2_; }
const NetExpr* decay_time() const { return delay3_; }
@ -121,17 +138,11 @@ class NetObj : public Attrib, public virtual LineInfo {
void fall_time(const NetExpr* d) { delay2_ = d; }
void decay_time(const NetExpr* d) { delay3_ = d; }
Link&pin(unsigned idx);
const Link&pin(unsigned idx) const;
void dump_node_pins(ostream&, unsigned) const;
void dump_obj_attr(ostream&, unsigned) const;
private:
NetScope*scope_;
perm_string name_;
Link*pins_;
const unsigned npins_;
const NetExpr* delay1_;
const NetExpr* delay2_;
const NetExpr* delay3_;
@ -151,11 +162,31 @@ class IslandBranch {
struct ivl_island_s* island;
};
/*
* A NetBranch is a construct of Verilog-A that is a branch between
* two nodes. The branch has exactly 2 pins and a discipline.
*
* pin(0) is the source of flow through a branch and the plus side of
* potential. Pin(1) is the sink of flow and the minus (or ground) of
* potential.
*/
class NetBranch : public NetPins {
public:
explicit NetBranch(discipline_t*dis);
explicit NetBranch(discipline_t*dis, perm_string name);
~NetBranch();
private:
discipline_t*discipline_;
perm_string name_;
};
class Link {
friend void connect(Link&, Link&);
friend void connect(Nexus*, Link&);
friend class NetObj;
friend class NetPins;
friend class Nexus;
public:
@ -189,8 +220,8 @@ class Link {
void set_init(verinum::V val);
verinum::V get_init() const;
void cur_link(NetObj*&net, unsigned &pin);
void cur_link(const NetObj*&net, unsigned &pin) const;
void cur_link(NetPins*&net, unsigned &pin);
void cur_link(const NetPins*&net, unsigned &pin) const;
// Get a pointer to the nexus that represents all the links
// connected to me.
@ -217,8 +248,8 @@ class Link {
// Return information about the object that this link is
// a part of.
const NetObj*get_obj() const;
NetObj*get_obj();
const NetPins*get_obj() const;
NetPins*get_obj();
unsigned get_pin() const;
// A link of an object (sometimes called a "pin") has a
@ -231,7 +262,7 @@ class Link {
private:
// The NetNode manages these. They point back to the
// NetNode so that following the links can get me here.
NetObj *node_;
NetPins *node_;
unsigned pin_;
DIR dir_;
@ -521,6 +552,10 @@ class NetNet : public NetObj {
bool get_isint() const;
void set_isint(bool);
/* Attach a discipline to the net. */
discipline_t* get_discipline() const;
void set_discipline(discipline_t*dis);
/* 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,
@ -588,6 +623,7 @@ class NetNet : public NetObj {
ivl_variable_type_t data_type_;
bool signed_;
bool isint_; // original type of integer
discipline_t*discipline_;
long msb_, lsb_;
const unsigned dimensions_;
@ -2880,7 +2916,7 @@ class NetEUFunc : public NetExpr {
class NetEAccess : public NetExpr {
public:
explicit NetEAccess(nature_t*nat);
explicit NetEAccess(NetBranch*br, nature_t*nat);
~NetEAccess();
virtual ivl_variable_type_t expr_type() const;
@ -2891,6 +2927,7 @@ class NetEAccess : public NetExpr {
virtual NexusSet* nex_input(bool rem_out = true);
private:
NetBranch*branch_;
nature_t*nature_;
};

View File

@ -205,6 +205,7 @@ void pform_attach_discipline(const struct vlltype&loc,
error_count += 1;
} else {
cur_net->set_data_type(IVL_VT_REAL);
cur_net->set_discipline(discipline);
}
}

View File

@ -152,10 +152,14 @@ ivl_expr_t dll_target::expr_from_value_(const verinum&val)
void dll_target::expr_access_func(const NetEAccess*net)
{
assert(expr_ == 0);
cerr << net->get_fileline() << ": internal error: "
<< "Nature access functions not implemented yet." << endl;
// Make a stub Branch Access Function expression node.
expr_ = (ivl_expr_t)calloc(1, sizeof(struct ivl_expr_s));
expr_->type_ = IVL_EX_BACCESS;
expr_->value_ = IVL_VT_REAL;
expr_->file = net->get_file();
expr_->lineno = net->get_lineno();
expr_->width_ = 1;
expr_->signed_= 1;
}
void dll_target::expr_binary(const NetEBinary*net)

View File

@ -43,6 +43,17 @@ static void show_array_expression(ivl_expr_t net, unsigned ind)
ivl_signal_dimensions(sig), width, vt);
}
static void show_branch_access_expression(ivl_expr_t net, unsigned ind)
{
fprintf(out, "%*s<Branch Access>\n", ind, "");
if (ivl_expr_value(net) != IVL_VT_REAL) {
fprintf(out, "%*sERROR: Expecting type IVL_VT_REAL, got %s\n",
ind, "", vt_type_string(net));
stub_errors += 1;
}
}
static void show_binary_expression(ivl_expr_t net, unsigned ind)
{
unsigned width = ivl_expr_width(net);
@ -216,6 +227,10 @@ void show_expression(ivl_expr_t net, unsigned ind)
show_array_expression(net, ind);
break;
case IVL_EX_BACCESS:
show_branch_access_expression(net, ind);
break;
case IVL_EX_BINARY:
show_binary_expression(net, ind);
break;