Branch references all the way down to the stub generator.

This includes enough API to get the branch nexus bits and signals
and show them in the dump. This also includes creating the reference
ground for branch access functions that use the implicit ground.
This commit is contained in:
Stephen Williams 2008-11-09 21:42:12 -08:00
parent 25201954d3
commit 00df651c5f
11 changed files with 155 additions and 75 deletions

View File

@ -138,9 +138,13 @@ ostream& operator <<(ostream&o, struct __ScopePathManip marg)
void NetBranch::dump(ostream&o, unsigned ind) const
{
o << setw(ind) << "" << "branch ...";
o << " island=" << get_island();
static const char*pin_names[2] = {
"terminal0",
"terminal1" };
o << setw(ind) << "" << "branch island=" << get_island();
o << " // " << get_fileline() << endl;
dump_node_pins(o, ind+4, pin_names);
}
void NetDelaySrc::dump(ostream&o, unsigned ind) const

View File

@ -1253,8 +1253,12 @@ NetExpr* PECallFunction::elaborate_access_func_(Design*des, NetScope*scope,
branch = new NetBranch(dis);
branch->set_line(*this);
des->add_branch(branch);
connect(branch->pin(0), sig->pin(0));
NetNet*gnd = des->find_discipline_reference(dis, scope);
connect(branch->pin(1), gnd->pin(0));
des->add_branch(branch);
join_island(branch);
} else {
@ -3043,3 +3047,24 @@ NetExpr* PEUnary::elaborate_expr_bits_(NetExpr*operand, int expr_wid) const
tmp->set_line(*this);
return tmp;
}
NetNet* Design::find_discipline_reference(ivl_discipline_t dis, NetScope*scope)
{
NetNet*gnd = discipline_references_[dis->name()];
if (gnd) return gnd;
string name = string(dis->name()) + "$gnd";
gnd = new NetNet(scope, lex_strings.make(name), NetNet::WIRE, 1);
gnd->set_discipline(dis);
gnd->data_type(IVL_VT_REAL);
discipline_references_[dis->name()] = gnd;
if (debug_elaborate)
cerr << gnd->get_fileline() << ": debug: "
<< "Create an implicit reference terminal"
<< " for discipline=" << dis->name()
<< " in scope=" << scope_path(scope) << endl;
return gnd;
}

View File

@ -116,6 +116,7 @@ ivl_nexus_ptrs
ivl_nexus_ptr
ivl_nexus_set_private
ivl_nexus_ptr_branch
ivl_nexus_ptr_con
ivl_nexus_ptr_drive0
ivl_nexus_ptr_drive1

View File

