Pass some module port information and fix a few bugs.

This patch adds some preliminary module port information to the ivl
interface. This may change as I investigate exactly what is needed.
It also fixes a few minor bugs (a missed local variable and spacing)
This commit is contained in:
Cary R 2011-03-07 11:18:23 -08:00 committed by Stephen Williams
parent 7b82bd26f5
commit 1e3af45335
13 changed files with 96 additions and 16 deletions

View File

@ -638,6 +638,7 @@ NetNet* PEIdent::elaborate_bi_net(Design*des, NetScope*scope) const
*/
NetNet* PEIdent::elaborate_port(Design*des, NetScope*scope) const
{
assert(scope->type() == NetScope::MODULE);
NetNet*sig = des->find_signal(scope, path_);
if (sig == 0) {
cerr << get_fileline() << ": error: no wire/reg " << path_
@ -690,8 +691,10 @@ NetNet* PEIdent::elaborate_port(Design*des, NetScope*scope) const
/* If this is a part select of the entire signal (or no part
select at all) then we're done. */
if ((lidx == 0) && (midx == (long)sig->vector_width()-1))
if ((lidx == 0) && (midx == (long)sig->vector_width()-1)) {
scope->add_module_port(sig);
return sig;
}
unsigned swid = abs(midx - lidx) + 1;
ivl_assert(*this, swid > 0 && swid < sig->vector_width());
@ -701,6 +704,7 @@ NetNet* PEIdent::elaborate_port(Design*des, NetScope*scope) const
tmp->port_type(sig->port_type());
tmp->data_type(sig->data_type());
tmp->set_line(*this);
tmp->local_flag(true);
NetNode*ps = 0;
switch (sig->port_type()) {
@ -732,5 +736,6 @@ NetNet* PEIdent::elaborate_port(Design*des, NetScope*scope) const
ps->set_line(*this);
des->add_node(ps);
scope->add_module_port(sig);
return sig;
}

View File

@ -409,6 +409,7 @@ void NetScope::emit_scope(struct target_t*tgt) const
tgt->signal_paths(cur->second);
}
if (type_ == MODULE) tgt->convert_module_ports(this);
}
bool NetScope::emit_defs(struct target_t*tgt) const

View File

@ -189,6 +189,7 @@ ivl_scope_logs
ivl_scope_log
ivl_scope_lpms
ivl_scope_lpm
ivl_scope_mod_port
ivl_scope_name
ivl_scope_param
ivl_scope_params

View File

