ivl_target.h access branch terminals

Fill in the functions to add branch terminals, and add code in the
stub to check that the terminals are present and reasonable.
This commit is contained in:
Stephen Williams 2008-11-23 22:38:33 -08:00
parent d8ec6fc42a
commit 87177087c4
7 changed files with 77 additions and 4 deletions

View File

@ -1,5 +1,7 @@
EXPORTS
ivl_branch_terminal
ivl_design_const
ivl_design_consts
ivl_design_discipline
@ -112,6 +114,8 @@ ivl_lval_part_off
ivl_lval_sig
ivl_lval_width
ivl_nature_name
ivl_nexus_get_private
ivl_nexus_name
ivl_nexus_ptrs

View File

@ -421,9 +421,11 @@ 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);
* Branches are analog constructs, a pair of terminals that is used in
* branch access functions. Terminal-1 is the reference node for the
* purposes of the access function that accesses it.
*/
/* 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
@ -589,6 +591,8 @@ extern ivl_dis_domain_t ivl_discipline_domain(ivl_discipline_t net);
extern ivl_nature_t ivl_discipline_potential(ivl_discipline_t net);
extern ivl_nature_t ivl_discipline_flow(ivl_discipline_t net);
extern const char* ivl_nature_name(ivl_nature_t net);
/* EVENTS
*
* Events are a unification of named events and implicit events

View File

@ -58,6 +58,10 @@ struct ivl_design_s {
const class Design*self;
};
/*
* A branch is a pair of terminals. The elaborator assures that the
* terminals have compatible disciplines.
*/
struct ivl_branch_s {
ivl_nexus_t pins[2];
};

View File

@ -31,6 +31,13 @@ static StringHeap api_strings;
/* THE FOLLOWING ARE FUNCTIONS THAT ARE CALLED FROM THE TARGET. */
extern "C" ivl_nexus_t ivl_branch_terminal(ivl_branch_t net, int idx)
{
assert(idx >= 0);
assert( idx < 2);
return net->pins[idx];
}
extern "C" const char*ivl_design_flag(ivl_design_t des, const char*key)
{
return des->self->get_flag(key);
@ -1315,6 +1322,11 @@ extern "C" ivl_signal_t ivl_lval_sig(ivl_lval_t net)
}
}
extern "C" const char* ivl_nature_name(ivl_nature_t net)
{
return net->name();
}
/*
* The nexus name is rarely needed. (Shouldn't be needed at all!) This
* function will calculate the name if it is not already calculated.

View File

@ -45,13 +45,42 @@ static void show_array_expression(ivl_expr_t net, unsigned ind)
static void show_branch_access_expression(ivl_expr_t net, unsigned ind)
{
fprintf(out, "%*s<Branch Access>\n", ind, "");
ivl_branch_t bra = ivl_expr_branch(net);
ivl_nature_t nature = ivl_expr_nature(net);
fprintf(out, "%*s<Access branch %p with nature %s>\n",
ind, "", bra, ivl_nature_name(nature));
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;
}
ivl_nexus_t ta = ivl_branch_terminal(bra, 0);
ivl_nexus_t tb = ivl_branch_terminal(bra, 1);
ivl_discipline_t ta_disc = discipline_of_nexus(ta);
if (ta_disc == 0) {
fprintf(out, "%*sERROR: Source terminal of branch has no discipline\n",
ind, "");
stub_errors += 1;
return;
}
ivl_discipline_t tb_disc = discipline_of_nexus(tb);
if (ta_disc == 0) {
fprintf(out, "%*sERROR: Reference terminal of branch has no discipline\n",
ind, "");
stub_errors += 1;
return;
}
if (ta_disc != tb_disc) {
fprintf(out, "%*sERROR: Branch terminal disciplines mismatch: %s != %s\n",
ind, "", ivl_discipline_name(ta_disc),
ivl_discipline_name(tb_disc));
stub_errors += 1;
}
}
static void show_binary_expression(ivl_expr_t net, unsigned ind)

View File

@ -44,6 +44,8 @@ extern unsigned width_of_nexus(ivl_nexus_t nex);
extern ivl_variable_type_t type_of_nexus(ivl_nexus_t nex);
extern ivl_discipline_t discipline_of_nexus(ivl_nexus_t nex);
/*
* Show the details of the expression.
*/

View File

@ -108,6 +108,24 @@ unsigned width_of_nexus(ivl_nexus_t nex)
return 0;
}
ivl_discipline_t discipline_of_nexus(ivl_nexus_t nex)
{
unsigned idx;
for (idx = 0 ; idx < ivl_nexus_ptrs(nex); idx += 1) {
ivl_nexus_ptr_t ptr = ivl_nexus_ptr(nex, idx);
ivl_signal_t sig = ivl_nexus_ptr_sig(ptr);
if (sig != 0) {
return ivl_signal_discipline(sig);
}
}
/* ERROR: A nexus should have at least one signal to carry
properties like the data type. */
return 0;
}
ivl_variable_type_t type_of_nexus(ivl_nexus_t net)
{
unsigned idx;