Scopes and processes are accessible randomly from

the design, and signals and logic are accessible
 from scopes. Remove the target calls that are no
 longer needed.

 Add the ivl_nexus_ptr_t and the means to get at
 them from nexus objects.

 Give names to methods that manipulate the ivl_design_t
 type more consistent names.
This commit is contained in:
steve 2000-10-15 04:46:23 +00:00
parent 7ee46bc621
commit 2dedd6c067
7 changed files with 563 additions and 485 deletions

View File

@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT) && !defined(macintosh)
#ident "$Id: ivl_target.h,v 1.19 2000/10/13 03:39:27 steve Exp $"
#ident "$Id: ivl_target.h,v 1.20 2000/10/15 04:46:23 steve Exp $"
#endif
#ifdef __cplusplus
@ -78,6 +78,13 @@ _BEGIN_DECL
* single output, including logic gates and nmos, pmos and cmon
* devices. There is also the occasional Icarus Verilog creation.
*
* ivl_nexus_t
* Structural links within an elaborated design are connected
* together at each bit. The connection point is a nexus, so pins
* of devices refer to an ivl_nexus_t. Furthermore, from a nexus
* there are backward references to all the device pins that point
* to it.
*
* ivl_process_t
* A Verilog process is represented by one of these. A process may
* be an "initial" or an "always" process. These come from initial
@ -111,6 +118,7 @@ typedef struct ivl_net_event_s*ivl_net_event_t;
typedef struct ivl_net_logic_s*ivl_net_logic_t;
typedef struct ivl_net_probe_s*ivl_net_probe_t;
typedef struct ivl_nexus_s *ivl_nexus_t;
typedef struct ivl_nexus_ptr_s*ivl_nexus_ptr_t;
typedef struct ivl_process_s *ivl_process_t;
typedef struct ivl_scope_s *ivl_scope_t;
typedef struct ivl_signal_s *ivl_signal_t;
@ -200,21 +208,45 @@ typedef enum ivl_statement_type_e {
IVL_ST_WHILE
} ivl_statement_type_t;
/* This is the type of the function to apply to a process. */
typedef int (*ivl_process_f)(ivl_process_t net);
/* This function returns the string value of the named flag. The key
is used to select the flag. If the key does not exist or the flag
does not have a value, this function returns 0.
/* This is the type of a function to apply to a scope. */
typedef int (ivl_scope_f)(ivl_scope_t net);
Flags come from the "-fkey=value" options to the iverilog command
line.
The key "-o" is special and is the argument to the -o flag of the
iverilog command. This is generally how the target learns the name
of the output file. */
extern const char* ivl_get_flag(ivl_design_t, const char*key);
/* DESIGN
* When handed a design (ivl_design_t) there are a few things that you
* can do with it. The Verilog program has one design that carries the
* entire program. Use the design methods to iterate over the elements
* of the design.
*
* ivl_design_flag
* This function returns the string value of a named flag. Flags
* come from the "-fkey=value" options to the iverilog command and
* are stored in a map for this function. Given the key, this
* function returns the value.
*
* The special key "-o" is the argument to the -o flag of the
* command line (or the default if the -o flag is not used) and is
* generally how the target learns the name of the output file.
*
* ivl_design_process
* This function scans the processes (threads) in the design. It
* calls the user suplied function on each of the processes until
* one of the functors returns non-0 or all the processes are
* scanned. This function will return 0, or the non-zero value that
* was returned from the last scanned process.
*
* ivl_design_root
* A design has a root named scope that is an instance of the top
* level module in the design. This is a hook for naming the
* design, or for starting the scope scan.
*/
/* Get the name of the root module. This can be used as the design name. */
extern const char* ivl_get_root_name(ivl_design_t net);
extern const char* ivl_design_flag(ivl_design_t des, const char*key);
extern int ivl_design_process(ivl_design_t des, ivl_process_f fun);
extern ivl_scope_t ivl_design_root(ivl_design_t des);
/*
* These methods apply to ivl_net_const_t objects.
@ -256,25 +288,96 @@ extern unsigned ivl_expr_width(ivl_expr_t net);
* ivl_logic_t enumeration identifies the various kinds of gates that
* the ivl_net_logic_t can represent. The various functions then
* provide access to the bits of information for a given logic device.
*
* ivl_logic_type
* This method returns the type of logic gate that the cookie
* represents.
*
* ivl_logic_name
* This method returns the complete name of the logic gate. Every
* gate has a complete name (that includes the scope) even if the
* Verilog source doesn't include one. The compiler will choose one
* if necessary.
*
* ivl_logic_basename
* This is the name of the gate without the scope part.
*
* ivl_logic_pins
* ivl_logic_pin
*/
extern const char* ivl_logic_name(ivl_net_logic_t net);
extern const char* ivl_logic_basename(ivl_net_logic_t net);
extern ivl_logic_t ivl_logic_type(ivl_net_logic_t net);
extern ivl_nexus_t ivl_logic_pin(ivl_net_logic_t net, unsigned pin);
extern unsigned ivl_logic_pins(ivl_net_logic_t net);
/* NEXUS
* connections of signals and nodes is handled by single-bit
* nexus. These functions manage the ivl_nexus_t object.
* nexus. These functions manage the ivl_nexus_t object. They also
* manage the ivl_nexus_ptr_t objects that are closely related to the
* nexus.
*
* ivl_nexus_name
* Each nexus is given a name, typically derived from the signals
* connected to it, but completely made up if need be. The name of
* every nexus is unique.
*
* ivl_nexus_ptrs
* This function returns the number of pointers that are held by
* the nexus. It should always return at least 1. The pointer
* proper is accessed by index.
*
* ivl_nexus_ptr
* Return a nexus pointer given the nexus and an index.
*/
extern const char* ivl_nexus_name(ivl_nexus_t net);
extern const char* ivl_nexus_name(ivl_nexus_t net);
extern unsigned ivl_nexus_ptrs(ivl_nexus_t net);
extern ivl_nexus_ptr_t ivl_nexus_ptr(ivl_nexus_t net, unsigned idx);
/* SCOPE
* Scopes of various sort have these properties. Use these methods to
* access them.
* access them. Scopes come to exist in the elaborated design
* generally when a module is instantiated, though they also come from
* named blocks, tasks and functions.
*
* (NOTE: Module scopes are *instances* of modules, and not the module
* definition. A definition may apply to many instances.)
*
* ivl_scope_children
* A scope may in turn contain other scopes. This method iterates
* through all the child scopes of a given scope. If the function
* returns any value other then 0, the iteration stops and the
* method returns that value. Otherwise, iteration continues until
* the children run out.
*
* If the scope has no children, this method will return 0 and
* otherwise do nothing.
*
* ivl_scope_log
* ivl_scope_logs
* Scopes have 0 or more logic devices in them. A logic device is
* represented by ivl_logic_t.
*
* ivl_scope_name
* Every scope has a hierarchical name. This name is also a prefix
* of all the names of objects contained within the scope.
*
* ivl_scope_sig
* ivl_scope_sigs
* Scopes have 0 or more signals in them. These signals are
* anything that can become and ivl_signal_t, include synthetic
* signals generated by the compiler.
*/
extern const char* ivl_scope_name(ivl_scope_t net);
extern int ivl_scope_children(ivl_scope_t net, ivl_scope_f func);
extern unsigned ivl_scope_logs(ivl_scope_t net);
extern ivl_net_logic_t ivl_scope_log(ivl_scope_t net, unsigned idx);
extern const char* ivl_scope_name(ivl_scope_t net);
extern unsigned ivl_scope_sigs(ivl_scope_t net);
extern ivl_signal_t ivl_scope_sig(ivl_scope_t net, unsigned idx);
/* SIGNALS
@ -403,14 +506,6 @@ typedef int (*net_const_f)(const char*name, ivl_net_const_t net);
typedef int (*net_event_f)(const char*name, ivl_net_event_t net);
/* target_net_logic
This function is called for each logic gate in the design. The name
parameter is the name of the gate in the design. If the gate is
part of an array of gates, the name includes its index. */
typedef int (*net_logic_f)(const char*name, ivl_net_logic_t net);
/* target_net_probe
This is the probe, or structural trigger, of an event. The
@ -418,41 +513,23 @@ typedef int (*net_logic_f)(const char*name, ivl_net_logic_t net);
before this probe is called. */
typedef int (*net_probe_f)(const char*name, ivl_net_probe_t net);
/* target_net_signal
Signals are things like "wire foo" or "reg bar;" that is, declared
signals in the verilog source. These are not memories, which are
handled elsewhere. */
typedef int (*net_signal_f)(const char*name, ivl_signal_t net);
/* target_process
The "target_process" function is called for each always and initial
block in the design. In principle, the target creates a thread for
each process in the Verilog original.
This function is called with the entire thread generated. The
process and statement access methods can be used to randomly
(read-only) access all the code of the thread. Also, the module may
hold on to the process, the core will not delete it. */
typedef int (*process_f)(ivl_process_t net);
/* target_scope (optional)
If the "target_scope" function is implemented in the module, it is
called to introduce a new scope in the design. If scopes are
nested, this method is always called for the containing scope
before the contained scope. Also, this is guaranteed to be called
before functions for any objects contained in this scope. */
typedef void (*scope_f)(ivl_scope_t net);
_END_DECL
/*
* $Log: ivl_target.h,v $
* Revision 1.20 2000/10/15 04:46:23 steve
* Scopes and processes are accessible randomly from
* the design, and signals and logic are accessible
* from scopes. Remove the target calls that are no
* longer needed.
*
* Add the ivl_nexus_ptr_t and the means to get at
* them from nexus objects.
*
* Give names to methods that manipulate the ivl_design_t
* type more consistent names.
*
* Revision 1.19 2000/10/13 03:39:27 steve
* Include constants in nexus targets.
*
@ -476,49 +553,5 @@ _END_DECL
* Revision 1.14 2000/09/30 02:18:15 steve
* ivl_expr_t support for binary operators,
* Create a proper ivl_scope_t object.
*
* Revision 1.13 2000/09/26 00:30:07 steve
* Add EX_NUMBER and ST_TRIGGER to dll-api.
*
* Revision 1.12 2000/09/24 15:46:00 steve
* API access to signal type and port type.
*
* Revision 1.11 2000/09/24 02:21:53 steve
* Add support for signal expressions.
*
* Revision 1.10 2000/09/23 05:15:07 steve
* Add enough tgt-verilog code to support hello world.
*
* Revision 1.9 2000/09/22 03:58:30 steve
* Access to the name of a system task call.
*
* Revision 1.8 2000/09/19 04:15:27 steve
* Introduce the means to get statement types.
*
* Revision 1.7 2000/09/18 01:24:32 steve
* Get the structure for ivl_statement_t worked out.
*
* Revision 1.6 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.
*
* Revision 1.5 2000/08/26 00:54:03 steve
* Get at gate information for ivl_target interface.
*
* Revision 1.4 2000/08/20 04:13:57 steve
* Add ivl_target support for logic gates, and
* make the interface more accessible.
*
* Revision 1.3 2000/08/19 18:12:42 steve
* Add target calls for scope, events and logic.
*
* Revision 1.2 2000/08/14 04:39:56 steve
* add th t-dll functions for net_const, net_bufz and processes.
*
* Revision 1.1 2000/08/12 16:34:37 steve
* Start stub for loadable targets.
*
*/
#endif