@ -1712,6 +1712,7 @@ extern ivl_parameter_t ivl_scope_param(ivl_scope_t net, unsigned idx);
extern ivl_scope_t ivl_scope_parent(ivl_scope_t net);
extern unsigned ivl_scope_ports(ivl_scope_t net);
extern ivl_signal_t ivl_scope_port(ivl_scope_t net, unsigned idx);
extern ivl_nexus_t ivl_scope_mod_port(ivl_scope_t net, unsigned idx);
extern unsigned ivl_scope_sigs(ivl_scope_t net);
extern ivl_signal_t ivl_scope_sig(ivl_scope_t net, unsigned idx);
extern unsigned ivl_scope_switches(ivl_scope_t net);

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2000-2010 Stephen Williams (steve@icarus.com)
* Copyright (c) 2000-2011 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
@ -359,6 +359,25 @@ perm_string NetScope::module_name() const
return module_name_;
}
void NetScope::add_module_port(NetNet*port)
{
assert(type_ == MODULE);
ports_.push_back(port);
}
unsigned NetScope::module_ports() const
{
assert(type_ == MODULE);
return ports_.size();
}
NetNet* NetScope::module_port(unsigned idx) const
{
assert(type_ == MODULE);
assert(idx < ports_.size());
return ports_[idx];
}
void NetScope::time_unit(int val)
{
time_unit_ = val;

View File

@ -804,6 +804,11 @@ class NetScope : public Attrib {
/* If the scope represents a module instance, the module_name
is the name of the module itself. */
perm_string module_name() const;
/* If the scope is a module then it may have ports that we need
* to keep track of. */
void add_module_port(NetNet*port);
unsigned module_ports() const;
NetNet*module_port(unsigned idx) const;
/* Scopes have their own time units and time precision. The
unit and precision are given as power of 10, i.e., -3 is
@ -944,6 +949,7 @@ class NetScope : public Attrib {
typedef std::map<perm_string,NetNet*>::const_iterator signals_map_iter_t;
std::map <perm_string,NetNet*> signals_map_;
perm_string module_name_;
vector<NetNet*>ports_;
union {
NetTaskDef*task_;
NetFuncDef*func_;

View File

@ -1928,7 +1928,8 @@ extern "C" ivl_scope_t ivl_scope_parent(ivl_scope_t net)
extern "C" unsigned ivl_scope_ports(ivl_scope_t net)
{
assert(net);
if (net->type_ == IVL_SCT_FUNCTION ||
if (net->type_ == IVL_SCT_MODULE ||
net->type_ == IVL_SCT_FUNCTION ||
net->type_ == IVL_SCT_TASK) return net->ports;
return 0;
}
@ -1939,7 +1940,15 @@ extern "C" ivl_signal_t ivl_scope_port(ivl_scope_t net, unsigned idx)
assert(net->type_ == IVL_SCT_FUNCTION ||
net->type_ == IVL_SCT_TASK);
assert(idx < net->ports);
return net->port[idx];
return net->u_.port[idx];
}
extern "C" ivl_nexus_t ivl_scope_mod_port(ivl_scope_t net, unsigned idx)
{
assert(net);
assert(net->type_ == IVL_SCT_MODULE);
assert(idx < net->ports);
return net->u_.nex[idx];
}
extern "C" unsigned ivl_scope_sigs(ivl_scope_t net)

View File

@ -88,9 +88,9 @@ void dll_target::task_def(const NetScope*net)
scop->ports = def->port_count();
if (scop->ports > 0) {
scop->port = new ivl_signal_t[scop->ports];
scop->u_.port = new ivl_signal_t[scop->ports];
for (unsigned idx = 0 ; idx < scop->ports ; idx += 1)
scop->port[idx] = find_signal(des_, def->port(idx));
scop->u_.port[idx] = find_signal(des_, def->port(idx));
}
}
@ -110,9 +110,9 @@ bool dll_target::func_def(const NetScope*net)
scop->ports = def->port_count() + 1;
if (scop->ports > 0) {
scop->port = new ivl_signal_t[scop->ports];
scop->u_.port = new ivl_signal_t[scop->ports];
for (unsigned idx = 1 ; idx < scop->ports ; idx += 1)
scop->port[idx] = find_signal(des_, def->port(idx-1));
scop->u_.port[idx] = find_signal(des_, def->port(idx-1));
}
/* FIXME: the ivl_target API expects port-0 to be the output
@ -121,7 +121,7 @@ bool dll_target::func_def(const NetScope*net)
this, but that will break code generators that use this
result. */
if (const NetNet*ret_sig = def->return_sig()) {
scop->port[0] = find_signal(des_, ret_sig);
scop->u_.port[0] = find_signal(des_, ret_sig);
return true;
}

View File

@ -563,6 +563,13 @@ void dll_target::add_root(ivl_design_s &des__, const NetScope *s)
root_->attr = fill_in_attributes(s);
root_->is_auto = 0;
root_->is_cell = s->is_cell();
root_->ports = s->module_ports();
if (root_->ports > 0) {
root_->u_.net = new NetNet*[root_->ports];
for (unsigned idx = 0; idx < root_->ports; idx += 1) {
root_->u_.net[idx] = s->module_port(idx);
}
}
des__.nroots_++;
if (des__.roots_)
@ -2273,6 +2280,7 @@ void dll_target::scope(const NetScope*net)
FILE_NAME(scop, net);
scop->parent = find_scope(des_, net->parent());
assert(scop->parent);
scop->parent->children[net->fullname()] = scop;
scop->nsigs_ = 0;
scop->sigs_ = 0;
scop->nlog_ = 0;
@ -2294,6 +2302,13 @@ void dll_target::scope(const NetScope*net)
case NetScope::MODULE:
scop->type_ = IVL_SCT_MODULE;
scop->tname_ = net->module_name();
scop->ports = net->module_ports();
if (scop->ports > 0) {
scop->u_.net = new NetNet*[scop->ports];
for (unsigned idx = 0; idx < scop->ports; idx += 1) {
scop->u_.net[idx] = net->module_port(idx);
}
}
break;
case NetScope::TASK: {
const NetTaskDef*def = net->task_def();
@ -2324,10 +2339,20 @@ void dll_target::scope(const NetScope*net)
scop->tname_ = scop->name_;
break;
}
}
}
assert(scop->parent != 0);
scop->parent->children[net->fullname()] = scop;
void dll_target::convert_module_ports(const NetScope*net)
{
ivl_scope_t scop = find_scope(des_, net);
if (scop->ports > 0) {
NetNet**nets = scop->u_.net;
scop->u_.nex = new ivl_nexus_t[scop->ports];
for (unsigned idx = 0; idx < scop->ports; idx += 1) {
ivl_signal_t sig = find_signal(des_, nets[idx]);
scop->u_.nex[idx] = nexus_sig_make(sig, 0);
}
delete nets;
}
}

View File

@ -93,6 +93,7 @@ struct dll_target : public target_t, public expr_scan_t {
bool process(const NetProcTop*);
bool process(const NetAnalogTop*);
void scope(const NetScope*);
void convert_module_ports(const NetScope*);
void signal(const NetNet*);
bool signal_paths(const NetNet*);
ivl_dll_t dll_;
@ -646,7 +647,11 @@ struct ivl_scope_s {
unsigned is_cell;
unsigned ports;
ivl_signal_t*port;
union {
ivl_signal_t*port;
ivl_nexus_t*nex;
NetNet**net;
} u_;
std::vector<ivl_switch_t>switches;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1998-2010 Stephen Williams <steve@icarus.com>
* Copyright (c) 1998-2011 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
@ -32,6 +32,10 @@ void target_t::scope(const NetScope*)
{
}
void target_t::convert_module_ports(const NetScope*)
{
}
bool target_t::branch(const NetBranch*obj)
{
cerr << obj->get_fileline() << ": error: target (" << typeid(*this).name()

View File

@ -1,7 +1,7 @@
#ifndef __target_H
#define __target_H
/*
* Copyright (c) 1998-2008 Stephen Williams (steve@icarus.com)
* Copyright (c) 1998-2011 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
@ -56,6 +56,10 @@ struct target_t {
anything else is called. */
virtual void scope(const NetScope*);
/* This is called to convert module ports from a NetNet* to an
* ivl_signal_t object. */
virtual void convert_module_ports(const NetScope*);
/* Output an event object. Called for each named event in the scope. */
virtual void event(const NetEvent*);

View File

@ -560,7 +560,7 @@ statement
requirements so are handled by their own rules. */
| label_opt K_file_line T_NUMBER T_NUMBER T_STRING ';'
{ compile_file_line($1, $3, $4, $5); }
| label_opt K_file_line T_NUMBER T_NUMBER T_NUMBER ';'
{ assert($5 == 0);
compile_file_line($1, $3, $4, 0); }