2000-08-12 18:34:37 +02:00
|
|
|
/*
|
|
|
|
|
* Copyright (c) 2000 Stephen Williams (steve@icarus.com)
|
|
|
|
|
*
|
|
|
|
|
* 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
|
|
|
|
|
*/
|
|
|
|
|
#if !defined(WINNT) && !defined(macintosh)
|
2000-10-08 06:01:54 +02:00
|
|
|
#ident "$Id: t-dll.cc,v 1.13 2000/10/08 04:01:55 steve Exp $"
|
2000-08-12 18:34:37 +02:00
|
|
|
#endif
|
|
|
|
|
|
2000-08-20 06:13:56 +02:00
|
|
|
# include "compiler.h"
|
2000-09-18 03:24:32 +02:00
|
|
|
# include "t-dll.h"
|
2000-08-12 18:34:37 +02:00
|
|
|
# include <dlfcn.h>
|
2000-10-05 07:03:01 +02:00
|
|
|
# include <malloc.h>
|
2000-08-12 18:34:37 +02:00
|
|
|
|
2000-09-18 03:24:32 +02:00
|
|
|
static struct dll_target dll_target_obj;
|
2000-08-12 18:34:37 +02:00
|
|
|
|
2000-10-07 21:45:42 +02:00
|
|
|
/*
|
|
|
|
|
* This function locates an ivl_scope_t object that matches the
|
|
|
|
|
* NetScope object. The search works by looking for the parent scope,
|
|
|
|
|
* then scanning the parent scope for the NetScope object.
|
|
|
|
|
*/
|
|
|
|
|
static ivl_scope_t find_scope(ivl_scope_t root, const NetScope*cur)
|
|
|
|
|
{
|
|
|
|
|
ivl_scope_t parent, tmp;
|
|
|
|
|
|
|
|
|
|
if (const NetScope*par = cur->parent()) {
|
|
|
|
|
parent = find_scope(root, par);
|
|
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
assert(root->self == cur);
|
|
|
|
|
return root;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (tmp = parent->child_ ; tmp ; tmp = tmp->sibling_)
|
|
|
|
|
if (tmp->self == cur)
|
|
|
|
|
return tmp;
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2000-10-08 06:01:54 +02:00
|
|
|
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_[0].pin_ = pin;
|
|
|
|
|
tmp->ptrs_[0].type_ = __NEXUS_PTR_SIG;
|
|
|
|
|
tmp->ptrs_[0].l.sig = net;
|
|
|
|
|
return tmp;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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->nptr_ = top;
|
|
|
|
|
|
|
|
|
|
nex->ptrs_[top-1].type_= __NEXUS_PTR_SIG;
|
|
|
|
|
nex->ptrs_[top-1].pin_ = pin;
|
|
|
|
|
nex->ptrs_[top-1].l.sig= net;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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->nptr_ = top;
|
|
|
|
|
|
|
|
|
|
nex->ptrs_[top-1].type_= __NEXUS_PTR_LOG;
|
|
|
|
|
nex->ptrs_[top-1].pin_ = pin;
|
|
|
|
|
nex->ptrs_[top-1].l.log= net;
|
|
|
|
|
}
|
|
|
|
|
|
2000-10-07 21:45:42 +02:00
|
|
|
void scope_add_logic(ivl_scope_t scope, ivl_net_logic_t net)
|
|
|
|
|
{
|
|
|
|
|
if (scope->nlog_ == 0) {
|
|
|
|
|
scope->nlog_ = 1;
|
|
|
|
|
scope->log_ = (ivl_net_logic_t*)malloc(sizeof(ivl_net_logic_t));
|
|
|
|
|
scope->log_[0] = net;
|
|
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
scope->nlog_ += 1;
|
|
|
|
|
scope->log_ = (ivl_net_logic_t*)
|
|
|
|
|
realloc(scope->log_, scope->nlog_*sizeof(ivl_net_logic_t));
|
|
|
|
|
scope->log_[scope->nlog_-1] = net;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
2000-08-12 18:34:37 +02:00
|
|
|
bool dll_target::start_design(const Design*des)
|
|
|
|
|
{
|
2000-08-14 06:39:56 +02:00
|
|
|
dll_path_ = des->get_flag("DLL");
|
|
|
|
|
dll_ = dlopen(dll_path_.c_str(), RTLD_NOW);
|
2000-08-12 18:34:37 +02:00
|
|
|
if (dll_ == 0) {
|
2000-08-14 06:39:56 +02:00
|
|
|
cerr << dll_path_ << ": " << dlerror() << endl;
|
2000-08-12 18:34:37 +02:00
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2000-09-18 03:24:32 +02:00
|
|
|
stmt_cur_ = 0;
|
|
|
|
|
|
2000-09-30 04:18:15 +02:00
|
|
|
// Initialize the design object.
|
|
|
|
|
des_.self = des;
|
2000-10-08 06:01:54 +02:00
|
|
|
des_.root_ = new struct ivl_scope_s;
|
|
|
|
|
des_.root_->name_ = strdup(des->find_root_scope()->name().c_str());
|
2000-09-30 04:18:15 +02:00
|
|
|
des_.root_->self = des->find_root_scope();
|
2000-08-12 18:34:37 +02:00
|
|
|
|
2000-10-07 01:46:50 +02:00
|
|
|
start_design_ = (start_design_f)dlsym(dll_, LU "target_start_design" TU);
|
|
|
|
|
end_design_ = (end_design_f) dlsym(dll_, LU "target_end_design" TU);
|
2000-08-19 20:12:42 +02:00
|
|
|
|
2000-08-20 06:13:56 +02:00
|
|
|
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);
|
2000-08-27 17:51:50 +02:00
|
|
|
net_signal_ = (net_signal_f)dlsym(dll_, LU "target_net_signal" TU);
|
2000-08-20 06:13:56 +02:00
|
|
|
process_ = (process_f) dlsym(dll_, LU "target_process" TU);
|
|
|
|
|
scope_ = (scope_f) dlsym(dll_, LU "target_scope" TU);
|
2000-08-14 06:39:56 +02:00
|
|
|
|
2000-09-30 04:18:15 +02:00
|
|
|
(start_design_)(&des_);
|
2000-08-12 18:34:37 +02:00
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2000-10-08 06:01:54 +02:00
|
|
|
/*
|
|
|
|
|
* Here ivl is telling us that the design is scanned completely, and
|
|
|
|
|
* here is where we call the API to process the constructed design.
|
|
|
|
|
*/
|
2000-08-12 18:34:37 +02:00
|
|
|
void dll_target::end_design(const Design*)
|
|
|
|
|
{
|
2000-10-08 06:01:54 +02:00
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2000-09-30 04:18:15 +02:00
|
|
|
(end_design_)(&des_);
|
2000-08-12 18:34:37 +02:00
|
|
|
dlclose(dll_);
|
|
|
|
|
}
|
|
|
|
|
|
2000-10-08 06:01:54 +02:00
|
|
|
/*
|
|
|
|
|
* Add a bufz object to the scope that contains it.
|
|
|
|
|
*
|
|
|
|
|
* Note that in the ivl_target API a BUFZ device is a special kind of
|
|
|
|
|
* ivl_net_logic_t device, so create an ivl_net_logic_t cookie to
|
|
|
|
|
* handle it.
|
|
|
|
|
*/
|
2000-08-14 06:39:56 +02:00
|
|
|
bool dll_target::bufz(const NetBUFZ*net)
|
|
|
|
|
{
|
2000-10-07 21:45:42 +02:00
|
|
|
struct ivl_net_logic_s *obj = new struct ivl_net_logic_s;
|
|
|
|
|
|
|
|
|
|
assert(net->pin_count() == 2);
|
|
|
|
|
|
|
|
|
|
obj->type_ = IVL_LO_BUFZ;
|
|
|
|
|
|
|
|
|
|
obj->npins_ = 2;
|
|
|
|
|
obj->pins_ = new ivl_nexus_t[2];
|
|
|
|
|
|
2000-10-08 06:01:54 +02:00
|
|
|
|
|
|
|
|
/* Get the ivl_nexus_t objects connected to the two pins.
|
|
|
|
|
|
|
|
|
|
(We know a priori that the ivl_nexus_t objects have been
|
|
|
|
|
allocated, because the signals have been scanned before
|
|
|
|
|
me. This saves me the trouble of allocating them.) */
|
|
|
|
|
|
2000-10-07 21:45:42 +02:00
|
|
|
assert(net->pin(0).nexus()->t_cookie());
|
|
|
|
|
obj->pins_[0] = (ivl_nexus_t) net->pin(0).nexus()->t_cookie();
|
2000-10-08 06:01:54 +02:00
|
|
|
nexus_log_add(obj->pins_[0], obj, 0);
|
2000-10-07 21:45:42 +02:00
|
|
|
|
|
|
|
|
assert(net->pin(1).nexus()->t_cookie());
|
|
|
|
|
obj->pins_[1] = (ivl_nexus_t) net->pin(1).nexus()->t_cookie();
|
2000-10-08 06:01:54 +02:00
|
|
|
nexus_log_add(obj->pins_[1], obj, 1);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Attach the logic device to the scope that contains it. */
|
2000-10-07 21:45:42 +02:00
|
|
|
|
|
|
|
|
assert(net->scope());
|
|
|
|
|
ivl_scope_t scope = find_scope(des_.root_, net->scope());
|
|
|
|
|
assert(scope);
|
|
|
|
|
|
|
|
|
|
scope_add_logic(scope, obj);
|
|
|
|
|
|
|
|
|
|
if (net_logic_) {
|
|
|
|
|
(net_logic_)(net->name(), obj);
|
2000-08-14 06:39:56 +02:00
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
cerr << dll_path_ << ": internal error: target DLL lacks "
|
2000-10-07 21:45:42 +02:00
|
|
|
<< "target_net_logic function." << endl;
|
2000-08-14 06:39:56 +02:00
|
|
|
}
|
|
|
|
|
|
2000-10-07 21:45:42 +02:00
|
|
|
return true;
|
2000-08-14 06:39:56 +02:00
|
|
|
}
|
|
|
|
|
|
2000-08-19 20:12:42 +02:00
|
|
|
void dll_target::event(const NetEvent*net)
|
|
|
|
|
{
|
|
|
|
|
if (net_event_) {
|
|
|
|
|
(net_event_)(net->full_name().c_str(), 0);
|
|
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
cerr << dll_path_ << ": internal error: target DLL lacks "
|
|
|
|
|
<< "target_net_event function." << endl;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void dll_target::logic(const NetLogic*net)
|
|
|
|
|
{
|
2000-10-07 01:46:50 +02:00
|
|
|
struct ivl_net_logic_s *obj = new struct ivl_net_logic_s;
|
|
|
|
|
|
|
|
|
|
switch (net->type()) {
|
|
|
|
|
case NetLogic::AND:
|
|
|
|
|
obj->type_ = IVL_LO_AND;
|
|
|
|
|
break;
|
|
|
|
|
case NetLogic::BUF:
|
|
|
|
|
obj->type_ = IVL_LO_BUF;
|
|
|
|
|
break;
|
|
|
|
|
case NetLogic::OR:
|
|
|
|
|
obj->type_ = IVL_LO_OR;
|
|
|
|
|
break;
|
|
|
|
|
case NetLogic::XOR:
|
|
|
|
|
obj->type_ = IVL_LO_XOR;
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
assert(0);
|
|
|
|
|
obj->type_ = IVL_LO_NONE;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
2000-10-08 06:01:54 +02:00
|
|
|
/* Connect all the ivl_nexus_t objects to the pins of the
|
|
|
|
|
device. */
|
|
|
|
|
|
2000-10-07 01:46:50 +02:00
|
|
|
obj->npins_ = net->pin_count();
|
|
|
|
|
obj->pins_ = new ivl_nexus_t[obj->npins_];
|
|
|
|
|
for (unsigned idx = 0 ; idx < obj->npins_ ; idx += 1) {
|
|
|
|
|
const Nexus*nex = net->pin(idx).nexus();
|
|
|
|
|
assert(nex->t_cookie());
|
|
|
|
|
obj->pins_[idx] = (ivl_nexus_t) nex->t_cookie();
|
2000-10-08 06:01:54 +02:00
|
|
|
nexus_log_add(obj->pins_[idx], obj, idx);
|
2000-10-07 01:46:50 +02:00
|
|
|
}
|
2000-08-20 06:13:56 +02:00
|
|
|
|
2000-10-07 21:45:42 +02:00
|
|
|
assert(net->scope());
|
|
|
|
|
ivl_scope_t scope = find_scope(des_.root_, net->scope());
|
|
|
|
|
assert(scope);
|
|
|
|
|
|
|
|
|
|
scope_add_logic(scope, obj);
|
|
|
|
|
|
2000-08-19 20:12:42 +02:00
|
|
|
if (net_logic_) {
|
2000-10-07 01:46:50 +02:00
|
|
|
(net_logic_)(net->name(), obj);
|
2000-08-19 20:12:42 +02:00
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
cerr << dll_path_ << ": internal error: target DLL lacks "
|
|
|
|
|
<< "target_net_logic function." << endl;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2000-08-14 06:39:56 +02:00
|
|
|
bool dll_target::net_const(const NetConst*net)
|
|
|
|
|
{
|
2000-10-05 07:03:01 +02:00
|
|
|
unsigned idx;
|
2000-10-07 01:46:50 +02:00
|
|
|
char*bits;
|
|
|
|
|
|
|
|
|
|
struct ivl_net_const_s *obj = new struct ivl_net_const_s;
|
2000-10-05 07:03:01 +02:00
|
|
|
|
|
|
|
|
obj->width_ = net->pin_count();
|
2000-10-07 01:46:50 +02:00
|
|
|
if (obj->width_ <= sizeof(char*)) {
|
|
|
|
|
bits = obj->b.bit_;
|
|
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
obj->b.bits_ = (char*)malloc(obj->width_);
|
|
|
|
|
bits = obj->b.bits_;
|
|
|
|
|
}
|
|
|
|
|
|
2000-10-05 07:03:01 +02:00
|
|
|
for (idx = 0 ; idx < obj->width_ ; idx += 1)
|
|
|
|
|
switch (net->value(idx)) {
|
|
|
|
|
case verinum::V0:
|
2000-10-07 01:46:50 +02:00
|
|
|
bits[idx] = '0';
|
2000-10-05 07:03:01 +02:00
|
|
|
break;
|
|
|
|
|
case verinum::V1:
|
2000-10-07 01:46:50 +02:00
|
|
|
bits[idx] = '1';
|
2000-10-05 07:03:01 +02:00
|
|
|
break;
|
|
|
|
|
case verinum::Vx:
|
2000-10-07 01:46:50 +02:00
|
|
|
bits[idx] = 'x';
|
2000-10-05 07:03:01 +02:00
|
|
|
break;
|
|
|
|
|
case verinum::Vz:
|
2000-10-07 01:46:50 +02:00
|
|
|
bits[idx] = 'z';
|
2000-10-05 07:03:01 +02:00
|
|
|
break;
|
|
|
|
|
}
|
2000-08-14 06:39:56 +02:00
|
|
|
|
2000-10-07 01:46:50 +02:00
|
|
|
/* Connect to all the nexus objects. Note that the one-bit
|
|
|
|
|
case can be handled more efficiently without allocating
|
|
|
|
|
array space. */
|
|
|
|
|
if (obj->width_ == 1) {
|
|
|
|
|
const Nexus*nex = net->pin(0).nexus();
|
|
|
|
|
assert(nex->t_cookie());
|
|
|
|
|
obj->n.pin_ = (ivl_nexus_t) nex->t_cookie();
|
|
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
obj->n.pins_ = new ivl_nexus_t[obj->width_];
|
|
|
|
|
for (unsigned idx = 0 ; idx < obj->width_ ; idx += 1) {
|
|
|
|
|
const Nexus*nex = net->pin(idx).nexus();
|
|
|
|
|
assert(nex->t_cookie());
|
|
|
|
|
obj->n.pins_[idx] = (ivl_nexus_t) nex->t_cookie();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* All done, call the target_net_const function if it exists. */
|
2000-08-14 06:39:56 +02:00
|
|
|
if (net_const_) {
|
2000-10-05 07:03:01 +02:00
|
|
|
int rc = (net_const_)(net->name(), obj);
|
2000-08-14 06:39:56 +02:00
|
|
|
return rc == 0;
|
|
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
cerr << dll_path_ << ": internal error: target DLL lacks "
|
|
|
|
|
<< "target_net_const function." << endl;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2000-08-19 20:12:42 +02:00
|
|
|
void dll_target::net_probe(const NetEvProbe*net)
|
|
|
|
|
{
|
|
|
|
|
if (net_probe_) {
|
2000-08-27 17:51:50 +02:00
|
|
|
int rc = (net_probe_)(net->name(), 0);
|
2000-08-19 20:12:42 +02:00
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
cerr << dll_path_ << ": internal error: target DLL lacks "
|
|
|
|
|
<< "target_net_probe function." << endl;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void dll_target::scope(const NetScope*net)
|
|
|
|
|
{
|
2000-09-30 04:18:15 +02:00
|
|
|
ivl_scope_t scope;
|
|
|
|
|
|
|
|
|
|
if (net->parent() == 0) {
|
|
|
|
|
assert(des_.root_->self == net);
|
|
|
|
|
scope = des_.root_;
|
|
|
|
|
|
|
|
|
|
} else {
|
2000-10-07 21:45:42 +02:00
|
|
|
scope = new struct ivl_scope_s;
|
2000-09-30 04:18:15 +02:00
|
|
|
scope->self = net;
|
2000-10-08 06:01:54 +02:00
|
|
|
scope->name_ = strdup(net->name().c_str());
|
2000-09-30 04:18:15 +02:00
|
|
|
|
|
|
|
|
ivl_scope_t parent = find_scope(des_.root_, net->parent());
|
|
|
|
|
assert(parent != 0);
|
|
|
|
|
|
|
|
|
|
scope->sibling_= parent->child_;
|
|
|
|
|
parent->child_ = scope;
|
|
|
|
|
}
|
|
|
|
|
|
2000-08-27 17:51:50 +02:00
|
|
|
if (scope_)
|
2000-09-30 04:18:15 +02:00
|
|
|
(scope_)(scope);
|
2000-08-27 17:51:50 +02:00
|
|
|
}
|
2000-08-19 20:12:42 +02:00
|
|
|
|
2000-08-27 17:51:50 +02:00
|
|
|
void dll_target::signal(const NetNet*net)
|
|
|
|
|
{
|
2000-10-08 06:01:54 +02:00
|
|
|
ivl_signal_t obj = new struct ivl_signal_s;
|
|
|
|
|
|
|
|
|
|
obj->name_ = strdup(net->name());
|
2000-10-07 01:46:50 +02:00
|
|
|
|
|
|
|
|
/* Attach the signal to the ivl_scope_t object that contains
|
|
|
|
|
it. This involves growing the sigs_ array in the scope
|
|
|
|
|
object, or creating the sigs_ array if this is the first
|
|
|
|
|
signal. */
|
|
|
|
|
obj->scope_ = find_scope(des_.root_, net->scope());
|
|
|
|
|
assert(obj->scope_);
|
|
|
|
|
|
|
|
|
|
if (obj->scope_->nsigs_ == 0) {
|
|
|
|
|
assert(obj->scope_->sigs_ == 0);
|
|
|
|
|
obj->scope_->nsigs_ = 1;
|
|
|
|
|
obj->scope_->sigs_ = (ivl_signal_t*)malloc(sizeof(ivl_signal_t));
|
|
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
assert(obj->scope_->sigs_);
|
|
|
|
|
obj->scope_->nsigs_ += 1;
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
2000-10-08 06:01:54 +02:00
|
|
|
#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));
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
2000-10-07 01:46:50 +02:00
|
|
|
/* Save the privitive properties of the signal in the
|
|
|
|
|
ivl_signal_t object. */
|
|
|
|
|
|
|
|
|
|
obj->width_ = net->pin_count();
|
|
|
|
|
obj->signed_= 0;
|
|
|
|
|
|
|
|
|
|
switch (net->port_type()) {
|
|
|
|
|
|
|
|
|
|
case NetNet::PINPUT:
|
|
|
|
|
obj->port_ = IVL_SIP_INPUT;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case NetNet::POUTPUT:
|
|
|
|
|
obj->port_ = IVL_SIP_OUTPUT;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case NetNet::PINOUT:
|
|
|
|
|
obj->port_ = IVL_SIP_INOUT;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
obj->port_ = IVL_SIP_NONE;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
switch (net->type()) {
|
|
|
|
|
|
|
|
|
|
case NetNet::REG:
|
|
|
|
|
case NetNet::INTEGER:
|
|
|
|
|
obj->type_ = IVL_SIT_REG;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case NetNet::SUPPLY0:
|
|
|
|
|
obj->type_ = IVL_SIT_SUPPLY0;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case NetNet::SUPPLY1:
|
|
|
|
|
obj->type_ = IVL_SIT_SUPPLY1;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case NetNet::TRI:
|
|
|
|
|
obj->type_ = IVL_SIT_TRI;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case NetNet::TRI0:
|
|
|
|
|
obj->type_ = IVL_SIT_TRI0;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case NetNet::TRI1:
|
|
|
|
|
obj->type_ = IVL_SIT_TRI1;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case NetNet::TRIAND:
|
|
|
|
|
obj->type_ = IVL_SIT_TRIAND;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case NetNet::TRIOR:
|
|
|
|
|
obj->type_ = IVL_SIT_TRIOR;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case NetNet::WAND:
|
|
|
|
|
obj->type_ = IVL_SIT_WAND;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case NetNet::WIRE:
|
|
|
|
|
case NetNet::IMPLICIT:
|
|
|
|
|
obj->type_ = IVL_SIT_WIRE;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case NetNet::WOR:
|
|
|
|
|
obj->type_ = IVL_SIT_WOR;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
obj->type_ = IVL_SIT_NONE;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Get the nexus objects for all the pins of the signal. If
|
|
|
|
|
the signal has only one pin, then write the single
|
|
|
|
|
ivl_nexus_t object into n.pin_. Otherwise, make an array of
|
|
|
|
|
ivl_nexus_t cookies.
|
|
|
|
|
|
|
|
|
|
When I create an ivl_nexus_t object, store it in the
|
|
|
|
|
t_cookie of the Nexus object so that I find it again when I
|
|
|
|
|
next encounter the nexus. */
|
|
|
|
|
|
|
|
|
|
if (obj->width_ == 1) {
|
|
|
|
|
const Nexus*nex = net->pin(0).nexus();
|
|
|
|
|
if (nex->t_cookie()) {
|
|
|
|
|
obj->n.pin_ = (ivl_nexus_t)nex->t_cookie();
|
2000-10-08 06:01:54 +02:00
|
|
|
nexus_sig_add(obj->n.pin_, obj, 0);
|
2000-10-07 01:46:50 +02:00
|
|
|
|
|
|
|
|
} else {
|
2000-10-08 06:01:54 +02:00
|
|
|
ivl_nexus_t tmp = nexus_sig_make(obj, 0);
|
|
|
|
|
tmp->name_ = strdup(nex->name());
|
2000-10-07 01:46:50 +02:00
|
|
|
nex->t_cookie(tmp);
|
|
|
|
|
obj->n.pin_ = tmp;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
unsigned idx;
|
|
|
|
|
|
|
|
|
|
obj->n.pins_ = (ivl_nexus_t*)
|
|
|
|
|
calloc(obj->width_, sizeof(ivl_nexus_t));
|
|
|
|
|
|
|
|
|
|
for (idx = 0 ; idx < obj->width_ ; idx += 1) {
|
|
|
|
|
const Nexus*nex = net->pin(idx).nexus();
|
|
|
|
|
if (nex->t_cookie()) {
|
|
|
|
|
obj->n.pins_[idx] = (ivl_nexus_t)nex->t_cookie();
|
2000-10-08 06:01:54 +02:00
|
|
|
nexus_sig_add(obj->n.pins_[idx], obj, idx);
|
2000-10-07 01:46:50 +02:00
|
|
|
|
|
|
|
|
} else {
|
2000-10-08 06:01:54 +02:00
|
|
|
ivl_nexus_t tmp = nexus_sig_make(obj, idx);
|
|
|
|
|
tmp->name_ = strdup(nex->name());
|
2000-10-07 01:46:50 +02:00
|
|
|
nex->t_cookie(tmp);
|
|
|
|
|
obj->n.pins_[idx] = tmp;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Invoke the target_net_signal function of the loaded target
|
|
|
|
|
module, if it exists. */
|
|
|
|
|
|
2000-08-27 17:51:50 +02:00
|
|
|
if (net_signal_) {
|
2000-10-08 06:01:54 +02:00
|
|
|
int rc = (net_signal_)(obj->name_, obj);
|
2000-08-27 17:51:50 +02:00
|
|
|
return;
|
2000-08-19 20:12:42 +02:00
|
|
|
|
2000-08-27 17:51:50 +02:00
|
|
|
} else {
|
|
|
|
|
cerr << dll_path_ << ": internal error: target DLL lacks "
|
|
|
|
|
<< "target_net_signal function." << endl;
|
|
|
|
|
return;
|
|
|
|
|
}
|
2000-08-19 20:12:42 +02:00
|
|
|
}
|
|
|
|
|
|
2000-08-12 18:34:37 +02:00
|
|
|
extern const struct target tgt_dll = { "dll", &dll_target_obj };
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* $Log: t-dll.cc,v $
|
2000-10-08 06:01:54 +02:00
|
|
|
* Revision 1.13 2000/10/08 04:01:55 steve
|
|
|
|
|
* Back pointers in the nexus objects into the devices
|
|
|
|
|
* that point to it.
|
|
|
|
|
*
|
|
|
|
|
* Collect threads into a list in the design.
|
|
|
|
|
*
|
2000-10-07 21:45:42 +02:00
|
|
|
* Revision 1.12 2000/10/07 19:45:43 steve
|
|
|
|
|
* Put logic devices into scopes.
|
|
|
|
|
*
|
2000-10-07 01:46:50 +02:00
|
|
|
* Revision 1.11 2000/10/06 23:46:51 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.10 2000/10/05 05:03:01 steve
|
|
|
|
|
* xor and constant devices.
|
|
|
|
|
*
|
2000-09-30 04:18:15 +02:00
|
|
|
* Revision 1.9 2000/09/30 02:18:15 steve
|
|
|
|
|
* ivl_expr_t support for binary operators,
|
|
|
|
|
* Create a proper ivl_scope_t object.
|
|
|
|
|
*
|
2000-09-24 17:46:00 +02:00
|
|
|
* Revision 1.8 2000/09/24 15:46:00 steve
|
|
|
|
|
* API access to signal type and port type.
|
|
|
|
|
*
|
2000-09-18 03:24:32 +02:00
|
|
|
* Revision 1.7 2000/09/18 01:24:32 steve
|
|
|
|
|
* Get the structure for ivl_statement_t worked out.
|
|
|
|
|
*
|
2000-08-27 17:51:50 +02:00
|
|
|
* 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.
|
|
|
|
|
*
|
2000-08-26 02:54:03 +02:00
|
|
|
* Revision 1.5 2000/08/26 00:54:03 steve
|
|
|
|
|
* Get at gate information for ivl_target interface.
|
|
|
|
|
*
|
2000-08-20 06:13:56 +02:00
|
|
|
* Revision 1.4 2000/08/20 04:13:57 steve
|
|
|
|
|
* Add ivl_target support for logic gates, and
|
|
|
|
|
* make the interface more accessible.
|
|
|
|
|
*
|
2000-08-19 20:12:42 +02:00
|
|
|
* Revision 1.3 2000/08/19 18:12:42 steve
|
|
|
|
|
* Add target calls for scope, events and logic.
|
|
|
|
|
*
|
2000-08-14 06:39:56 +02:00
|
|
|
* Revision 1.2 2000/08/14 04:39:57 steve
|
|
|
|
|
* add th t-dll functions for net_const, net_bufz and processes.
|
|
|
|
|
*
|
2000-08-12 18:34:37 +02:00
|
|
|
* Revision 1.1 2000/08/12 16:34:37 steve
|
|
|
|
|
* Start stub for loadable targets.
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
|