@ -60,6 +60,9 @@ _BEGIN_DECL
* This object represent an array that can be a memory or a net
* array. (They are the same from the perspective of ivl_target.h.)
*
* ivl_branch_t
* this object represents an analog branch.
*
* ivl_design_t
* This object represents the entire elaborated design. Various
* global properties and methods are available from this.
@ -149,6 +152,7 @@ _BEGIN_DECL
* throughout the design.
*/
typedef struct ivl_array_s *ivl_array_t;
typedef struct ivl_branch_s *ivl_branch_t;
typedef struct ivl_delaypath_s*ivl_delaypath_t;
typedef struct ivl_design_s *ivl_design_t;
typedef struct ivl_discipline_s*ivl_discipline_t;
@ -416,6 +420,12 @@ struct ivl_attribute_s {
};
typedef const struct ivl_attribute_s*ivl_attribute_t;
/* BRANCH
*/
extern ivl_discipline_t ivl_branch_discipline(ivl_branch_t obj);
extern ivl_scope_t ivl_branch_scope(ivl_branch_t obj);
extern ivl_nexus_t ivl_branch_terminal(ivl_branch_t obj, int idx);
/* DELAYPATH
* Delaypath objects represent delay paths called out by a specify
* block in the Verilog source file. The destination signal references
@ -1383,6 +1393,7 @@ extern void* ivl_nexus_get_private(ivl_nexus_t net);
extern ivl_drive_t ivl_nexus_ptr_drive0(ivl_nexus_ptr_t net);
extern ivl_drive_t ivl_nexus_ptr_drive1(ivl_nexus_ptr_t net);
extern unsigned ivl_nexus_ptr_pin(ivl_nexus_ptr_t net);
extern ivl_branch_t ivl_nexus_ptr_branch(ivl_nexus_ptr_t net);
extern ivl_net_const_t ivl_nexus_ptr_con(ivl_nexus_ptr_t net);
extern ivl_net_logic_t ivl_nexus_ptr_log(ivl_nexus_ptr_t net);
extern ivl_lpm_t ivl_nexus_ptr_lpm(ivl_nexus_ptr_t net);

View File

@ -22,11 +22,20 @@
# include <inttypes.h>
/*
* This deader has declarations related to the ivl_target.h API that
* This header has declarations related to the ivl_target.h API that
* are not to be exported outside of the core via the ivl_target.h
* interface.
*
* (NOTE: A lot of similar definitions exist in the t-dll.h header
* file. That is a legacy from an earlier time before the
* ivl_target_priv.h header file was started, and those definitions
* should gradually be moved over to this header file.)
*/
struct ivl_branch_s {
ivl_nexus_t pins[2];
};
/*
* Information about islands. Connected branches within a net are
* collected into islands. Branches that are purely ddiscrete do not

View File

@ -36,7 +36,7 @@
# include "ivl_assert.h"
Design:: Design()
: errors(0), nodes_(0), procs_(0), aprocs_(0), lcounter_(0)
: errors(0), nodes_(0), procs_(0), aprocs_(0)
{
branches_ = 0;
procs_idx_ = 0;
@ -49,15 +49,6 @@ Design::~Design()
{
}
string Design::local_symbol(const string&path)
{
ostringstream res;
res << path << "." << "_L" << lcounter_;
lcounter_ += 1;
return res.str();
}
void Design::set_precision(int val)
{
if (val < des_precision_)

View File

@ -3886,6 +3886,8 @@ class Design {
void delete_process(NetProcTop*);
bool check_always_delay() const;
NetNet* find_discipline_reference(ivl_discipline_t dis, NetScope*scope);
// Iterate over the design...
void dump(ostream&) const;
void functor(struct functor_t*);
@ -3896,9 +3898,6 @@ class Design {
// detected. It prevents code being emitted.
unsigned errors;
public:
string local_symbol(const string&path);
private:
// Keep a tree of scopes. The NetScope class handles the wide
// tree and per-hop searches for me.
@ -3917,14 +3916,17 @@ class Design {
NetProcTop*procs_;
NetProcTop*procs_idx_;
// List the ANALOG processes in the design.
NetAnalogTop*aprocs_;
// Map of discipline take to NetNet for the reference node.
map<perm_string,NetNet*>discipline_references_;
// Map the design arguments to values.
map<string,const char*> flags_;
int des_precision_;
unsigned lcounter_;
private: // not implemented
Design(const Design&);
Design& operator= (const Design&);

View File

@ -1318,14 +1318,14 @@ extern "C" void ivl_nexus_set_private(ivl_nexus_t net, void*data)
extern "C" unsigned ivl_nexus_ptrs(ivl_nexus_t net)
{
assert(net);
return net->nptr_;
return net->ptrs_.size();
}
extern "C" ivl_nexus_ptr_t ivl_nexus_ptr(ivl_nexus_t net, unsigned idx)
{
assert(net);
assert(idx < net->nptr_);
return net->ptrs_ + idx;
assert(idx < net->ptrs_.size());
return & net->ptrs_[idx];
}
extern "C" ivl_drive_t ivl_nexus_ptr_drive0(ivl_nexus_ptr_t net)
@ -1346,6 +1346,15 @@ extern "C" unsigned ivl_nexus_ptr_pin(ivl_nexus_ptr_t net)
return net->pin_;
}
extern "C" ivl_branch_t ivl_nexus_ptr_branch(ivl_nexus_ptr_t net)
{
if (net == 0)
return 0;
if (net->type_ != __NEXUS_PTR_BRA)
return 0;
return net->l.bra;
}
extern "C" ivl_net_const_t ivl_nexus_ptr_con(ivl_nexus_ptr_t net)
{
if (net == 0)

122
t-dll.cc
View File

@ -128,6 +128,11 @@ void* ivl_nexus_s::operator new(size_t s)
return tmp;
}
void ivl_nexus_s::operator delete(void*, size_t)
{
assert(0);
}
inline static const char *basename(ivl_scope_t scope, const char *inst)
{
inst += strlen(ivl_scope_name(scope));
@ -281,10 +286,7 @@ ivl_signal_t dll_target::find_signal(ivl_design_s &des, const NetNet*net)
static ivl_nexus_t nexus_sig_make(ivl_signal_t net, unsigned pin)
{
ivl_nexus_t tmp = new struct ivl_nexus_s;
tmp->private_data = 0;
tmp->nptr_ = 1;
tmp->ptrs_ = (struct ivl_nexus_ptr_s*)
malloc(sizeof(struct ivl_nexus_ptr_s));
tmp->ptrs_.resize(1);
tmp->ptrs_[0].pin_ = pin;
tmp->ptrs_[0].type_ = __NEXUS_PTR_SIG;
tmp->ptrs_[0].l.sig = net;
@ -305,11 +307,8 @@ static ivl_nexus_t nexus_sig_make(ivl_signal_t net, unsigned pin)
static void nexus_sig_add(ivl_nexus_t nex, ivl_signal_t net, unsigned pin)
{
unsigned top = nex->nptr_ + 1;
nex->ptrs_ = (struct ivl_nexus_ptr_s*)
realloc(nex->ptrs_, top * sizeof(struct ivl_nexus_ptr_s));
nex->nptr_ = top;
unsigned top = nex->ptrs_.size();
nex->ptrs_.resize(top+1);
ivl_drive_t drive = IVL_DR_HiZ;
switch (ivl_signal_type(net)) {
case IVL_SIT_REG:
@ -319,11 +318,22 @@ static void nexus_sig_add(ivl_nexus_t nex, ivl_signal_t net, unsigned pin)
break;
}
nex->ptrs_[top-1].type_= __NEXUS_PTR_SIG;
nex->ptrs_[top-1].drive0 = drive;
nex->ptrs_[top-1].drive1 = drive;
nex->ptrs_[top-1].pin_ = pin;
nex->ptrs_[top-1].l.sig= net;
nex->ptrs_[top].type_= __NEXUS_PTR_SIG;
nex->ptrs_[top].drive0 = drive;
nex->ptrs_[top].drive1 = drive;
nex->ptrs_[top].pin_ = pin;
nex->ptrs_[top].l.sig= net;
}
static void nexus_bra_add(ivl_nexus_t nex, ivl_branch_t net, unsigned pin)
{
unsigned top = nex->ptrs_.size();
nex->ptrs_.resize(top+1);
nex->ptrs_[top].type_= __NEXUS_PTR_BRA;
nex->ptrs_[top].drive0 = 0;
nex->ptrs_[top].drive1 = 0;
nex->ptrs_[top].pin_ = pin;
nex->ptrs_[top].l.bra= net;
}
/*
@ -337,62 +347,54 @@ static ivl_nexus_ptr_t nexus_log_add(ivl_nexus_t nex,
ivl_net_logic_t net,
unsigned pin)
{
unsigned top = nex->nptr_ + 1;
nex->ptrs_ = (struct ivl_nexus_ptr_s*)
realloc(nex->ptrs_, top * sizeof(struct ivl_nexus_ptr_s));
nex->nptr_ = top;
unsigned top = nex->ptrs_.size();
nex->ptrs_.resize(top+1);
nex->ptrs_[top-1].type_= __NEXUS_PTR_LOG;
nex->ptrs_[top-1].drive0 = (pin == 0)? IVL_DR_STRONG : IVL_DR_HiZ;
nex->ptrs_[top-1].drive1 = (pin == 0)? IVL_DR_STRONG : IVL_DR_HiZ;
nex->ptrs_[top-1].pin_ = pin;
nex->ptrs_[top-1].l.log= net;
nex->ptrs_[top].type_= __NEXUS_PTR_LOG;
nex->ptrs_[top].drive0 = (pin == 0)? IVL_DR_STRONG : IVL_DR_HiZ;
nex->ptrs_[top].drive1 = (pin == 0)? IVL_DR_STRONG : IVL_DR_HiZ;
nex->ptrs_[top].pin_ = pin;
nex->ptrs_[top].l.log= net;
return nex->ptrs_ + top - 1;
return & (nex->ptrs_[top]);
}
static void nexus_con_add(ivl_nexus_t nex, ivl_net_const_t net, unsigned pin,
ivl_drive_t drive0, ivl_drive_t drive1)
{
unsigned top = nex->nptr_ + 1;
nex->ptrs_ = (struct ivl_nexus_ptr_s*)
realloc(nex->ptrs_, top * sizeof(struct ivl_nexus_ptr_s));
nex->nptr_ = top;
unsigned top = nex->ptrs_.size();
nex->ptrs_.resize(top+1);
nex->ptrs_[top-1].type_= __NEXUS_PTR_CON;
nex->ptrs_[top-1].drive0 = drive0;
nex->ptrs_[top-1].drive1 = drive1;
nex->ptrs_[top-1].pin_ = pin;
nex->ptrs_[top-1].l.con= net;
nex->ptrs_[top].type_= __NEXUS_PTR_CON;
nex->ptrs_[top].drive0 = drive0;
nex->ptrs_[top].drive1 = drive1;
nex->ptrs_[top].pin_ = pin;
nex->ptrs_[top].l.con= net;
}
static void nexus_lpm_add(ivl_nexus_t nex, ivl_lpm_t net, unsigned pin,
ivl_drive_t drive0, ivl_drive_t drive1)
{
unsigned top = nex->nptr_ + 1;
nex->ptrs_ = (struct ivl_nexus_ptr_s*)
realloc(nex->ptrs_, top * sizeof(struct ivl_nexus_ptr_s));
nex->nptr_ = top;
unsigned top = nex->ptrs_.size();
nex->ptrs_.resize(top+1);
nex->ptrs_[top-1].type_= __NEXUS_PTR_LPM;
nex->ptrs_[top-1].drive0 = drive0;
nex->ptrs_[top-1].drive1 = drive0;
nex->ptrs_[top-1].pin_ = pin;
nex->ptrs_[top-1].l.lpm= net;
nex->ptrs_[top].type_= __NEXUS_PTR_LPM;
nex->ptrs_[top].drive0 = drive0;
nex->ptrs_[top].drive1 = drive0;
nex->ptrs_[top].pin_ = pin;
nex->ptrs_[top].l.lpm= net;
}
static void nexus_switch_add(ivl_nexus_t nex, ivl_switch_t net, unsigned pin)
{
unsigned top = nex->nptr_ + 1;
nex->ptrs_ = (struct ivl_nexus_ptr_s*)
realloc(nex->ptrs_, top*sizeof(struct ivl_nexus_ptr_s));
nex->nptr_ = top;
unsigned top = nex->ptrs_.size();
nex->ptrs_.resize(top+1);
nex->ptrs_[top-1].type_= __NEXUS_PTR_SWI;
nex->ptrs_[top-1].drive0 = IVL_DR_HiZ;
nex->ptrs_[top-1].drive1 = IVL_DR_HiZ;
nex->ptrs_[top-1].pin_ = pin;
nex->ptrs_[top-1].l.swi= net;
nex->ptrs_[top].type_= __NEXUS_PTR_SWI;
nex->ptrs_[top].drive0 = IVL_DR_HiZ;
nex->ptrs_[top].drive1 = IVL_DR_HiZ;
nex->ptrs_[top].pin_ = pin;
nex->ptrs_[top].l.swi= net;
}
void scope_add_logic(ivl_scope_t scope, ivl_net_logic_t net)
@ -776,6 +778,22 @@ void dll_target::make_const_delays_(struct ivl_net_const_s*obj,
}
}
bool dll_target::branch(const NetBranch*net)
{
struct ivl_branch_s*obj = new struct ivl_branch_s;
ivl_assert(*net, net->pin_count() == 2);
assert(net->pin(0).nexus()->t_cookie());
obj->pins[0] = net->pin(0).nexus()->t_cookie();
nexus_bra_add(obj->pins[0], obj, 0);
assert(net->pin(1).nexus()->t_cookie());
obj->pins[1] = net->pin(1).nexus()->t_cookie();
nexus_bra_add(obj->pins[1], obj, 1);
return true;
}
/*
* Add a bufz object to the scope that contains it.
*
@ -2504,6 +2522,7 @@ void dll_target::signal(const NetNet*net)
for (unsigned idx = 0 ; idx < obj->array_words ; idx += 1) {
const Nexus*nex = net->pin(idx).nexus();
ivl_assert(*net, nex);
if (nex->t_cookie()) {
if (obj->array_words > 1) {
obj->pins[idx] = nex->t_cookie();
@ -2522,6 +2541,7 @@ void dll_target::signal(const NetNet*net)
else
obj->pin = tmp;
}
ivl_assert(*net, net->pin(idx).nexus()->t_cookie());
}
}

View File

@ -71,6 +71,7 @@ struct dll_target : public target_t, public expr_scan_t {
int end_design(const Design*);
bool bufz(const NetBUFZ*);
bool branch(const NetBranch*);
void event(const NetEvent*);
void logic(const NetLogic*);
bool tran(const NetTran*);
@ -516,6 +517,7 @@ struct ivl_nexus_ptr_s {
ivl_net_const_t con; /* type 2 */
ivl_lpm_t lpm; /* type 3 */
ivl_switch_t swi; /* type 4 */
ivl_branch_t bra; /* type 5 */
} l;
};
# define __NEXUS_PTR_SIG 0
@ -523,13 +525,14 @@ struct ivl_nexus_ptr_s {
# define __NEXUS_PTR_CON 2
# define __NEXUS_PTR_LPM 3
# define __NEXUS_PTR_SWI 4
# define __NEXUS_PTR_BRA 5
/*
* NOTE: ONLY allocate ivl_nexus_s objects with the included "new" operator.
*/
struct ivl_nexus_s {
unsigned nptr_;
struct ivl_nexus_ptr_s*ptrs_;
ivl_nexus_s() : ptrs_(1), nexus_(0), name_(0), private_data(0) { }
vector<ivl_nexus_ptr_s>ptrs_;
const Nexus*nexus_;
const char*name_;
void*private_data;

View File

@ -1132,6 +1132,7 @@ static void show_nexus_details(ivl_signal_t net, ivl_nexus_t nex)
ivl_lpm_t lpm;
ivl_signal_t sig;
ivl_switch_t swt;
ivl_branch_t bra;
ivl_nexus_ptr_t ptr = ivl_nexus_ptr(nex, idx);
const char*dr0 = str_tab[ivl_nexus_ptr_drive0(ptr)];
@ -1173,6 +1174,10 @@ static void show_nexus_details(ivl_signal_t net, ivl_nexus_t nex)
} else if ((con = ivl_nexus_ptr_con(ptr))) {
signal_nexus_const(net, ptr, con);
} else if ((bra = ivl_nexus_ptr_branch(ptr))) {
fprintf(out, " BRANCH %p terminal %u\n",
bra, ivl_nexus_ptr_pin(ptr));
} else {
fprintf(out, " ?[%u] (%s0, %s1)\n",
ivl_nexus_ptr_pin(ptr), dr0, dr1);