View File

@ -17,13 +17,34 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT) && !defined(macintosh)
#ident "$Id: t-dll-api.cc,v 1.11 2000/10/08 04:01:54 steve Exp $"
#ident "$Id: t-dll-api.cc,v 1.12 2000/10/15 04:46:23 steve Exp $"
#endif
# include "t-dll.h"
/* THE FOLLOWING ARE FUNCTIONS THAT ARE CALLED FROM THE TARGET. */
extern "C" const char*ivl_design_flag(ivl_design_t des, const char*key)
{
return des->self->get_flag(key).c_str();
}
extern "C" int ivl_design_process(ivl_design_t des, ivl_process_f func)
{
for (ivl_process_t idx = des->threads_; idx; idx = idx->next_) {
int rc = (func)(idx);
if (rc != 0)
return rc;
}
return 0;
}
extern "C" ivl_scope_t ivl_design_root(ivl_design_t des)
{
return des->root_;
}
extern "C" ivl_expr_type_t ivl_expr_type(ivl_expr_t net)
{
if (net == 0)
@ -31,16 +52,6 @@ extern "C" ivl_expr_type_t ivl_expr_type(ivl_expr_t net)
return net->type_;
}
extern "C" const char*ivl_get_flag(ivl_design_t des, const char*key)
{
return des->self->get_flag(key).c_str();
}
extern "C" const char*ivl_get_root_name(ivl_design_t des)
{
return des->root_->name_;
}
extern "C" const char*ivl_const_bits(ivl_net_const_t net)
{
assert(net);
@ -153,6 +164,21 @@ extern "C" unsigned ivl_expr_width(ivl_expr_t net)
return net->width_;
}
extern "C" const char* ivl_logic_name(ivl_net_logic_t net)
{
assert(net);
return net->name_;
}
extern "C" const char* ivl_logic_basename(ivl_net_logic_t net)
{
const char*nam = net->name_;
nam += strlen(ivl_scope_name(net->scope_));
assert(*nam == '.');
nam += 1;
return nam;
}
extern "C" ivl_logic_t ivl_logic_type(ivl_net_logic_t net)
{
return net->type_;
@ -175,6 +201,19 @@ extern "C" const char* ivl_nexus_name(ivl_nexus_t net)
return net->name_;
}
extern "C" unsigned ivl_nexus_ptrs(ivl_nexus_t net)
{
assert(net);
return net->nptr_;
}
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;
}
extern "C" ivl_process_type_t ivl_process_type(ivl_process_t net)
{
return net->type_;
@ -185,11 +224,48 @@ extern "C" ivl_statement_t ivl_process_stmt(ivl_process_t net)
return net->stmt_;
}
extern "C" int ivl_scope_children(ivl_scope_t net, ivl_scope_f func)
{
for (ivl_scope_t cur = net->child_; cur; cur = cur->sibling_) {
int rc = func(cur);
if (rc != 0)
return rc;
}
return 0;
}
extern "C" unsigned ivl_scope_logs(ivl_scope_t net)
{
assert(net);
return net->nlog_;
}
extern "C" ivl_net_logic_t ivl_scope_log(ivl_scope_t net, unsigned idx)
{
assert(net);
assert(idx < net->nlog_);
return net->log_[idx];
}
extern "C" const char* ivl_scope_name(ivl_scope_t net)
{
return net->name_;
}
extern "C" unsigned ivl_scope_sigs(ivl_scope_t net)
{
assert(net);
return net->nsigs_;
}
extern "C" ivl_signal_t ivl_scope_sig(ivl_scope_t net, unsigned idx)
{
assert(net);
assert(idx < net->nsigs_);
return net->sigs_[idx];
}
extern "C" const char* ivl_signal_basename(ivl_signal_t net)
{
const char*nam = net->name_;
@ -340,6 +416,18 @@ extern "C" ivl_statement_t ivl_stmt_sub_stmt(ivl_statement_t net)
/*
* $Log: t-dll-api.cc,v $
* Revision 1.12 2000/10/15 04:46:23 steve
* Scopes and processes are accessible randomly from
* the design, and signals and logic are accessible
* from scopes. Remove the target calls that are no
* longer needed.
*
* Add the ivl_nexus_ptr_t and the means to get at
* them from nexus objects.
*
* Give names to methods that manipulate the ivl_design_t
* type more consistent names.
*
* Revision 1.11 2000/10/08 04:01:54 steve
* Back pointers in the nexus objects into the devices
* that point to it.

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT) && !defined(macintosh)
#ident "$Id: t-dll.cc,v 1.14 2000/10/13 03:39:27 steve Exp $"
#ident "$Id: t-dll.cc,v 1.15 2000/10/15 04:46:23 steve Exp $"
#endif
# include "compiler.h"
@ -40,12 +40,12 @@ static ivl_scope_t find_scope(ivl_scope_t root, const NetScope*cur)
parent = find_scope(root, par);
} else {
assert(root->self == cur);
assert(strcmp(root->name_, cur->name().c_str()) == 0);
return root;
}
for (tmp = parent->child_ ; tmp ; tmp = tmp->sibling_)
if (tmp->self == cur)
if (strcmp(tmp->name_, cur->name().c_str()) == 0)
return tmp;
return 0;
@ -55,7 +55,8 @@ static ivl_nexus_t nexus_sig_make(ivl_signal_t net, unsigned pin)
{
ivl_nexus_t tmp = new struct ivl_nexus_s;
tmp->nptr_ = 1;
tmp->ptrs_ = (struct __nexus_ptr*) malloc(sizeof(struct __nexus_ptr));
tmp->ptrs_ = (struct ivl_nexus_ptr_s*)
malloc(sizeof(struct ivl_nexus_ptr_s));
tmp->ptrs_[0].pin_ = pin;
tmp->ptrs_[0].type_ = __NEXUS_PTR_SIG;
tmp->ptrs_[0].l.sig = net;
@ -65,8 +66,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 __nexus_ptr*)
realloc(nex->ptrs_, top * sizeof(struct __nexus_ptr));
nex->ptrs_ = (struct ivl_nexus_ptr_s*)
realloc(nex->ptrs_, top * sizeof(struct ivl_nexus_ptr_s));
nex->nptr_ = top;
nex->ptrs_[top-1].type_= __NEXUS_PTR_SIG;
@ -77,8 +78,8 @@ static void nexus_sig_add(ivl_nexus_t nex, ivl_signal_t net, unsigned pin)
static void nexus_log_add(ivl_nexus_t nex, ivl_net_logic_t net, unsigned pin)
{
unsigned top = nex->nptr_ + 1;
nex->ptrs_ = (struct __nexus_ptr*)
realloc(nex->ptrs_, top * sizeof(struct __nexus_ptr));
nex->ptrs_ = (struct ivl_nexus_ptr_s*)
realloc(nex->ptrs_, top * sizeof(struct ivl_nexus_ptr_s));
nex->nptr_ = top;
nex->ptrs_[top-1].type_= __NEXUS_PTR_LOG;
@ -89,8 +90,8 @@ static void nexus_log_add(ivl_nexus_t nex, ivl_net_logic_t net, unsigned pin)
static void nexus_con_add(ivl_nexus_t nex, ivl_net_const_t net, unsigned pin)
{
unsigned top = nex->nptr_ + 1;
nex->ptrs_ = (struct __nexus_ptr*)
realloc(nex->ptrs_, top * sizeof(struct __nexus_ptr));
nex->ptrs_ = (struct ivl_nexus_ptr_s*)
realloc(nex->ptrs_, top * sizeof(struct ivl_nexus_ptr_s));
nex->nptr_ = top;
nex->ptrs_[top-1].type_= __NEXUS_PTR_CON;
@ -130,18 +131,13 @@ bool dll_target::start_design(const Design*des)
des_.self = des;
des_.root_ = new struct ivl_scope_s;
des_.root_->name_ = strdup(des->find_root_scope()->name().c_str());
des_.root_->self = des->find_root_scope();
start_design_ = (start_design_f)dlsym(dll_, LU "target_start_design" TU);
end_design_ = (end_design_f) dlsym(dll_, LU "target_end_design" TU);
net_const_ = (net_const_f) dlsym(dll_, LU "target_net_const" TU);
net_event_ = (net_event_f) dlsym(dll_, LU "target_net_event" TU);
net_logic_ = (net_logic_f) dlsym(dll_, LU "target_net_logic" TU);
net_probe_ = (net_probe_f) dlsym(dll_, LU "target_net_probe" TU);
net_signal_ = (net_signal_f)dlsym(dll_, LU "target_net_signal" TU);
process_ = (process_f) dlsym(dll_, LU "target_process" TU);
scope_ = (scope_f) dlsym(dll_, LU "target_scope" TU);
(start_design_)(&des_);
return true;
@ -153,17 +149,6 @@ bool dll_target::start_design(const Design*des)
*/
void dll_target::end_design(const Design*)
{
if (process_) {
for (ivl_process_t idx = des_.threads_; idx; idx = idx->next_) {
process_(idx);
}
} else {
cerr << dll_path_ << ": internal error: target DLL lacks "
<< "target_process function." << endl;
}
(end_design_)(&des_);
dlclose(dll_);
}
@ -186,7 +171,6 @@ bool dll_target::bufz(const NetBUFZ*net)
obj->npins_ = 2;
obj->pins_ = new ivl_nexus_t[2];
/* Get the ivl_nexus_t objects connected to the two pins.
(We know a priori that the ivl_nexus_t objects have been
@ -208,13 +192,10 @@ bool dll_target::bufz(const NetBUFZ*net)
ivl_scope_t scope = find_scope(des_.root_, net->scope());
assert(scope);
obj->scope_ = scope;
obj->name_ = strdup(net->name());
scope_add_logic(scope, obj);
if (net_logic_) {
(net_logic_)(net->name(), obj);
}
return true;
}
@ -270,12 +251,10 @@ void dll_target::logic(const NetLogic*net)
ivl_scope_t scope = find_scope(des_.root_, net->scope());
assert(scope);
obj->scope_= scope;
obj->name_ = strdup(net->name());
scope_add_logic(scope, obj);
if (net_logic_) {
(net_logic_)(net->name(), obj);
}
}
bool dll_target::net_const(const NetConst*net)
@ -358,12 +337,11 @@ void dll_target::scope(const NetScope*net)
ivl_scope_t scope;
if (net->parent() == 0) {
assert(des_.root_->self == net);
assert(strcmp(des_.root_->name_, net->name().c_str()) == 0);
scope = des_.root_;
} else {
scope = new struct ivl_scope_s;
scope->self = net;
scope->name_ = strdup(net->name().c_str());
ivl_scope_t parent = find_scope(des_.root_, net->parent());
@ -372,9 +350,6 @@ void dll_target::scope(const NetScope*net)
scope->sibling_= parent->child_;
parent->child_ = scope;
}
if (scope_)
(scope_)(scope);
}
void dll_target::signal(const NetNet*net)
@ -401,13 +376,13 @@ void dll_target::signal(const NetNet*net)
obj->scope_->sigs_ = (ivl_signal_t*)
realloc(obj->scope_->sigs_,
obj->scope_->nsigs_*sizeof(ivl_signal_t));
obj->scope_->sigs_[obj->scope_->nsigs_-1] = obj;
}
obj->scope_->sigs_[obj->scope_->nsigs_-1] = obj;
#ifndef NDEBUG
{ const char*scope_name = obj->scope_->self->name().c_str();
size_t name_len = strlen(scope_name);
assert(0 == strncmp(scope_name, obj->name_, name_len));
{ size_t name_len = strlen(obj->scope_->name_);
assert(0 == strncmp(obj->scope_->name_, obj->name_, name_len));
}
#endif
@ -531,19 +506,6 @@ void dll_target::signal(const NetNet*net)
}
}
}
/* Invoke the target_net_signal function of the loaded target
module, if it exists. */
if (net_signal_) {
int rc = (net_signal_)(obj->name_, obj);
return;
} else {
cerr << dll_path_ << ": internal error: target DLL lacks "
<< "target_net_signal function." << endl;
return;
}
}
extern const struct target tgt_dll = { "dll", &dll_target_obj };
@ -551,6 +513,18 @@ extern const struct target tgt_dll = { "dll", &dll_target_obj };
/*
* $Log: t-dll.cc,v $
* Revision 1.15 2000/10/15 04:46:23 steve
* Scopes and processes are accessible randomly from
* the design, and signals and logic are accessible
* from scopes. Remove the target calls that are no
* longer needed.
*
* Add the ivl_nexus_ptr_t and the means to get at
* them from nexus objects.
*
* Give names to methods that manipulate the ivl_design_t
* type more consistent names.
*
* Revision 1.14 2000/10/13 03:39:27 steve
* Include constants in nexus targets.
*

28
t-dll.h
View File

@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT) && !defined(macintosh)
#ident "$Id: t-dll.h,v 1.12 2000/10/13 03:39:27 steve Exp $"
#ident "$Id: t-dll.h,v 1.13 2000/10/15 04:46:23 steve Exp $"
#endif
# include "target.h"
@ -66,12 +66,7 @@ struct dll_target : public target_t, public expr_scan_t {
net_const_f net_const_;
net_event_f net_event_;
net_logic_f net_logic_;
net_probe_f net_probe_;
net_signal_f net_signal_;
process_f process_;
scope_f scope_;
/* These methods and members are used for forming the
statements of a thread. */
@ -160,6 +155,10 @@ struct ivl_net_const_s {
*/
struct ivl_net_logic_s {
ivl_logic_t type_;
char* name_;
ivl_scope_t scope_;
unsigned npins_;
ivl_nexus_t*pins_;
};
@ -170,7 +169,7 @@ struct ivl_net_logic_s {
* devices. the __nexus_ptr structure is a helper that actually does
* the pointing.
*/
struct __nexus_ptr {
struct ivl_nexus_ptr_s {
unsigned pin_ :24;
unsigned type_ : 8;
union {
@ -185,7 +184,7 @@ struct __nexus_ptr {
struct ivl_nexus_s {
unsigned nptr_;
struct __nexus_ptr*ptrs_;
struct ivl_nexus_ptr_s*ptrs_;
char*name_;
};
@ -210,7 +209,6 @@ struct ivl_scope_s {
ivl_scope_t child_, sibling_;
char* name_;
const NetScope*self;
unsigned nsigs_;
ivl_signal_t*sigs_;
@ -300,6 +298,18 @@ struct ivl_statement_s {
/*
* $Log: t-dll.h,v $
* Revision 1.13 2000/10/15 04:46:23 steve
* Scopes and processes are accessible randomly from
* the design, and signals and logic are accessible
* from scopes. Remove the target calls that are no
* longer needed.
*
* Add the ivl_nexus_ptr_t and the means to get at
* them from nexus objects.
*
* Give names to methods that manipulate the ivl_design_t
* type more consistent names.
*
* Revision 1.12 2000/10/13 03:39:27 steve
* Include constants in nexus targets.
*

View File

@ -18,6 +18,9 @@ The target module loader is invoked with the ivl flag "-tdll". That
is, the DLL loader is a linked in target type. The name of the target
module to load is then specified with the DLL flag, i.e. "-fDLL=<path>".
COMPILING TARGET MODULES
<write me>
LOADABLE TARGET MODULE API
@ -25,37 +28,3 @@ The target module API is defined in the ivl_target.h header file. This
declares all the type and functions that a loadable module needs to
access the design.
PROCESSES
A process is an always or initial construct with its associated
statement. The target gets from the compiler an ivl_process_t object,
that holds the process type (always or initial) and the statement,
which is an ivl_statement_t.
All the interesting stuff happens in the ivl_statement_t object. This
is a generic object that represents any single Verilog statement. If
the statement is compound, then it also holds references to the
contained statements. The target module can access statements in any
way it chooses, once it is handed the process that contains the
statement.
EXPRESSIONS
In behavioral code (and some combinational code) expressions are
passed on to the target as ivl_expr_t objects. Each object is a node
in a tree that represents the expression from the source. All the
issues of width and sign are taken care of so that it is clear an easy
to know exactly what you have.
All expressions have a width, available with the ivl_expr_width()
function. Each node in an expression tree may have a different width,
the compiler figures out everything and eliminates the ambiguity.
All expressions are also "signed" or "unsigned" -- mostly
unsigned. The ivl_expr_signed() function returns true if the
expression node is signed. A node may be signed, for example, if it is
a reference to an integer or a signed wire. The compiler figures out
whether or not each node is signed, the target need not guess.

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT) && !defined(macintosh)
#ident "$Id: stub.c,v 1.16 2000/10/08 05:00:04 steve Exp $"
#ident "$Id: stub.c,v 1.17 2000/10/15 04:46:23 steve Exp $"
#endif
/*
@ -32,135 +32,6 @@
static FILE*out;
int target_start_design(ivl_design_t des)
{
const char*path = ivl_get_flag(des, "-o");
if (path == 0) {
return -1;
}
out = fopen(path, "w");
if (out == 0) {
perror(path);
return -2;
}
fprintf(out, "root module = %s;\n", ivl_get_root_name(des));
return 0;
}
void target_end_design(ivl_design_t des)
{
fclose(out);
}
int target_net_const(const char*name, ivl_net_const_t net)
{
unsigned idx;
unsigned wid = ivl_const_pins(net);
const char*bits = ivl_const_bits(net);
fprintf(out, "LPM_CONSTANT %s: %s%u'b", name,
ivl_const_signed(net)? "+- ":"",
wid);
for (idx = 0 ; idx < wid ; idx += 1)
fprintf(out, "%c", bits[wid-1-idx]);
fprintf(out, " (%s", ivl_nexus_name(ivl_const_pin(net, 0)));
for (idx = 1 ; idx < wid ; idx += 1)
fprintf(out, ", %s", ivl_nexus_name(ivl_const_pin(net, idx)));
fprintf(out, ")\n");
return 0;
}
int target_net_event(const char*name, ivl_net_event_t net)
{
fprintf(out, "STUB: %s: event\n", name);
return 0;
}
int target_net_logic(const char*name, ivl_net_logic_t net)
{
unsigned npins, idx;
switch (ivl_logic_type(net)) {
case IVL_LO_AND:
fprintf(out, "and %s (%s", name,
ivl_nexus_name(ivl_logic_pin(net, 0)));
break;
case IVL_LO_BUF:
fprintf(out, "buf %s (%s", name,
ivl_nexus_name(ivl_logic_pin(net, 0)));
break;
case IVL_LO_BUFZ:
fprintf(out, "bufz %s (%s", name,
ivl_nexus_name(ivl_logic_pin(net, 0)));
break;
case IVL_LO_OR:
fprintf(out, "or %s (%s", name,
ivl_nexus_name(ivl_logic_pin(net, 0)));
break;
case IVL_LO_XOR:
fprintf(out, "xor %s (%s", name,
ivl_nexus_name(ivl_logic_pin(net, 0)));
break;
default:
fprintf(out, "unsupported gate %s: \n", name);
return -1;
}
npins = ivl_logic_pins(net);
for (idx = 1 ; idx < npins ; idx += 1)
fprintf(out, ", %s", ivl_nexus_name(ivl_logic_pin(net,idx)));
fprintf(out, ");\n");
return 0;
}
int target_net_probe(const char*name, ivl_net_probe_t net)
{
fprintf(out, "STUB: %s: probe\n", name);
return 0;
}
int target_net_signal(const char*name, ivl_signal_t net)
{
const char*type = "?";
const char*port = "";
switch (ivl_signal_type(net)) {
case IVL_SIT_REG:
type = "reg";
break;
case IVL_SIT_WIRE:
type = "wire";
break;
}
switch (ivl_signal_port(net)) {
case IVL_SIP_INPUT:
port = "input ";
break;
case IVL_SIP_OUTPUT:
port = "output ";
break;
case IVL_SIP_INOUT:
port = "inout ";
break;
}
fprintf(out, "%s %s[%u] %s\n", type, port,
ivl_signal_pins(net), name);
return 0;
}
static void show_expression(ivl_expr_t net, unsigned ind)
{
const ivl_expr_type_t code = ivl_expr_type(net);
@ -281,7 +152,7 @@ static void show_statement(ivl_statement_t net, unsigned ind)
}
}
int target_process(ivl_process_t net)
static int show_process(ivl_process_t net)
{
switch (ivl_process_type(net)) {
case IVL_PR_INITIAL:
@ -297,8 +168,168 @@ int target_process(ivl_process_t net)
return 0;
}
static void show_signal(ivl_signal_t net)
{
const char*type = "?";
const char*port = "";
switch (ivl_signal_type(net)) {
case IVL_SIT_REG:
type = "reg";
break;
case IVL_SIT_WIRE:
type = "wire";
break;
}
switch (ivl_signal_port(net)) {
case IVL_SIP_INPUT:
port = "input ";
break;
case IVL_SIP_OUTPUT:
port = "output ";
break;
case IVL_SIP_INOUT:
port = "inout ";
break;
}
fprintf(out, " %s %s[%u] %s\n", type, port,
ivl_signal_pins(net), ivl_signal_basename(net));
}
static void show_logic(ivl_net_logic_t net)
{
unsigned npins, idx;
const char*name = ivl_logic_basename(net);
switch (ivl_logic_type(net)) {
case IVL_LO_AND:
fprintf(out, " and %s (%s", name,
ivl_nexus_name(ivl_logic_pin(net, 0)));
break;
case IVL_LO_BUF:
fprintf(out, " buf %s (%s", name,
ivl_nexus_name(ivl_logic_pin(net, 0)));
break;
case IVL_LO_BUFZ:
fprintf(out, " bufz %s (%s", name,
ivl_nexus_name(ivl_logic_pin(net, 0)));
break;
case IVL_LO_OR:
fprintf(out, " or %s (%s", name,
ivl_nexus_name(ivl_logic_pin(net, 0)));
break;
case IVL_LO_XOR:
fprintf(out, " xor %s (%s", name,
ivl_nexus_name(ivl_logic_pin(net, 0)));
break;
default:
fprintf(out, " unsupported gate %s (%s", name,
ivl_nexus_name(ivl_logic_pin(net, 0)));
return;
}
npins = ivl_logic_pins(net);
for (idx = 1 ; idx < npins ; idx += 1)
fprintf(out, ", %s", ivl_nexus_name(ivl_logic_pin(net,idx)));
fprintf(out, ");\n");
}
static int show_scope(ivl_scope_t net)
{
unsigned idx;
fprintf(out, "scope: %s (%u signals, %u logic)\n", ivl_scope_name(net),
ivl_scope_sigs(net), ivl_scope_logs(net));
for (idx = 0 ; idx < ivl_scope_sigs(net) ; idx += 1)
show_signal(ivl_scope_sig(net, idx));
for (idx = 0 ; idx < ivl_scope_logs(net) ; idx += 1)
show_logic(ivl_scope_log(net, idx));
fprintf(out, "end scope %s\n", ivl_scope_name(net));
return ivl_scope_children(net, show_scope);
}
int target_start_design(ivl_design_t des)
{
const char*path = ivl_design_flag(des, "-o");
if (path == 0) {
return -1;
}
out = fopen(path, "w");
if (out == 0) {
perror(path);
return -2;
}
fprintf(out, "root module = %s;\n",
ivl_scope_name(ivl_design_root(des)));
return 0;
}
void target_end_design(ivl_design_t des)
{
show_scope(ivl_design_root(des));
ivl_design_process(des, show_process);
fclose(out);
}
int target_net_const(const char*name, ivl_net_const_t net)
{
unsigned idx;
unsigned wid = ivl_const_pins(net);
const char*bits = ivl_const_bits(net);
fprintf(out, "LPM_CONSTANT %s: %s%u'b", name,
ivl_const_signed(net)? "+- ":"",
wid);
for (idx = 0 ; idx < wid ; idx += 1)
fprintf(out, "%c", bits[wid-1-idx]);
fprintf(out, " (%s", ivl_nexus_name(ivl_const_pin(net, 0)));
for (idx = 1 ; idx < wid ; idx += 1)
fprintf(out, ", %s", ivl_nexus_name(ivl_const_pin(net, idx)));
fprintf(out, ")\n");
return 0;
}
int target_net_event(const char*name, ivl_net_event_t net)
{
fprintf(out, "STUB: %s: event\n", name);
return 0;
}
int target_net_probe(const char*name, ivl_net_probe_t net)
{
fprintf(out, "STUB: %s: probe\n", name);
return 0;
}
/*
* $Log: stub.c,v $
* Revision 1.17 2000/10/15 04:46:23 steve
* Scopes and processes are accessible randomly from
* the design, and signals and logic are accessible
* from scopes. Remove the target calls that are no
* longer needed.
*
* Add the ivl_nexus_ptr_t and the means to get at
* them from nexus objects.
*
* Give names to methods that manipulate the ivl_design_t
* type more consistent names.
*
* Revision 1.16 2000/10/08 05:00:04 steve
* Missing stream in call to fprintf.
*
@ -312,46 +343,5 @@ int target_process(ivl_process_t net)
*
* Revision 1.13 2000/10/05 05:03:01 steve
* xor and constant devices.
*
* Revision 1.12 2000/09/26 00:30:07 steve
* Add EX_NUMBER and ST_TRIGGER to dll-api.
*
* Revision 1.11 2000/09/24 15:46:00 steve
* API access to signal type and port type.
*
* Revision 1.10 2000/09/24 02:21:53 steve
* Add support for signal expressions.
*
* Revision 1.9 2000/09/22 03:58:30 steve
* Access to the name of a system task call.
*
* Revision 1.8 2000/09/19 04:15:27 steve
* Introduce the means to get statement types.
*
* Revision 1.7 2000/09/18 01:24:32 steve
* Get the structure for ivl_statement_t worked out.
*
* Revision 1.6 2000/08/27 15:51:51 steve
* t-dll iterates signals, and passes them to the
* target module.
*
* Some of NetObj should return char*, not string.
*
* Revision 1.5 2000/08/26 00:54:03 steve
* Get at gate information for ivl_target interface.
*
* Revision 1.4 2000/08/20 04:13:57 steve
* Add ivl_target support for logic gates, and
* make the interface more accessible.
*
* Revision 1.3 2000/08/19 18:12:42 steve
* Add target calls for scope, events and logic.
*
* Revision 1.2 2000/08/14 04:39:57 steve
* add th t-dll functions for net_const, net_bufz and processes.
*
* Revision 1.1 2000/08/12 16:34:37 steve
* Start stub for loadable targets.
*
*/

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT) && !defined(macintosh)
#ident "$Id: verilog.c,v 1.10 2000/10/08 04:01:55 steve Exp $"
#ident "$Id: verilog.c,v 1.11 2000/10/15 04:46:23 steve Exp $"
#endif
/*
@ -32,106 +32,6 @@
static FILE*out;
int target_start_design(ivl_design_t des)
{
const char*path = ivl_get_flag(des, "-o");
if (path == 0) {
return -1;
}
out = fopen(path, "w");
if (out == 0) {
perror(path);
return -2;
}
fprintf(out, "module %s;\n", ivl_get_root_name(des));
return 0;
}
void target_end_design(ivl_design_t des)
{
fprintf(out, "endmodule\n");
fclose(out);
}
int target_net_const(const char*name, ivl_net_const_t net)
{
fprintf(out, "STUB: %s: constant\n", name);
return 0;
}
int target_net_event(const char*name, ivl_net_event_t net)
{
fprintf(out, "STUB: %s: event\n", name);
return 0;
}
int target_net_logic(const char*name, ivl_net_logic_t net)
{
unsigned npins, idx;
switch (ivl_logic_type(net)) {
case IVL_LO_AND:
fprintf(out, " and %s (%s", name,
ivl_nexus_name(ivl_logic_pin(net, 0)));
break;
case IVL_LO_BUF:
fprintf(out, " buf %s (%s", name,
ivl_nexus_name(ivl_logic_pin(net, 0)));
break;
case IVL_LO_OR:
fprintf(out, " or %s (%s", name,
ivl_nexus_name(ivl_logic_pin(net, 0)));
break;
case IVL_LO_XOR:
fprintf(out, " xor %s (%s", name,
ivl_nexus_name(ivl_logic_pin(net, 0)));
break;
default:
fprintf(out, "STUB: %s: unsupported gate\n", name);
return -1;
}
npins = ivl_logic_pins(net);
for (idx = 1 ; idx < npins ; idx += 1)
fprintf(out, ", %s", ivl_nexus_name(ivl_logic_pin(net,idx)));
fprintf(out, ");\n");
return 0;
}
int target_net_probe(const char*name, ivl_net_probe_t net)
{
fprintf(out, "STUB: %s: probe\n", name);
return 0;
}
int target_net_signal(const char*name, ivl_signal_t net)
{
unsigned cnt = ivl_signal_pins(net);
switch (ivl_signal_type(net)) {
case IVL_SIT_REG:
fprintf(out, " reg [%u:0] %s; // %s\n", cnt-1,
ivl_signal_basename(net), name);
break;
case IVL_SIT_WIRE:
fprintf(out, " wire [%u:0] %s; // %s\n", cnt-1,
ivl_signal_basename(net), name);
break;
default:
fprintf(out, " <huh!?> [%u:0] %s;\n", cnt-1, name);
break;
}
return 0;
}
static void show_expression(ivl_expr_t net)
{
if (net == 0)
@ -268,7 +168,7 @@ static void show_statement(ivl_statement_t net, unsigned ind)
}
}
int target_process(ivl_process_t net)
static int show_process(ivl_process_t net)
{
switch (ivl_process_type(net)) {
case IVL_PR_INITIAL:
@ -284,8 +184,122 @@ int target_process(ivl_process_t net)
return 0;
}
int target_start_design(ivl_design_t des)
{
const char*path = ivl_design_flag(des, "-o");
if (path == 0) {
return -1;
}
out = fopen(path, "w");
if (out == 0) {
perror(path);
return -2;
}
fprintf(out, "module %s;\n", ivl_scope_name(ivl_design_root(des)));
return 0;
}
void target_end_design(ivl_design_t des)
{
ivl_design_process(des, show_process);
fprintf(out, "endmodule\n");
fclose(out);
}
int target_net_const(const char*name, ivl_net_const_t net)
{
fprintf(out, "STUB: %s: constant\n", name);
return 0;
}
int target_net_event(const char*name, ivl_net_event_t net)
{
fprintf(out, "STUB: %s: event\n", name);
return 0;
}
int target_net_logic(const char*name, ivl_net_logic_t net)
{
unsigned npins, idx;
switch (ivl_logic_type(net)) {
case IVL_LO_AND:
fprintf(out, " and %s (%s", name,
ivl_nexus_name(ivl_logic_pin(net, 0)));
break;
case IVL_LO_BUF:
fprintf(out, " buf %s (%s", name,
ivl_nexus_name(ivl_logic_pin(net, 0)));
break;
case IVL_LO_OR:
fprintf(out, " or %s (%s", name,
ivl_nexus_name(ivl_logic_pin(net, 0)));
break;
case IVL_LO_XOR:
fprintf(out, " xor %s (%s", name,
ivl_nexus_name(ivl_logic_pin(net, 0)));
break;
default:
fprintf(out, "STUB: %s: unsupported gate\n", name);
return -1;
}
npins = ivl_logic_pins(net);
for (idx = 1 ; idx < npins ; idx += 1)
fprintf(out, ", %s", ivl_nexus_name(ivl_logic_pin(net,idx)));
fprintf(out, ");\n");
return 0;
}
int target_net_probe(const char*name, ivl_net_probe_t net)
{
fprintf(out, "STUB: %s: probe\n", name);
return 0;
}
int target_net_signal(const char*name, ivl_signal_t net)
{
unsigned cnt = ivl_signal_pins(net);
switch (ivl_signal_type(net)) {
case IVL_SIT_REG:
fprintf(out, " reg [%u:0] %s; // %s\n", cnt-1,
ivl_signal_basename(net), name);
break;
case IVL_SIT_WIRE:
fprintf(out, " wire [%u:0] %s; // %s\n", cnt-1,
ivl_signal_basename(net), name);
break;
default:
fprintf(out, " <huh!?> [%u:0] %s;\n", cnt-1, name);
break;
}
return 0;
}
/*
* $Log: verilog.c,v $
* Revision 1.11 2000/10/15 04:46:23 steve
* Scopes and processes are accessible randomly from
* the design, and signals and logic are accessible
* from scopes. Remove the target calls that are no
* longer needed.
*
* Add the ivl_nexus_ptr_t and the means to get at
* them from nexus objects.
*
* Give names to methods that manipulate the ivl_design_t
* type more consistent names.
*
* Revision 1.10 2000/10/08 04:01:55 steve
* Back pointers in the nexus objects into the devices
* that point to it.