Merge branch 'master' into vvp-net-out-rework
This commit is contained in:
commit
53051be2d4
3
Module.h
3
Module.h
|
|
@ -1,7 +1,7 @@
|
||||||
#ifndef __Module_H
|
#ifndef __Module_H
|
||||||
#define __Module_H
|
#define __Module_H
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1998-2008 Stephen Williams (steve@icarus.com)
|
* Copyright (c) 1998-2009 Stephen Williams (steve@icarus.com)
|
||||||
*
|
*
|
||||||
* This source code is free software; you can redistribute it
|
* This source code is free software; you can redistribute it
|
||||||
* and/or modify it in source code form under the terms of the GNU
|
* and/or modify it in source code form under the terms of the GNU
|
||||||
|
|
@ -105,6 +105,7 @@ class Module : public PScope, public LineInfo {
|
||||||
/* These are the timescale for this module. The default is
|
/* These are the timescale for this module. The default is
|
||||||
set by the `timescale directive. */
|
set by the `timescale directive. */
|
||||||
int time_unit, time_precision;
|
int time_unit, time_precision;
|
||||||
|
bool time_from_timescale;
|
||||||
|
|
||||||
/* Task definitions within this module */
|
/* Task definitions within this module */
|
||||||
map<perm_string,PTask*> tasks;
|
map<perm_string,PTask*> tasks;
|
||||||
|
|
|
||||||
22
PDelays.cc
22
PDelays.cc
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1999-2008 Stephen Williams (steve@icarus.com)
|
* Copyright (c) 1999-2009 Stephen Williams (steve@icarus.com)
|
||||||
*
|
*
|
||||||
* This source code is free software; you can redistribute it
|
* This source code is free software; you can redistribute it
|
||||||
* and/or modify it in source code form under the terms of the GNU
|
* and/or modify it in source code form under the terms of the GNU
|
||||||
|
|
@ -26,6 +26,11 @@
|
||||||
# include "verinum.h"
|
# include "verinum.h"
|
||||||
# include "netmisc.h"
|
# include "netmisc.h"
|
||||||
|
|
||||||
|
bool dly_used_no_timescale = false;
|
||||||
|
bool dly_used_timescale = false;
|
||||||
|
bool display_ts_dly_warning = true;
|
||||||
|
|
||||||
|
|
||||||
PDelays::PDelays()
|
PDelays::PDelays()
|
||||||
{
|
{
|
||||||
delete_flag_ = true;
|
delete_flag_ = true;
|
||||||
|
|
@ -62,10 +67,23 @@ void PDelays::set_delays(const svector<PExpr*>*del, bool df)
|
||||||
|
|
||||||
static NetExpr*calculate_val(Design*des, NetScope*scope, const PExpr*expr)
|
static NetExpr*calculate_val(Design*des, NetScope*scope, const PExpr*expr)
|
||||||
{
|
{
|
||||||
|
|
||||||
NetExpr*dex = expr->elaborate_expr(des, scope, -1, false);
|
NetExpr*dex = expr->elaborate_expr(des, scope, -1, false);
|
||||||
eval_expr(dex);
|
eval_expr(dex);
|
||||||
|
|
||||||
|
/* Print a warning if we find default and `timescale based
|
||||||
|
* delays in the design, since this is likely an error. */
|
||||||
|
if (scope->time_from_timescale()) dly_used_timescale = true;
|
||||||
|
else dly_used_no_timescale = true;
|
||||||
|
|
||||||
|
if (display_ts_dly_warning &&
|
||||||
|
dly_used_no_timescale && dly_used_timescale) {
|
||||||
|
cerr << "warning: Found both default and "
|
||||||
|
"`timescale based delays. Use" << endl;
|
||||||
|
cerr << " -Wtimescale to find the "
|
||||||
|
"module(s) with no `timescale." << endl;
|
||||||
|
display_ts_dly_warning = false;
|
||||||
|
}
|
||||||
|
|
||||||
/* If the delay expression is a real constant or vector
|
/* If the delay expression is a real constant or vector
|
||||||
constant, then evaluate it, scale it to the local time
|
constant, then evaluate it, scale it to the local time
|
||||||
units, and return an adjusted value. */
|
units, and return an adjusted value. */
|
||||||
|
|
|
||||||
16
PWire.cc
16
PWire.cc
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1999-2007 Stephen Williams (steve@icarus.com)
|
* Copyright (c) 1999-2009 Stephen Williams (steve@icarus.com)
|
||||||
*
|
*
|
||||||
* This source code is free software; you can redistribute it
|
* This source code is free software; you can redistribute it
|
||||||
* and/or modify it in source code form under the terms of the GNU
|
* and/or modify it in source code form under the terms of the GNU
|
||||||
|
|
@ -29,8 +29,8 @@ PWire::PWire(perm_string n,
|
||||||
: name_(n), type_(t), port_type_(pt), data_type_(dt),
|
: name_(n), type_(t), port_type_(pt), data_type_(dt),
|
||||||
signed_(false), isint_(false),
|
signed_(false), isint_(false),
|
||||||
port_msb_(0), port_lsb_(0), port_set_(false),
|
port_msb_(0), port_lsb_(0), port_set_(false),
|
||||||
net_msb_(0), net_lsb_(0), net_set_(false), error_cnt_(0),
|
net_msb_(0), net_lsb_(0), net_set_(false), is_scalar_(false),
|
||||||
lidx_(0), ridx_(0), discipline_(0)
|
error_cnt_(0), lidx_(0), ridx_(0), discipline_(0)
|
||||||
{
|
{
|
||||||
if (t == NetNet::INTEGER) {
|
if (t == NetNet::INTEGER) {
|
||||||
type_ = NetNet::REG;
|
type_ = NetNet::REG;
|
||||||
|
|
@ -135,7 +135,12 @@ bool PWire::get_isint() const
|
||||||
return isint_;
|
return isint_;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PWire::set_range(PExpr*m, PExpr*l, PWSRType type)
|
bool PWire::get_scalar() const
|
||||||
|
{
|
||||||
|
return is_scalar_;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PWire::set_range(PExpr*m, PExpr*l, PWSRType type, bool is_scalar)
|
||||||
{
|
{
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case SR_PORT:
|
case SR_PORT:
|
||||||
|
|
@ -147,6 +152,7 @@ void PWire::set_range(PExpr*m, PExpr*l, PWSRType type)
|
||||||
port_msb_ = m;
|
port_msb_ = m;
|
||||||
port_lsb_ = l;
|
port_lsb_ = l;
|
||||||
port_set_ = true;
|
port_set_ = true;
|
||||||
|
is_scalar_ = is_scalar;
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
@ -159,6 +165,7 @@ void PWire::set_range(PExpr*m, PExpr*l, PWSRType type)
|
||||||
net_msb_ = m;
|
net_msb_ = m;
|
||||||
net_lsb_ = l;
|
net_lsb_ = l;
|
||||||
net_set_ = true;
|
net_set_ = true;
|
||||||
|
is_scalar_ = is_scalar;
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
@ -181,6 +188,7 @@ void PWire::set_range(PExpr*m, PExpr*l, PWSRType type)
|
||||||
net_msb_ = m;
|
net_msb_ = m;
|
||||||
net_lsb_ = l;
|
net_lsb_ = l;
|
||||||
net_set_ = true;
|
net_set_ = true;
|
||||||
|
is_scalar_ = is_scalar;
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
6
PWire.h
6
PWire.h
|
|
@ -1,7 +1,7 @@
|
||||||
#ifndef __PWire_H
|
#ifndef __PWire_H
|
||||||
#define __PWire_H
|
#define __PWire_H
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1998-2007 Stephen Williams (steve@icarus.com)
|
* Copyright (c) 1998-2009 Stephen Williams (steve@icarus.com)
|
||||||
*
|
*
|
||||||
* This source code is free software; you can redistribute it
|
* This source code is free software; you can redistribute it
|
||||||
* and/or modify it in source code form under the terms of the GNU
|
* and/or modify it in source code form under the terms of the GNU
|
||||||
|
|
@ -70,11 +70,12 @@ class PWire : public LineInfo {
|
||||||
void set_signed(bool flag);
|
void set_signed(bool flag);
|
||||||
bool get_signed() const;
|
bool get_signed() const;
|
||||||
bool get_isint() const;
|
bool get_isint() const;
|
||||||
|
bool get_scalar() const;
|
||||||
|
|
||||||
bool set_data_type(ivl_variable_type_t dt);
|
bool set_data_type(ivl_variable_type_t dt);
|
||||||
ivl_variable_type_t get_data_type() const;
|
ivl_variable_type_t get_data_type() const;
|
||||||
|
|
||||||
void set_range(PExpr*msb, PExpr*lsb, PWSRType type);
|
void set_range(PExpr*msb, PExpr*lsb, PWSRType type, bool is_scalar);
|
||||||
|
|
||||||
void set_memory_idx(PExpr*ldx, PExpr*rdx);
|
void set_memory_idx(PExpr*ldx, PExpr*rdx);
|
||||||
|
|
||||||
|
|
@ -104,6 +105,7 @@ class PWire : public LineInfo {
|
||||||
PExpr*net_msb_;
|
PExpr*net_msb_;
|
||||||
PExpr*net_lsb_;
|
PExpr*net_lsb_;
|
||||||
bool net_set_;
|
bool net_set_;
|
||||||
|
bool is_scalar_;
|
||||||
unsigned error_cnt_;
|
unsigned error_cnt_;
|
||||||
|
|
||||||
// If this wire is actually a memory, these indices will give
|
// If this wire is actually a memory, these indices will give
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
.TH iverilog 1 "February 4th, 2009" "" "Version 0.9.devel"
|
.TH iverilog 1 "April 17th, 2009" "" "Version 0.10.devel"
|
||||||
.SH NAME
|
.SH NAME
|
||||||
iverilog - Icarus Verilog compiler
|
iverilog - Icarus Verilog compiler
|
||||||
|
|
||||||
|
|
@ -100,7 +100,7 @@ The standards requires that a vectored port have matching ranges for its
|
||||||
port declaration as well as any net/register declaration. It was common
|
port declaration as well as any net/register declaration. It was common
|
||||||
practice in the past to only specify the range for the net/register
|
practice in the past to only specify the range for the net/register
|
||||||
declaration and some tools still allow this. By default any mismatch is
|
declaration and some tools still allow this. By default any mismatch is
|
||||||
reported as a error. Using \fI-gno-io-range-error\fP will produce a
|
reported as a error. Using \fB-gno-io-range-error\fP will produce a
|
||||||
warning instead of a fatal error for the case of a vectored net/register
|
warning instead of a fatal error for the case of a vectored net/register
|
||||||
and a scalar port declaration.
|
and a scalar port declaration.
|
||||||
.TP 8
|
.TP 8
|
||||||
|
|
@ -250,7 +250,7 @@ after a \fB-Wall\fP argument to suppress isolated warning types.
|
||||||
|
|
||||||
.TP 8
|
.TP 8
|
||||||
.B all
|
.B all
|
||||||
This enables all supported warning categories.
|
This enables the implicit, portbind and timescale warning categories.
|
||||||
|
|
||||||
.TP 8
|
.TP 8
|
||||||
.B implicit
|
.B implicit
|
||||||
|
|
|
||||||
28
elab_expr.cc
28
elab_expr.cc
|
|
@ -1617,7 +1617,7 @@ NetExpr* PEConcat::elaborate_expr(Design*des, NetScope*scope,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tmp->expr_type() == IVL_VT_REAL) {
|
if (tmp->expr_type() == IVL_VT_REAL) {
|
||||||
cerr << tmp->get_fileline() << ": error: concatenation "
|
cerr << tmp->get_fileline() << ": error: Concatenation "
|
||||||
<< "repeat expression can not be REAL." << endl;
|
<< "repeat expression can not be REAL." << endl;
|
||||||
des->errors += 1;
|
des->errors += 1;
|
||||||
return 0;
|
return 0;
|
||||||
|
|
@ -1627,7 +1627,7 @@ NetExpr* PEConcat::elaborate_expr(Design*des, NetScope*scope,
|
||||||
|
|
||||||
if (rep == 0) {
|
if (rep == 0) {
|
||||||
cerr << get_fileline() << ": error: "
|
cerr << get_fileline() << ": error: "
|
||||||
"concatenation repeat expression cannot be evaluated."
|
"Concatenation repeat expression cannot be evaluated."
|
||||||
<< endl;
|
<< endl;
|
||||||
cerr << get_fileline() << ": : The expression is: "
|
cerr << get_fileline() << ": : The expression is: "
|
||||||
<< *tmp << endl;
|
<< *tmp << endl;
|
||||||
|
|
@ -1688,7 +1688,7 @@ NetExpr* PEConcat::elaborate_expr(Design*des, NetScope*scope,
|
||||||
|
|
||||||
if (ex->expr_type() == IVL_VT_REAL) {
|
if (ex->expr_type() == IVL_VT_REAL) {
|
||||||
cerr << ex->get_fileline() << ": error: "
|
cerr << ex->get_fileline() << ": error: "
|
||||||
<< "concatenation operand can not be real: "
|
<< "Concatenation operand can not be real: "
|
||||||
<< *parms_[idx] << endl;
|
<< *parms_[idx] << endl;
|
||||||
des->errors += 1;
|
des->errors += 1;
|
||||||
continue;
|
continue;
|
||||||
|
|
@ -1696,8 +1696,8 @@ NetExpr* PEConcat::elaborate_expr(Design*des, NetScope*scope,
|
||||||
|
|
||||||
if (! ex->has_width()) {
|
if (! ex->has_width()) {
|
||||||
cerr << ex->get_fileline() << ": error: "
|
cerr << ex->get_fileline() << ": error: "
|
||||||
<< "concatenation operand has indefinite width: "
|
<< "Concatenation operand \"" << *parms_[idx]
|
||||||
<< *ex << endl;
|
<< "\" has indefinite width." << endl;
|
||||||
des->errors += 1;
|
des->errors += 1;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
@ -2642,11 +2642,13 @@ NetExpr* PEIdent::elaborate_expr_net_word_(Design*des, NetScope*scope,
|
||||||
if (name_tail.index.size() > 1)
|
if (name_tail.index.size() > 1)
|
||||||
word_sel = name_tail.index.back().sel;
|
word_sel = name_tail.index.back().sel;
|
||||||
|
|
||||||
if (res->expr_type() == IVL_VT_REAL &&
|
if (net->get_scalar() &&
|
||||||
word_sel != index_component_t::SEL_NONE) {
|
word_sel != index_component_t::SEL_NONE) {
|
||||||
cerr << get_fileline() << ": error: "
|
cerr << get_fileline() << ": error: can not select part of ";
|
||||||
<< "can not select part of real array word: "
|
if (res->expr_type() == IVL_VT_REAL) cerr << "real";
|
||||||
<< net->name() <<"[" << *word_index << "]" << endl;
|
else cerr << "scalar";
|
||||||
|
cerr << " array word: " << net->name()
|
||||||
|
<<"[" << *word_index << "]" << endl;
|
||||||
des->errors += 1;
|
des->errors += 1;
|
||||||
delete res;
|
delete res;
|
||||||
return 0;
|
return 0;
|
||||||
|
|
@ -2946,10 +2948,12 @@ NetExpr* PEIdent::elaborate_expr_net(Design*des, NetScope*scope,
|
||||||
if (! path_.back().index.empty())
|
if (! path_.back().index.empty())
|
||||||
use_sel = path_.back().index.back().sel;
|
use_sel = path_.back().index.back().sel;
|
||||||
|
|
||||||
if (node->expr_type() == IVL_VT_REAL &&
|
if (net->get_scalar() &&
|
||||||
use_sel != index_component_t::SEL_NONE) {
|
use_sel != index_component_t::SEL_NONE) {
|
||||||
cerr << get_fileline() << ": error: "
|
cerr << get_fileline() << ": error: can not select part of ";
|
||||||
<< "can not select part of real: " << net->name() << endl;
|
if (node->expr_type() == IVL_VT_REAL) cerr << "real: ";
|
||||||
|
else cerr << "scalar: ";
|
||||||
|
cerr << net->name() << endl;
|
||||||
des->errors += 1;
|
des->errors += 1;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
19
elab_lval.cc
19
elab_lval.cc
|
|
@ -199,10 +199,12 @@ NetAssign_* PEIdent::elaborate_lval(Design*des,
|
||||||
return elaborate_lval_net_word_(des, scope, reg);
|
return elaborate_lval_net_word_(des, scope, reg);
|
||||||
|
|
||||||
// This must be after the array word elaboration above!
|
// This must be after the array word elaboration above!
|
||||||
if (reg->data_type() == IVL_VT_REAL &&
|
if (reg->get_scalar() &&
|
||||||
use_sel != index_component_t::SEL_NONE) {
|
use_sel != index_component_t::SEL_NONE) {
|
||||||
cerr << get_fileline() << ": error: "
|
cerr << get_fileline() << ": error: can not select part of ";
|
||||||
<< "can not select part of real: " << reg->name() << endl;
|
if (reg->data_type() == IVL_VT_REAL) cerr << "real: ";
|
||||||
|
else cerr << "scalar: ";
|
||||||
|
cerr << reg->name() << endl;
|
||||||
des->errors += 1;
|
des->errors += 1;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
@ -301,12 +303,13 @@ NetAssign_* PEIdent::elaborate_lval_net_word_(Design*des,
|
||||||
if (name_tail.index.size() > 1)
|
if (name_tail.index.size() > 1)
|
||||||
use_sel = name_tail.index.back().sel;
|
use_sel = name_tail.index.back().sel;
|
||||||
|
|
||||||
if (reg->data_type() == IVL_VT_REAL &&
|
if (reg->get_scalar() &&
|
||||||
use_sel != index_component_t::SEL_NONE) {
|
use_sel != index_component_t::SEL_NONE) {
|
||||||
perm_string name = peek_tail_name(path_);
|
cerr << get_fileline() << ": error: can not select part of ";
|
||||||
cerr << get_fileline() << ": error: "
|
if (reg->data_type() == IVL_VT_REAL) cerr << "real";
|
||||||
<< "can not select part of real array word: "
|
else cerr << "scalar";
|
||||||
<< reg->name() << "[" << *word << "]" << endl;
|
cerr << " array word: " << reg->name()
|
||||||
|
<< "[" << *word << "]" << endl;
|
||||||
des->errors += 1;
|
des->errors += 1;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
17
elab_net.cc
17
elab_net.cc
|
|
@ -466,10 +466,13 @@ NetNet* PEIdent::elaborate_lnet_common_(Design*des, NetScope*scope,
|
||||||
|
|
||||||
/* The array has a part/bit select at the end. */
|
/* The array has a part/bit select at the end. */
|
||||||
if (name_tail.index.size() > sig->array_dimensions()) {
|
if (name_tail.index.size() > sig->array_dimensions()) {
|
||||||
if (sig->data_type() == IVL_VT_REAL) {
|
if (sig->get_scalar()) {
|
||||||
cerr << get_fileline() << ": error: "
|
cerr << get_fileline() << ": error: "
|
||||||
<< "can not select part of real array word: "
|
<< "can not select part of ";
|
||||||
<< sig->name() << "[" << widx_val << "]" << endl;
|
if (sig->data_type() == IVL_VT_REAL) cerr << "real";
|
||||||
|
else cerr << "scalar";
|
||||||
|
cerr << " array word: " << sig->name()
|
||||||
|
<< "[" << widx_val << "]" << endl;
|
||||||
des->errors += 1;
|
des->errors += 1;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
@ -489,10 +492,12 @@ NetNet* PEIdent::elaborate_lnet_common_(Design*des, NetScope*scope,
|
||||||
lidx = lidx_tmp;
|
lidx = lidx_tmp;
|
||||||
}
|
}
|
||||||
} else if (!name_tail.index.empty()) {
|
} else if (!name_tail.index.empty()) {
|
||||||
if (sig->data_type() == IVL_VT_REAL) {
|
if (sig->get_scalar()) {
|
||||||
cerr << get_fileline() << ": error: "
|
cerr << get_fileline() << ": error: "
|
||||||
<< "can not select part of real: "
|
<< "can not select part of ";
|
||||||
<< sig->name() << endl;
|
if (sig->data_type() == IVL_VT_REAL) cerr << "real: ";
|
||||||
|
else cerr << "scalar: ";
|
||||||
|
cerr << sig->name() << endl;
|
||||||
des->errors += 1;
|
des->errors += 1;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1062,6 +1062,7 @@ void PGModule::elaborate_scope_mod_instances_(Design*des, Module*mod, NetScope*s
|
||||||
// Set time units and precision.
|
// Set time units and precision.
|
||||||
my_scope->time_unit(mod->time_unit);
|
my_scope->time_unit(mod->time_unit);
|
||||||
my_scope->time_precision(mod->time_precision);
|
my_scope->time_precision(mod->time_precision);
|
||||||
|
my_scope->time_from_timescale(mod->time_from_timescale);
|
||||||
des->set_precision(mod->time_precision);
|
des->set_precision(mod->time_precision);
|
||||||
|
|
||||||
// Look for module parameter replacements. The "replace" map
|
// Look for module parameter replacements. The "replace" map
|
||||||
|
|
|
||||||
25
elab_sig.cc
25
elab_sig.cc
|
|
@ -599,9 +599,11 @@ void PFunction::elaborate_sig(Design*des, NetScope*scope) const
|
||||||
}
|
}
|
||||||
|
|
||||||
ret_sig = new NetNet(scope, fname, NetNet::REG, mnum, lnum);
|
ret_sig = new NetNet(scope, fname, NetNet::REG, mnum, lnum);
|
||||||
|
ret_sig->set_scalar(false);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
ret_sig = new NetNet(scope, fname, NetNet::REG);
|
ret_sig = new NetNet(scope, fname, NetNet::REG);
|
||||||
|
ret_sig->set_scalar(true);
|
||||||
}
|
}
|
||||||
ret_sig->set_line(*this);
|
ret_sig->set_line(*this);
|
||||||
ret_sig->set_signed(return_type_.type == PTF_REG_S);
|
ret_sig->set_signed(return_type_.type == PTF_REG_S);
|
||||||
|
|
@ -614,6 +616,7 @@ void PFunction::elaborate_sig(Design*des, NetScope*scope) const
|
||||||
ret_sig->set_line(*this);
|
ret_sig->set_line(*this);
|
||||||
ret_sig->set_signed(true);
|
ret_sig->set_signed(true);
|
||||||
ret_sig->set_isint(true);
|
ret_sig->set_isint(true);
|
||||||
|
ret_sig->set_scalar(false);
|
||||||
ret_sig->port_type(NetNet::POUTPUT);
|
ret_sig->port_type(NetNet::POUTPUT);
|
||||||
ret_sig->data_type(IVL_VT_LOGIC);
|
ret_sig->data_type(IVL_VT_LOGIC);
|
||||||
break;
|
break;
|
||||||
|
|
@ -623,6 +626,7 @@ void PFunction::elaborate_sig(Design*des, NetScope*scope) const
|
||||||
ret_sig->set_line(*this);
|
ret_sig->set_line(*this);
|
||||||
ret_sig->set_signed(false);
|
ret_sig->set_signed(false);
|
||||||
ret_sig->set_isint(false);
|
ret_sig->set_isint(false);
|
||||||
|
ret_sig->set_scalar(false);
|
||||||
ret_sig->port_type(NetNet::POUTPUT);
|
ret_sig->port_type(NetNet::POUTPUT);
|
||||||
ret_sig->data_type(IVL_VT_LOGIC);
|
ret_sig->data_type(IVL_VT_LOGIC);
|
||||||
break;
|
break;
|
||||||
|
|
@ -633,6 +637,7 @@ void PFunction::elaborate_sig(Design*des, NetScope*scope) const
|
||||||
ret_sig->set_line(*this);
|
ret_sig->set_line(*this);
|
||||||
ret_sig->set_signed(true);
|
ret_sig->set_signed(true);
|
||||||
ret_sig->set_isint(false);
|
ret_sig->set_isint(false);
|
||||||
|
ret_sig->set_scalar(true);
|
||||||
ret_sig->port_type(NetNet::POUTPUT);
|
ret_sig->port_type(NetNet::POUTPUT);
|
||||||
ret_sig->data_type(IVL_VT_REAL);
|
ret_sig->data_type(IVL_VT_REAL);
|
||||||
break;
|
break;
|
||||||
|
|
@ -850,10 +855,15 @@ void PWhile::elaborate_sig(Design*des, NetScope*scope) const
|
||||||
NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
|
NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
|
||||||
{
|
{
|
||||||
NetNet::Type wtype = type_;
|
NetNet::Type wtype = type_;
|
||||||
if (wtype == NetNet::IMPLICIT)
|
bool is_implicit_scalar = false;
|
||||||
|
if (wtype == NetNet::IMPLICIT) {
|
||||||
wtype = NetNet::WIRE;
|
wtype = NetNet::WIRE;
|
||||||
if (wtype == NetNet::IMPLICIT_REG)
|
is_implicit_scalar = true;
|
||||||
|
}
|
||||||
|
if (wtype == NetNet::IMPLICIT_REG) {
|
||||||
wtype = NetNet::REG;
|
wtype = NetNet::REG;
|
||||||
|
is_implicit_scalar = true;
|
||||||
|
}
|
||||||
|
|
||||||
unsigned wid = 1;
|
unsigned wid = 1;
|
||||||
long lsb = 0, msb = 0;
|
long lsb = 0, msb = 0;
|
||||||
|
|
@ -902,6 +912,8 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
|
||||||
delete texpr;
|
delete texpr;
|
||||||
nmsb = pmsb;
|
nmsb = pmsb;
|
||||||
nlsb = plsb;
|
nlsb = plsb;
|
||||||
|
/* An implicit port can have a range so note that here. */
|
||||||
|
is_implicit_scalar = false;
|
||||||
}
|
}
|
||||||
if (!port_set_) assert(port_msb_ == 0 && port_lsb_ == 0);
|
if (!port_set_) assert(port_msb_ == 0 && port_lsb_ == 0);
|
||||||
if (port_msb_ == 0) assert(port_lsb_ == 0);
|
if (port_msb_ == 0) assert(port_lsb_ == 0);
|
||||||
|
|
@ -1095,8 +1107,11 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
|
||||||
}
|
}
|
||||||
|
|
||||||
if (debug_elaborate) {
|
if (debug_elaborate) {
|
||||||
cerr << get_fileline() << ": debug: Create signal "
|
cerr << get_fileline() << ": debug: Create signal " << wtype;
|
||||||
<< wtype << " ["<<msb<<":"<<lsb<<"] " << name_;
|
if (!get_scalar()) {
|
||||||
|
cerr << " ["<<msb<<":"<<lsb<<"]";
|
||||||
|
}
|
||||||
|
cerr << " " << name_;
|
||||||
if (array_dimensions > 0) {
|
if (array_dimensions > 0) {
|
||||||
cerr << " [" << array_s0 << ":" << array_e0 << "]" << endl;
|
cerr << " [" << array_s0 << ":" << array_e0 << "]" << endl;
|
||||||
}
|
}
|
||||||
|
|
@ -1126,6 +1141,8 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
|
||||||
sig->port_type(port_type_);
|
sig->port_type(port_type_);
|
||||||
sig->set_signed(get_signed());
|
sig->set_signed(get_signed());
|
||||||
sig->set_isint(get_isint());
|
sig->set_isint(get_isint());
|
||||||
|
if (is_implicit_scalar) sig->set_scalar(true);
|
||||||
|
else sig->set_scalar(get_scalar());
|
||||||
|
|
||||||
if (ivl_discipline_t dis = get_discipline()) {
|
if (ivl_discipline_t dis = get_discipline()) {
|
||||||
sig->set_discipline(dis);
|
sig->set_discipline(dis);
|
||||||
|
|
|
||||||
28
elaborate.cc
28
elaborate.cc
|
|
@ -1827,6 +1827,20 @@ static NetExpr*elaborate_delay_expr(PExpr*expr, Design*des, NetScope*scope)
|
||||||
probe_expr_width(des, scope, expr);
|
probe_expr_width(des, scope, expr);
|
||||||
NetExpr*dex = elab_and_eval(des, scope, expr, -1);
|
NetExpr*dex = elab_and_eval(des, scope, expr, -1);
|
||||||
|
|
||||||
|
/* Print a warning if we find default and `timescale based
|
||||||
|
* delays in the design, since this is likely an error. */
|
||||||
|
if (scope->time_from_timescale()) dly_used_timescale = true;
|
||||||
|
else dly_used_no_timescale = true;
|
||||||
|
|
||||||
|
if (display_ts_dly_warning &&
|
||||||
|
dly_used_no_timescale && dly_used_timescale) {
|
||||||
|
cerr << "warning: Found both default and "
|
||||||
|
"`timescale based delays. Use" << endl;
|
||||||
|
cerr << " -Wtimescale to find the "
|
||||||
|
"module(s) with no `timescale." << endl;
|
||||||
|
display_ts_dly_warning = false;
|
||||||
|
}
|
||||||
|
|
||||||
/* If the delay expression is a real constant or vector
|
/* If the delay expression is a real constant or vector
|
||||||
constant, then evaluate it, scale it to the local time
|
constant, then evaluate it, scale it to the local time
|
||||||
units, and return an adjusted NetEConst. */
|
units, and return an adjusted NetEConst. */
|
||||||
|
|
@ -3737,6 +3751,19 @@ void PSpecPath::elaborate(Design*des, NetScope*scope) const
|
||||||
if (ndelays > 12)
|
if (ndelays > 12)
|
||||||
ndelays = 12;
|
ndelays = 12;
|
||||||
|
|
||||||
|
/* Print a warning if we find default and `timescale based
|
||||||
|
* delays in the design, since this is likely an error. */
|
||||||
|
if (scope->time_from_timescale()) dly_used_timescale = true;
|
||||||
|
else dly_used_no_timescale = true;
|
||||||
|
|
||||||
|
if (display_ts_dly_warning &&
|
||||||
|
dly_used_no_timescale && dly_used_timescale) {
|
||||||
|
cerr << "warning: Found both default and "
|
||||||
|
"`timescale based delays. Use" << endl;
|
||||||
|
cerr << " -Wtimescale to find the "
|
||||||
|
"module(s) with no `timescale." << endl;
|
||||||
|
display_ts_dly_warning = false;
|
||||||
|
}
|
||||||
int shift = scope->time_unit() - des->get_precision();
|
int shift = scope->time_unit() - des->get_precision();
|
||||||
|
|
||||||
/* Elaborate the delay values themselves. Remember to scale
|
/* Elaborate the delay values themselves. Remember to scale
|
||||||
|
|
@ -4301,6 +4328,7 @@ Design* elaborate(list<perm_string>roots)
|
||||||
scope->set_line(rmod);
|
scope->set_line(rmod);
|
||||||
scope->time_unit(rmod->time_unit);
|
scope->time_unit(rmod->time_unit);
|
||||||
scope->time_precision(rmod->time_precision);
|
scope->time_precision(rmod->time_precision);
|
||||||
|
scope->time_from_timescale(rmod->time_from_timescale);
|
||||||
scope->default_nettype(rmod->default_nettype);
|
scope->default_nettype(rmod->default_nettype);
|
||||||
des->set_precision(rmod->time_precision);
|
des->set_precision(rmod->time_precision);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
.TH iverilog-vpi 1 "November 19th, 2008" "" "Version 0.9.devel"
|
.TH iverilog-vpi 1 "April 17th, 2009" "" "Version 0.10.devel"
|
||||||
.SH NAME
|
.SH NAME
|
||||||
iverilog-vpi - Compile front end for VPI modules
|
iverilog-vpi - Compile front end for VPI modules
|
||||||
|
|
||||||
|
|
|
||||||
14
net_scope.cc
14
net_scope.cc
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2000-2008 Stephen Williams (steve@icarus.com)
|
* Copyright (c) 2000-2009 Stephen Williams (steve@icarus.com)
|
||||||
*
|
*
|
||||||
* This source code is free software; you can redistribute it
|
* This source code is free software; you can redistribute it
|
||||||
* and/or modify it in source code form under the terms of the GNU
|
* and/or modify it in source code form under the terms of the GNU
|
||||||
|
|
@ -46,12 +46,14 @@ NetScope::NetScope(NetScope*up, const hname_t&n, NetScope::TYPE t)
|
||||||
default_nettype_ = up->default_nettype();
|
default_nettype_ = up->default_nettype();
|
||||||
time_unit_ = up->time_unit();
|
time_unit_ = up->time_unit();
|
||||||
time_prec_ = up->time_precision();
|
time_prec_ = up->time_precision();
|
||||||
|
time_from_timescale_ = up->time_from_timescale();
|
||||||
sib_ = up_->sub_;
|
sib_ = up_->sub_;
|
||||||
up_->sub_ = this;
|
up_->sub_ = this;
|
||||||
} else {
|
} else {
|
||||||
default_nettype_ = NetNet::NONE;
|
default_nettype_ = NetNet::NONE;
|
||||||
time_unit_ = 0;
|
time_unit_ = 0;
|
||||||
time_prec_ = 0;
|
time_prec_ = 0;
|
||||||
|
time_from_timescale_ = false;
|
||||||
assert(t == MODULE);
|
assert(t == MODULE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -295,6 +297,11 @@ void NetScope::time_precision(int val)
|
||||||
time_prec_ = val;
|
time_prec_ = val;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void NetScope::time_from_timescale(bool val)
|
||||||
|
{
|
||||||
|
time_from_timescale_ = val;
|
||||||
|
}
|
||||||
|
|
||||||
int NetScope::time_unit() const
|
int NetScope::time_unit() const
|
||||||
{
|
{
|
||||||
return time_unit_;
|
return time_unit_;
|
||||||
|
|
@ -305,6 +312,11 @@ int NetScope::time_precision() const
|
||||||
return time_prec_;
|
return time_prec_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool NetScope::time_from_timescale() const
|
||||||
|
{
|
||||||
|
return time_from_timescale_;
|
||||||
|
}
|
||||||
|
|
||||||
void NetScope::default_nettype(NetNet::Type nt)
|
void NetScope::default_nettype(NetNet::Type nt)
|
||||||
{
|
{
|
||||||
default_nettype_ = nt;
|
default_nettype_ = nt;
|
||||||
|
|
|
||||||
20
netlist.cc
20
netlist.cc
|
|
@ -491,8 +491,8 @@ const Link& NetDelaySrc::condit_pin() const
|
||||||
NetNet::NetNet(NetScope*s, perm_string n, Type t, unsigned npins)
|
NetNet::NetNet(NetScope*s, perm_string n, Type t, unsigned npins)
|
||||||
: NetObj(s, n, 1),
|
: NetObj(s, n, 1),
|
||||||
type_(t), port_type_(NOT_A_PORT), data_type_(IVL_VT_NO_TYPE),
|
type_(t), port_type_(NOT_A_PORT), data_type_(IVL_VT_NO_TYPE),
|
||||||
signed_(false), isint_(false), discipline_(0), msb_(npins-1), lsb_(0),
|
signed_(false), isint_(false), is_scalar_(false),
|
||||||
dimensions_(0),
|
discipline_(0), msb_(npins-1), lsb_(0), dimensions_(0),
|
||||||
s0_(0), e0_(0), local_flag_(false), eref_count_(0), lref_count_(0)
|
s0_(0), e0_(0), local_flag_(false), eref_count_(0), lref_count_(0)
|
||||||
{
|
{
|
||||||
assert(s);
|
assert(s);
|
||||||
|
|
@ -544,7 +544,8 @@ NetNet::NetNet(NetScope*s, perm_string n, Type t,
|
||||||
long ms, long ls)
|
long ms, long ls)
|
||||||
: NetObj(s, n, 1), type_(t),
|
: NetObj(s, n, 1), type_(t),
|
||||||
port_type_(NOT_A_PORT), data_type_(IVL_VT_NO_TYPE), signed_(false),
|
port_type_(NOT_A_PORT), data_type_(IVL_VT_NO_TYPE), signed_(false),
|
||||||
isint_(false), discipline_(0), msb_(ms), lsb_(ls), dimensions_(0), s0_(0), e0_(0),
|
isint_(false), is_scalar_(false), discipline_(0), msb_(ms), lsb_(ls),
|
||||||
|
dimensions_(0), s0_(0), e0_(0),
|
||||||
local_flag_(false), eref_count_(0), lref_count_(0)
|
local_flag_(false), eref_count_(0), lref_count_(0)
|
||||||
{
|
{
|
||||||
assert(s);
|
assert(s);
|
||||||
|
|
@ -594,7 +595,8 @@ NetNet::NetNet(NetScope*s, perm_string n, Type t,
|
||||||
: NetObj(s, n, calculate_count(array_s, array_e)),
|
: NetObj(s, n, calculate_count(array_s, array_e)),
|
||||||
type_(t), port_type_(NOT_A_PORT),
|
type_(t), port_type_(NOT_A_PORT),
|
||||||
data_type_(IVL_VT_NO_TYPE), signed_(false), isint_(false),
|
data_type_(IVL_VT_NO_TYPE), signed_(false), isint_(false),
|
||||||
discipline_(0), msb_(ms), lsb_(ls), dimensions_(1), s0_(array_s), e0_(array_e),
|
is_scalar_(false), discipline_(0), msb_(ms), lsb_(ls),
|
||||||
|
dimensions_(1), s0_(array_s), e0_(array_e),
|
||||||
local_flag_(false), eref_count_(0), lref_count_(0)
|
local_flag_(false), eref_count_(0), lref_count_(0)
|
||||||
{
|
{
|
||||||
ivl_assert(*this, s);
|
ivl_assert(*this, s);
|
||||||
|
|
@ -727,6 +729,16 @@ void NetNet::set_isint(bool flag)
|
||||||
isint_ = flag;
|
isint_ = flag;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool NetNet::get_scalar() const
|
||||||
|
{
|
||||||
|
return is_scalar_;
|
||||||
|
}
|
||||||
|
|
||||||
|
void NetNet::set_scalar(bool flag)
|
||||||
|
{
|
||||||
|
is_scalar_ = flag;
|
||||||
|
}
|
||||||
|
|
||||||
ivl_discipline_t NetNet::get_discipline() const
|
ivl_discipline_t NetNet::get_discipline() const
|
||||||
{
|
{
|
||||||
return discipline_;
|
return discipline_;
|
||||||
|
|
|
||||||
|
|
@ -581,6 +581,9 @@ class NetNet : public NetObj {
|
||||||
bool get_isint() const;
|
bool get_isint() const;
|
||||||
void set_isint(bool);
|
void set_isint(bool);
|
||||||
|
|
||||||
|
bool get_scalar() const;
|
||||||
|
void set_scalar(bool);
|
||||||
|
|
||||||
/* Attach a discipline to the net. */
|
/* Attach a discipline to the net. */
|
||||||
ivl_discipline_t get_discipline() const;
|
ivl_discipline_t get_discipline() const;
|
||||||
void set_discipline(ivl_discipline_t dis);
|
void set_discipline(ivl_discipline_t dis);
|
||||||
|
|
@ -650,6 +653,7 @@ class NetNet : public NetObj {
|
||||||
ivl_variable_type_t data_type_;
|
ivl_variable_type_t data_type_;
|
||||||
bool signed_;
|
bool signed_;
|
||||||
bool isint_; // original type of integer
|
bool isint_; // original type of integer
|
||||||
|
bool is_scalar_;
|
||||||
ivl_discipline_t discipline_;
|
ivl_discipline_t discipline_;
|
||||||
|
|
||||||
long msb_, lsb_;
|
long msb_, lsb_;
|
||||||
|
|
@ -773,9 +777,11 @@ class NetScope : public Attrib {
|
||||||
|
|
||||||
void time_unit(int);
|
void time_unit(int);
|
||||||
void time_precision(int);
|
void time_precision(int);
|
||||||
|
void time_from_timescale(bool);
|
||||||
|
|
||||||
int time_unit() const;
|
int time_unit() const;
|
||||||
int time_precision() const;
|
int time_precision() const;
|
||||||
|
bool time_from_timescale() const;
|
||||||
|
|
||||||
void default_nettype(NetNet::Type);
|
void default_nettype(NetNet::Type);
|
||||||
NetNet::Type default_nettype() const;
|
NetNet::Type default_nettype() const;
|
||||||
|
|
@ -883,6 +889,7 @@ class NetScope : public Attrib {
|
||||||
unsigned def_lineno_;
|
unsigned def_lineno_;
|
||||||
|
|
||||||
signed char time_unit_, time_prec_;
|
signed char time_unit_, time_prec_;
|
||||||
|
bool time_from_timescale_;
|
||||||
NetNet::Type default_nettype_;
|
NetNet::Type default_nettype_;
|
||||||
|
|
||||||
NetEvent *events_;
|
NetEvent *events_;
|
||||||
|
|
|
||||||
|
|
@ -231,4 +231,8 @@ const char *human_readable_op(const char op, bool unary = false);
|
||||||
enum const_bool { C_NON, C_0, C_1, C_X };
|
enum const_bool { C_NON, C_0, C_1, C_X };
|
||||||
const_bool const_logical(const NetExpr*expr);
|
const_bool const_logical(const NetExpr*expr);
|
||||||
|
|
||||||
|
extern bool dly_used_no_timescale;
|
||||||
|
extern bool dly_used_timescale;
|
||||||
|
extern bool display_ts_dly_warning;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
21
pform.cc
21
pform.cc
|
|
@ -342,6 +342,9 @@ void pform_startmodule(const char*name, const char*file, unsigned lineno,
|
||||||
pform_cur_module = new Module(lex_name);
|
pform_cur_module = new Module(lex_name);
|
||||||
pform_cur_module->time_unit = pform_time_unit;
|
pform_cur_module->time_unit = pform_time_unit;
|
||||||
pform_cur_module->time_precision = pform_time_prec;
|
pform_cur_module->time_precision = pform_time_prec;
|
||||||
|
/* If we have a timescale file then the time information is from
|
||||||
|
* a timescale directive. */
|
||||||
|
pform_cur_module->time_from_timescale = pform_timescale_file != 0;
|
||||||
pform_cur_module->default_nettype = pform_default_nettype;
|
pform_cur_module->default_nettype = pform_default_nettype;
|
||||||
|
|
||||||
FILE_NAME(pform_cur_module, file, lineno);
|
FILE_NAME(pform_cur_module, file, lineno);
|
||||||
|
|
@ -1028,13 +1031,13 @@ static void pform_set_net_range(perm_string name,
|
||||||
if (range == 0) {
|
if (range == 0) {
|
||||||
/* This is the special case that we really mean a
|
/* This is the special case that we really mean a
|
||||||
scalar. Set a fake range. */
|
scalar. Set a fake range. */
|
||||||
cur->set_range(0, 0, rt);
|
cur->set_range(0, 0, rt, true);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
assert(range->count() == 2);
|
assert(range->count() == 2);
|
||||||
assert((*range)[0]);
|
assert((*range)[0]);
|
||||||
assert((*range)[1]);
|
assert((*range)[1]);
|
||||||
cur->set_range((*range)[0], (*range)[1], rt);
|
cur->set_range((*range)[0], (*range)[1], rt, false);
|
||||||
}
|
}
|
||||||
cur->set_signed(signed_flag);
|
cur->set_signed(signed_flag);
|
||||||
|
|
||||||
|
|
@ -1396,14 +1399,16 @@ void pform_module_define_port(const struct vlltype&li,
|
||||||
|
|
||||||
if (range == 0) {
|
if (range == 0) {
|
||||||
cur->set_range(0, 0, (type == NetNet::IMPLICIT) ? SR_PORT :
|
cur->set_range(0, 0, (type == NetNet::IMPLICIT) ? SR_PORT :
|
||||||
SR_BOTH);
|
SR_BOTH,
|
||||||
|
true);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
assert(range->count() == 2);
|
assert(range->count() == 2);
|
||||||
assert((*range)[0]);
|
assert((*range)[0]);
|
||||||
assert((*range)[1]);
|
assert((*range)[1]);
|
||||||
cur->set_range((*range)[0], (*range)[1],
|
cur->set_range((*range)[0], (*range)[1],
|
||||||
(type == NetNet::IMPLICIT) ? SR_PORT : SR_BOTH);
|
(type == NetNet::IMPLICIT) ? SR_PORT : SR_BOTH,
|
||||||
|
false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (attr) {
|
if (attr) {
|
||||||
|
|
@ -1483,7 +1488,7 @@ void pform_makewire(const vlltype&li, perm_string name,
|
||||||
<< " to " << dt << "." << endl;
|
<< " to " << dt << "." << endl;
|
||||||
}
|
}
|
||||||
ivl_assert(*cur, flag);
|
ivl_assert(*cur, flag);
|
||||||
cur->set_range(0, 0, SR_NET);
|
cur->set_range(0, 0, SR_NET, true);
|
||||||
cur->set_signed(true);
|
cur->set_signed(true);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
|
@ -1673,7 +1678,7 @@ svector<PWire*>*pform_make_task_ports(NetNet::PortType pt,
|
||||||
|
|
||||||
/* If there is a range involved, it needs to be set. */
|
/* If there is a range involved, it needs to be set. */
|
||||||
if (range)
|
if (range)
|
||||||
curw->set_range((*range)[0], (*range)[1], SR_PORT);
|
curw->set_range((*range)[0], (*range)[1], SR_PORT, false);
|
||||||
|
|
||||||
svector<PWire*>*tmp = new svector<PWire*>(*res, curw);
|
svector<PWire*>*tmp = new svector<PWire*>(*res, curw);
|
||||||
|
|
||||||
|
|
@ -1933,7 +1938,7 @@ static void pform_set_reg_integer(perm_string name)
|
||||||
|
|
||||||
cur->set_range(new PENumber(new verinum(integer_width-1, integer_width)),
|
cur->set_range(new PENumber(new verinum(integer_width-1, integer_width)),
|
||||||
new PENumber(new verinum((uint64_t)0, integer_width)),
|
new PENumber(new verinum((uint64_t)0, integer_width)),
|
||||||
SR_NET);
|
SR_NET, false);
|
||||||
cur->set_signed(true);
|
cur->set_signed(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1964,7 +1969,7 @@ static void pform_set_reg_time(perm_string name)
|
||||||
|
|
||||||
cur->set_range(new PENumber(new verinum(TIME_WIDTH-1, integer_width)),
|
cur->set_range(new PENumber(new verinum(TIME_WIDTH-1, integer_width)),
|
||||||
new PENumber(new verinum((uint64_t)0, integer_width)),
|
new PENumber(new verinum((uint64_t)0, integer_width)),
|
||||||
SR_NET);
|
SR_NET, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void pform_set_reg_time(list<perm_string>*names)
|
void pform_set_reg_time(list<perm_string>*names)
|
||||||
|
|
|
||||||
|
|
@ -64,6 +64,21 @@ static PLI_INT32 function_not_implemented_compiletf(PLI_BYTE8* name)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This is used to warn the user that the specified optional system
|
||||||
|
* task/function is not available (from Annex C 1364-2005).
|
||||||
|
*/
|
||||||
|
static PLI_INT32 missing_optional_compiletf(PLI_BYTE8* name)
|
||||||
|
{
|
||||||
|
vpiHandle callh = vpi_handle(vpiSysTfCall, 0);
|
||||||
|
|
||||||
|
vpi_printf("%s:%d: SORRY: %s() is not available in Icarus verilog.\n",
|
||||||
|
vpi_get_str(vpiFile, callh), (int)vpi_get(vpiLineNo, callh),
|
||||||
|
name);
|
||||||
|
vpi_control(vpiFinish, 1);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Register the function with Verilog.
|
* Register the function with Verilog.
|
||||||
*/
|
*/
|
||||||
|
|
@ -217,4 +232,83 @@ void sys_special_register(void)
|
||||||
tf_data.tfname = "$ferror";
|
tf_data.tfname = "$ferror";
|
||||||
tf_data.user_data = "$ferror";
|
tf_data.user_data = "$ferror";
|
||||||
vpi_register_systf(&tf_data);
|
vpi_register_systf(&tf_data);
|
||||||
|
|
||||||
|
/* The following optional system tasks/functions are not implemented
|
||||||
|
* in Icarus Verilog (from Annex C 1364-2005). */
|
||||||
|
tf_data.type = vpiSysTask;
|
||||||
|
tf_data.calltf = 0;
|
||||||
|
tf_data.sizetf = 0;
|
||||||
|
tf_data.compiletf = missing_optional_compiletf;
|
||||||
|
|
||||||
|
tf_data.tfname = "$input";
|
||||||
|
tf_data.user_data = "$input";
|
||||||
|
vpi_register_systf(&tf_data);
|
||||||
|
|
||||||
|
tf_data.tfname = "$key";
|
||||||
|
tf_data.user_data = "$key";
|
||||||
|
vpi_register_systf(&tf_data);
|
||||||
|
|
||||||
|
tf_data.tfname = "$nokey";
|
||||||
|
tf_data.user_data = "$nokey";
|
||||||
|
vpi_register_systf(&tf_data);
|
||||||
|
|
||||||
|
tf_data.tfname = "$list";
|
||||||
|
tf_data.user_data = "$list";
|
||||||
|
vpi_register_systf(&tf_data);
|
||||||
|
|
||||||
|
tf_data.tfname = "$log";
|
||||||
|
tf_data.user_data = "$log";
|
||||||
|
vpi_register_systf(&tf_data);
|
||||||
|
|
||||||
|
tf_data.tfname = "$nolog";
|
||||||
|
tf_data.user_data = "$nolog";
|
||||||
|
vpi_register_systf(&tf_data);
|
||||||
|
|
||||||
|
tf_data.tfname = "$save";
|
||||||
|
tf_data.user_data = "$save";
|
||||||
|
vpi_register_systf(&tf_data);
|
||||||
|
|
||||||
|
tf_data.tfname = "$restart";
|
||||||
|
tf_data.user_data = "$restart";
|
||||||
|
vpi_register_systf(&tf_data);
|
||||||
|
|
||||||
|
tf_data.tfname = "$incsave";
|
||||||
|
tf_data.user_data = "$incsave";
|
||||||
|
vpi_register_systf(&tf_data);
|
||||||
|
|
||||||
|
tf_data.tfname = "$scope";
|
||||||
|
tf_data.user_data = "$scope";
|
||||||
|
vpi_register_systf(&tf_data);
|
||||||
|
|
||||||
|
tf_data.tfname = "$showscopes";
|
||||||
|
tf_data.user_data = "$showscopes";
|
||||||
|
vpi_register_systf(&tf_data);
|
||||||
|
|
||||||
|
tf_data.tfname = "$showvars";
|
||||||
|
tf_data.user_data = "$showvars";
|
||||||
|
vpi_register_systf(&tf_data);
|
||||||
|
|
||||||
|
tf_data.tfname = "$sreadmemb";
|
||||||
|
tf_data.user_data = "$sreadmemb";
|
||||||
|
vpi_register_systf(&tf_data);
|
||||||
|
|
||||||
|
tf_data.tfname = "$sreadmemh";
|
||||||
|
tf_data.user_data = "$sreadmemh";
|
||||||
|
vpi_register_systf(&tf_data);
|
||||||
|
|
||||||
|
/* Optional functions. */
|
||||||
|
tf_data.type = vpiSysFunc;
|
||||||
|
tf_data.sysfunctype = vpiIntFunc;
|
||||||
|
|
||||||
|
tf_data.tfname = "$countdrivers";
|
||||||
|
tf_data.user_data = "$countdrivers";
|
||||||
|
vpi_register_systf(&tf_data);
|
||||||
|
|
||||||
|
tf_data.tfname = "$getpattern";
|
||||||
|
tf_data.user_data = "$getpattern";
|
||||||
|
vpi_register_systf(&tf_data);
|
||||||
|
|
||||||
|
tf_data.tfname = "$scale";
|
||||||
|
tf_data.user_data = "$scale";
|
||||||
|
vpi_register_systf(&tf_data);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -551,8 +551,15 @@ static void scan_item(unsigned depth, vpiHandle item, int skip)
|
||||||
switch (vpi_get(vpiType, item)) {
|
switch (vpi_get(vpiType, item)) {
|
||||||
|
|
||||||
case vpiNet: type = "wire"; if(0){
|
case vpiNet: type = "wire"; if(0){
|
||||||
case vpiIntegerVar:
|
|
||||||
case vpiMemoryWord:
|
case vpiMemoryWord:
|
||||||
|
if (vpi_get(vpiConstantSelect, item) == 0) {
|
||||||
|
/* Turn a non-constant array word select into a
|
||||||
|
* constant word select. */
|
||||||
|
vpiHandle array = vpi_handle(vpiParent, item);
|
||||||
|
PLI_INT32 index = vpi_get(vpiIndex, item);
|
||||||
|
item = vpi_handle_by_index(array, index);
|
||||||
|
}
|
||||||
|
case vpiIntegerVar:
|
||||||
case vpiTimeVar:
|
case vpiTimeVar:
|
||||||
case vpiReg: type = "reg"; }
|
case vpiReg: type = "reg"; }
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -563,8 +563,15 @@ static void scan_item(unsigned depth, vpiHandle item, int skip)
|
||||||
switch (vpi_get(vpiType, item)) {
|
switch (vpi_get(vpiType, item)) {
|
||||||
|
|
||||||
case vpiNet: type = "wire"; if(0){
|
case vpiNet: type = "wire"; if(0){
|
||||||
case vpiIntegerVar:
|
|
||||||
case vpiMemoryWord:
|
case vpiMemoryWord:
|
||||||
|
if (vpi_get(vpiConstantSelect, item) == 0) {
|
||||||
|
/* Turn a non-constant array word select into a
|
||||||
|
* constant word select. */
|
||||||
|
vpiHandle array = vpi_handle(vpiParent, item);
|
||||||
|
PLI_INT32 index = vpi_get(vpiIndex, item);
|
||||||
|
item = vpi_handle_by_index(array, index);
|
||||||
|
}
|
||||||
|
case vpiIntegerVar:
|
||||||
case vpiTimeVar:
|
case vpiTimeVar:
|
||||||
case vpiReg: type = "reg"; }
|
case vpiReg: type = "reg"; }
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,10 @@
|
||||||
# include <stdio.h>
|
# include <stdio.h>
|
||||||
# include <assert.h>
|
# include <assert.h>
|
||||||
# include "sys_readmem_lex.h"
|
# include "sys_readmem_lex.h"
|
||||||
|
# include <sys/stat.h>
|
||||||
|
|
||||||
|
char **search_list = NULL;
|
||||||
|
unsigned sl_count = 0;
|
||||||
|
|
||||||
static void get_mem_params(vpiHandle argv, vpiHandle callh, char *name,
|
static void get_mem_params(vpiHandle argv, vpiHandle callh, char *name,
|
||||||
char **fname, vpiHandle *mitem,
|
char **fname, vpiHandle *mitem,
|
||||||
|
|
@ -291,8 +295,18 @@ static PLI_INT32 sys_readmem_calltf(PLI_BYTE8*name)
|
||||||
&start_addr, &stop_addr, &addr_incr,
|
&start_addr, &stop_addr, &addr_incr,
|
||||||
&min_addr, &max_addr)) return 0;
|
&min_addr, &max_addr)) return 0;
|
||||||
|
|
||||||
/* Open the data file. */
|
/* Open the data file. */
|
||||||
file = fopen(fname, "r");
|
file = fopen(fname, "r");
|
||||||
|
/* Check to see if we have other directories to look for this file. */
|
||||||
|
if (file == 0 && sl_count > 0 && fname[0] != '/') {
|
||||||
|
unsigned idx;
|
||||||
|
char path[4096];
|
||||||
|
|
||||||
|
for (idx = 0; idx < sl_count; idx += 1) {
|
||||||
|
snprintf(path, 4096, "%s/%s", search_list[idx], fname);
|
||||||
|
if ((file = fopen(path, "r"))) break;
|
||||||
|
}
|
||||||
|
}
|
||||||
if (file == 0) {
|
if (file == 0) {
|
||||||
vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, callh),
|
vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, callh),
|
||||||
(int)vpi_get(vpiLineNo, callh));
|
(int)vpi_get(vpiLineNo, callh));
|
||||||
|
|
@ -391,6 +405,102 @@ static PLI_INT32 sys_readmem_calltf(PLI_BYTE8*name)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static PLI_INT32 free_readmempath(p_cb_data cb_data)
|
||||||
|
{
|
||||||
|
unsigned idx;
|
||||||
|
for(idx = 0; idx < sl_count; idx += 1) {
|
||||||
|
free(search_list[idx]);
|
||||||
|
}
|
||||||
|
free(search_list);
|
||||||
|
search_list = NULL;
|
||||||
|
sl_count = 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static PLI_INT32 sys_readmempath_calltf(PLI_BYTE8*name)
|
||||||
|
{
|
||||||
|
vpiHandle callh = vpi_handle(vpiSysTfCall, 0);
|
||||||
|
vpiHandle argv = vpi_iterate(vpiArgument, callh);
|
||||||
|
vpiHandle paths = vpi_scan(argv);
|
||||||
|
s_vpi_value val;
|
||||||
|
unsigned len, idx;
|
||||||
|
char *path;
|
||||||
|
|
||||||
|
vpi_free_object(argv);
|
||||||
|
|
||||||
|
/* Get the search path string. */
|
||||||
|
val.format = vpiStringVal;
|
||||||
|
vpi_get_value(paths, &val);
|
||||||
|
|
||||||
|
/* Verify that we have a string and that it is not NULL. */
|
||||||
|
if (val.format != vpiStringVal || !*(val.value.str)) {
|
||||||
|
vpi_printf("WARNING: %s:%d: ", vpi_get_str(vpiFile, callh),
|
||||||
|
(int)vpi_get(vpiLineNo, callh));
|
||||||
|
vpi_printf("%s's argument (%s) is not a valid string.\n",
|
||||||
|
name, vpi_get_str(vpiType, paths));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Verify that the search path is composed of only printable
|
||||||
|
* characters.
|
||||||
|
*/
|
||||||
|
len = strlen(val.value.str);
|
||||||
|
for (idx = 0; idx < len; idx++) {
|
||||||
|
if (! isprint(val.value.str[idx])) {
|
||||||
|
char msg [64];
|
||||||
|
char *esc_path = as_escaped(val.value.str);
|
||||||
|
snprintf(msg, 64, "WARNING: %s:%d:",
|
||||||
|
vpi_get_str(vpiFile, callh),
|
||||||
|
(int)vpi_get(vpiLineNo, callh));
|
||||||
|
vpi_printf("%s %s's argument contains non-printable "
|
||||||
|
"characters.\n", msg, name);
|
||||||
|
vpi_printf("%*s \"%s\"\n", (int) strlen(msg), " ", esc_path);
|
||||||
|
free(esc_path);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Clear the old list before creating the new list. */
|
||||||
|
free_readmempath(NULL);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Break the string into individual paths and add them to the list.
|
||||||
|
* Print a warning if the path is not valid.
|
||||||
|
*/
|
||||||
|
for (path = strtok(val.value.str, ":"); path; path = strtok(NULL, ":")) {
|
||||||
|
int res;
|
||||||
|
struct stat sb;
|
||||||
|
|
||||||
|
/* Warn the user if the path is not valid. */
|
||||||
|
res = stat(path, &sb);
|
||||||
|
if (res == 0) {
|
||||||
|
if (!S_ISDIR(sb.st_mode)) {
|
||||||
|
vpi_printf("WARNING: %s:%d: ",
|
||||||
|
vpi_get_str(vpiFile, callh),
|
||||||
|
(int)vpi_get(vpiLineNo, callh));
|
||||||
|
vpi_printf("%s's path element \"%s\" is not a "
|
||||||
|
"directory!\n", name, path);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
vpi_printf("WARNING: %s:%d: ", vpi_get_str(vpiFile, callh),
|
||||||
|
(int)vpi_get(vpiLineNo, callh));
|
||||||
|
vpi_printf("%s could not find directory \"%s\"!\n",
|
||||||
|
name, path);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Add a valid search path element to the list. */
|
||||||
|
sl_count += 1;
|
||||||
|
search_list = (char **) realloc(search_list,
|
||||||
|
sizeof(char **)*sl_count);
|
||||||
|
search_list[sl_count-1] = strdup(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static PLI_INT32 sys_writemem_calltf(PLI_BYTE8*name)
|
static PLI_INT32 sys_writemem_calltf(PLI_BYTE8*name)
|
||||||
{
|
{
|
||||||
int addr;
|
int addr;
|
||||||
|
|
@ -455,6 +565,7 @@ static PLI_INT32 sys_writemem_calltf(PLI_BYTE8*name)
|
||||||
void sys_readmem_register()
|
void sys_readmem_register()
|
||||||
{
|
{
|
||||||
s_vpi_systf_data tf_data;
|
s_vpi_systf_data tf_data;
|
||||||
|
s_cb_data cb_data;
|
||||||
|
|
||||||
tf_data.type = vpiSysTask;
|
tf_data.type = vpiSysTask;
|
||||||
tf_data.tfname = "$readmemh";
|
tf_data.tfname = "$readmemh";
|
||||||
|
|
@ -472,6 +583,14 @@ void sys_readmem_register()
|
||||||
tf_data.user_data = "$readmemb";
|
tf_data.user_data = "$readmemb";
|
||||||
vpi_register_systf(&tf_data);
|
vpi_register_systf(&tf_data);
|
||||||
|
|
||||||
|
tf_data.type = vpiSysTask;
|
||||||
|
tf_data.tfname = "$readmempath";
|
||||||
|
tf_data.calltf = sys_readmempath_calltf;
|
||||||
|
tf_data.compiletf = sys_one_string_arg_compiletf;
|
||||||
|
tf_data.sizetf = 0;
|
||||||
|
tf_data.user_data = "$readmempath";
|
||||||
|
vpi_register_systf(&tf_data);
|
||||||
|
|
||||||
tf_data.type = vpiSysTask;
|
tf_data.type = vpiSysTask;
|
||||||
tf_data.tfname = "$writememh";
|
tf_data.tfname = "$writememh";
|
||||||
tf_data.calltf = sys_writemem_calltf;
|
tf_data.calltf = sys_writemem_calltf;
|
||||||
|
|
@ -487,4 +606,10 @@ void sys_readmem_register()
|
||||||
tf_data.sizetf = 0;
|
tf_data.sizetf = 0;
|
||||||
tf_data.user_data = "$writememb";
|
tf_data.user_data = "$writememb";
|
||||||
vpi_register_systf(&tf_data);
|
vpi_register_systf(&tf_data);
|
||||||
|
|
||||||
|
cb_data.reason = cbEndOfSimulation;
|
||||||
|
cb_data.time = 0;
|
||||||
|
cb_data.cb_rtn = free_readmempath;
|
||||||
|
cb_data.user_data = "system";
|
||||||
|
vpi_register_cb(&cb_data);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -519,8 +519,15 @@ static void scan_item(unsigned depth, vpiHandle item, int skip)
|
||||||
switch (vpi_get(vpiType, item)) {
|
switch (vpi_get(vpiType, item)) {
|
||||||
|
|
||||||
case vpiNet: type = "wire"; if(0){
|
case vpiNet: type = "wire"; if(0){
|
||||||
case vpiIntegerVar:
|
|
||||||
case vpiMemoryWord:
|
case vpiMemoryWord:
|
||||||
|
if (vpi_get(vpiConstantSelect, item) == 0) {
|
||||||
|
/* Turn a non-constant array word select into a
|
||||||
|
* constant word select. */
|
||||||
|
vpiHandle array = vpi_handle(vpiParent, item);
|
||||||
|
PLI_INT32 index = vpi_get(vpiIndex, item);
|
||||||
|
item = vpi_handle_by_index(array, index);
|
||||||
|
}
|
||||||
|
case vpiIntegerVar:
|
||||||
case vpiTimeVar:
|
case vpiTimeVar:
|
||||||
case vpiReg: type = "reg"; }
|
case vpiReg: type = "reg"; }
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2003-2008 Stephen Williams (steve@icarus.com)
|
* Copyright (c) 2003-2009 Stephen Williams (steve@icarus.com)
|
||||||
*
|
*
|
||||||
* This source code is free software; you can redistribute it
|
* This source code is free software; you can redistribute it
|
||||||
* and/or modify it in source code form under the terms of the GNU
|
* and/or modify it in source code form under the terms of the GNU
|
||||||
|
|
@ -246,6 +246,16 @@ PLI_INT32 sys_dumpvars_compiletf(PLI_BYTE8 *name)
|
||||||
while ((arg=vpi_scan(argv)) != NULL) {
|
while ((arg=vpi_scan(argv)) != NULL) {
|
||||||
switch(vpi_get(vpiType, arg)) {
|
switch(vpi_get(vpiType, arg)) {
|
||||||
case vpiMemoryWord:
|
case vpiMemoryWord:
|
||||||
|
/*
|
||||||
|
* We need to allow non-constant selects to support the following:
|
||||||
|
*
|
||||||
|
* for (lp = 0; lp < max ; lp = lp + 1) $dumpvars(0, array[lp]);
|
||||||
|
*
|
||||||
|
* We need to do a direct callback on the selected element vs using
|
||||||
|
* the &A<> structure. The later will not give us what we want.
|
||||||
|
* This is implemented in the calltf routine.
|
||||||
|
*/
|
||||||
|
#if 0
|
||||||
if (vpi_get(vpiConstantSelect, arg) == 0) {
|
if (vpi_get(vpiConstantSelect, arg) == 0) {
|
||||||
vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, callh),
|
vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, callh),
|
||||||
(int)vpi_get(vpiLineNo, callh));
|
(int)vpi_get(vpiLineNo, callh));
|
||||||
|
|
@ -253,6 +263,7 @@ PLI_INT32 sys_dumpvars_compiletf(PLI_BYTE8 *name)
|
||||||
vpi_get_str(vpiType, arg));
|
vpi_get_str(vpiType, arg));
|
||||||
vpi_control(vpiFinish, 1);
|
vpi_control(vpiFinish, 1);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
/* The module types. */
|
/* The module types. */
|
||||||
case vpiModule:
|
case vpiModule:
|
||||||
case vpiTask:
|
case vpiTask:
|
||||||
|
|
|
||||||
|
|
@ -675,6 +675,9 @@ static int vpi_array_vthr_A_get(int code, vpiHandle ref)
|
||||||
case vpiRightRange:
|
case vpiRightRange:
|
||||||
return parent->lsb.value;
|
return parent->lsb.value;
|
||||||
|
|
||||||
|
case vpiIndex:
|
||||||
|
return (int)obj->get_address() + parent->first_addr.value;
|
||||||
|
|
||||||
case vpiAutomatic:
|
case vpiAutomatic:
|
||||||
return (int) parent->scope->is_automatic;
|
return (int) parent->scope->is_automatic;
|
||||||
|
|
||||||
|
|
|
||||||
12
vvp/stop.cc
12
vvp/stop.cc
|
|
@ -457,8 +457,13 @@ static void invoke_command(char*txt)
|
||||||
if (argc > 0) {
|
if (argc > 0) {
|
||||||
|
|
||||||
if (argv[0][0] == '$') {
|
if (argv[0][0] == '$') {
|
||||||
cmd_call(argc, argv);
|
if (strcmp(argv[0], "$stop") == 0) {
|
||||||
|
printf("The simulator is already stopped!\n");
|
||||||
|
} else if (strcmp(argv[0], "$finish") == 0){
|
||||||
|
cmd_finish(argc, argv);
|
||||||
|
} else {
|
||||||
|
cmd_call(argc, argv);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
unsigned idx;
|
unsigned idx;
|
||||||
for (idx = 0 ; cmd_table[idx].name ; idx += 1)
|
for (idx = 0 ; cmd_table[idx].name ; idx += 1)
|
||||||
|
|
@ -483,6 +488,9 @@ void stop_handler(int rc)
|
||||||
}
|
}
|
||||||
|
|
||||||
vpi_mcd_printf(1,"** VVP Stop(%d) **\n", rc);
|
vpi_mcd_printf(1,"** VVP Stop(%d) **\n", rc);
|
||||||
|
vpi_mcd_printf(1,"** Flushing output streams.\n");
|
||||||
|
invoke_command("$fflush");
|
||||||
|
invoke_command("$dumpflush");
|
||||||
vpi_mcd_printf(1,"** Current simulation time is %" TIME_FMT_U " ticks.\n",
|
vpi_mcd_printf(1,"** Current simulation time is %" TIME_FMT_U " ticks.\n",
|
||||||
schedule_simtime());
|
schedule_simtime());
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
.TH vvp 1 "November 19th, 2008" "" "Version 0.9.devel"
|
.TH vvp 1 "April 17th, 2009" "" "Version 0.10.devel"
|
||||||
.SH NAME
|
.SH NAME
|
||||||
vvp - Icarus Verilog vvp runtime engine
|
vvp - Icarus Verilog vvp runtime engine
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue