Merge branch 'x-mil4'

Conflicts:
	tgt-vvp/eval_real.c
	vvp/codes.h
	vvp/compile.cc
	vvp/opcodes.txt
This commit is contained in:
Stephen Williams 2012-10-23 14:48:25 -07:00
commit 559d965681
58 changed files with 1623 additions and 622 deletions

View File

@ -108,8 +108,8 @@ O = main.o async.o design_dump.o discipline.o dup_expr.o elaborate.o \
eval_tree.o expr_synth.o functor.o lexor.o lexor_keyword.o link_const.o \
load_module.o netlist.o netmisc.o nettypes.o net_analog.o net_assign.o \
net_design.o netdarray.o \
netenum.o netstruct.o net_event.o net_expr.o net_func.o net_func_eval.o \
net_link.o net_modulo.o \
netenum.o netparray.o netstruct.o netvector.o net_event.o net_expr.o net_func.o \
net_func_eval.o net_link.o net_modulo.o \
net_nex_input.o net_nex_output.o net_proc.o net_scope.o net_tran.o \
net_udp.o pad_to_width.o parse.o parse_misc.o pform.o pform_analog.o \
pform_disciplines.o pform_dump.o pform_package.o pform_pclass.o \

View File

@ -121,6 +121,13 @@ class PExpr : public LineInfo {
// to be propagated down to any context-dependant operands.
void cast_signed(bool flag) { signed_flag_ = flag; }
// This is the more generic form of the elaborate_expr method
// below. The plan is to replace the simpler elaborate_expr
// method with this version, which can handle more advanced
// types. But for now, this is only implemented in special cases.
virtual NetExpr*elaborate_expr(Design*des, NetScope*scope,
ivl_type_t type, unsigned flags) const;
// Procedural elaboration of the expression. The expr_width is
// the required width of the expression.
//
@ -450,6 +457,8 @@ class PENew : public PExpr {
virtual void dump(ostream&) const;
virtual unsigned test_width(Design*des, NetScope*scope,
width_mode_t&mode);
virtual NetExpr*elaborate_expr(Design*des, NetScope*scope,
ivl_type_t type, unsigned flags) const;
virtual NetExpr*elaborate_expr(Design*des, NetScope*,
unsigned expr_wid,
unsigned flags) const;

View File

@ -106,6 +106,7 @@ class PAssign_ : public Statement {
NetAssign_* elaborate_lval(Design*, NetScope*scope) const;
NetExpr* elaborate_rval_(Design*, NetScope*, unsigned lv_width,
ivl_variable_type_t type) const;
NetExpr* elaborate_rval_(Design*, NetScope*, ivl_type_t ntype) const;
NetExpr* elaborate_rval_obj_(Design*, NetScope*,
ivl_variable_type_t type) const;

View File

@ -29,6 +29,7 @@
# include "compiler.h"
# include "discipline.h"
# include "netdarray.h"
# include "netvector.h"
# include "ivl_assert.h"
# include "PExpr.h"
@ -140,6 +141,24 @@ ostream& operator << (ostream&o, ivl_switch_type_t val)
return o;
}
ostream& ivl_type_s::debug_dump(ostream&o) const
{
o << typeid(*this).name();
return o;
}
ostream& netdarray_t::debug_dump(ostream&o) const
{
o << "dynamic array of " << *element_type();
return o;
}
ostream& netvector_t::debug_dump(ostream&o) const
{
o << type_ << (signed_? " signed" : " unsigned") << packed_dims_;
return o;
}
static inline void dump_scope_path(ostream&o, const NetScope*scope)
{
const NetScope*parent = scope->parent();
@ -230,14 +249,9 @@ void NetNet::dump_net(ostream&o, unsigned ind) const
{
o << setw(ind) << "" << type() << ": " << name()
<< unpacked_dims_ << " unpacked dims=" << unpacked_dimensions();
if (!packed_dims_.empty())
o << " packed dims=" << packed_dims_;
o << " pin_count=" << pin_count();
if (local_flag_)
o << " (local)";
o << " " << data_type_;
if (signed_)
o << " signed";
switch (port_type_) {
case NetNet::NOT_A_PORT:
break;
@ -261,14 +275,7 @@ void NetNet::dump_net(ostream&o, unsigned ind) const
if (ivl_discipline_t dis = get_discipline())
o << " discipline=" << dis->name();
if (netdarray_t*darray = darray_type())
o << " dynamic array of " << darray->data_type();
if (! packed_dims_.empty())
o << " packed dims: " << packed_dims_;
if (net_type_)
o << " net_type_=" << typeid(*net_type_).name();
if (net_type_) o << " " << *net_type_;
o << " (eref=" << peek_eref() << ", lref=" << peek_lref() << ")";
if (scope())
@ -1098,7 +1105,7 @@ void NetFuncDef::dump(ostream&o, unsigned ind) const
if (result_sig_) {
o << setw(ind+2) << "" << "Return signal: ";
if (result_sig_->get_signed()) o << "+";
o << result_sig_->name() << result_sig_->packed_dims() << endl;
o << result_sig_->name() << endl;
}
o << setw(ind+2) << "" << "Arguments: ";
if (port_count() == 0) o << "<none>";
@ -1120,7 +1127,7 @@ void NetFuncDef::dump(ostream&o, unsigned ind) const
break;
}
if (port(idx)->get_signed()) o << "+";
o << port(idx)->name() << port(idx)->packed_dims() << endl;
o << port(idx)->name() << endl;
}
if (statement_)
statement_->dump(o, ind+2);
@ -1520,7 +1527,14 @@ void NetESelect::dump(ostream&o) const
else
o << "(0)";
o << "+:" << expr_width() << "]>";
o << "+:" << expr_width() << "]";
if (ivl_type_t nt = net_type()) {
o << " net_type=(" << *nt << ")";
} else {
o << " expr_type=" << expr_type();
}
o << ">";
}
void NetESFunc::dump(ostream&o) const
@ -1539,7 +1553,8 @@ void NetESignal::dump(ostream&o) const
o << "+";
o << name();
if (word_) o << "[word=" << *word_ << "]";
o << sig()->packed_dims();
vector<netrange_t>tmp = net_->net_type()->slice_dimensions();
o << tmp;
}
void NetETernary::dump(ostream&o) const

View File

@ -27,6 +27,7 @@
# include "pform.h"
# include "netlist.h"
# include "netenum.h"
# include "netvector.h"
# include "discipline.h"
# include "netmisc.h"
# include "netdarray.h"
@ -130,6 +131,17 @@ unsigned PExpr::test_width(Design*des, NetScope*, width_mode_t&)
return 1;
}
NetExpr* PExpr::elaborate_expr(Design*des, NetScope*, ivl_type_t, unsigned) const
{
cerr << get_fileline() << ": internal error: I do not know how to"
<< " elaborate (ivl_type_t) this expression. " << endl;
cerr << get_fileline() << ": : Expression is: " << *this
<< endl;
des->errors += 1;
return 0;
}
NetExpr* PExpr::elaborate_expr(Design*des, NetScope*, unsigned, unsigned) const
{
cerr << get_fileline() << ": internal error: I do not know how to"
@ -1480,7 +1492,7 @@ static const netstruct_t::member_t*get_struct_member(const LineInfo*li,
perm_string method_name,
unsigned long&off)
{
netstruct_t*type = net->struct_type();
const netstruct_t*type = net->struct_type();
ivl_assert(*li, type);
if (! type->packed()) {
@ -2354,8 +2366,8 @@ unsigned PEIdent::test_width(Design*des, NetScope*scope, width_mode_t&mode)
if (netdarray_t*darray = net? net->darray_type() : 0) {
if (use_sel == index_component_t::SEL_BIT) {
expr_type_ = darray->data_type();
expr_width_ = darray->vector_width();
expr_type_ = darray->element_base_type();
expr_width_ = darray->element_width();
min_width_ = expr_width_;
signed_flag_ = net->get_signed();
} else {
@ -2382,6 +2394,10 @@ unsigned PEIdent::test_width(Design*des, NetScope*scope, width_mode_t&mode)
expr_width_ = net->vector_width();
min_width_ = expr_width_;
signed_flag_ = net->get_signed();
if (debug_elaborate) {
cerr << get_fileline() << ": PEIdent::test_width: "
<< net->name() << " is a net, width=" << expr_width_ << endl;
}
return expr_width_;
}
@ -3550,7 +3566,7 @@ NetExpr* PEIdent::elaborate_expr_net_idx_up_(Design*des, NetScope*scope,
long lsv = base_c->value().as_long();
long offset = 0;
// Get the signal range.
const list<netrange_t>&packed = net->sig()->packed_dims();
const vector<netrange_t>&packed = net->sig()->packed_dims();
ivl_assert(*this, packed.size() == prefix_indices.size()+1);
// We want the last range, which is where we work.
@ -3744,7 +3760,7 @@ NetExpr* PEIdent::elaborate_expr_net_bit_(Design*des, NetScope*scope,
cerr << get_fileline() << ": debug: "
<< "Bit select of a dynamic array becomes NetESelect." << endl;
}
NetESelect*res = new NetESelect(net, mux, darray->vector_width());
NetESelect*res = new NetESelect(net, mux, darray->element_width());
res->set_line(*net);
return res;
}
@ -3779,7 +3795,7 @@ NetExpr* PEIdent::elaborate_expr_net_bit_(Design*des, NetScope*scope,
long msv = msc->value().as_long();
const list<netrange_t>& sig_packed = net->sig()->packed_dims();
const vector<netrange_t>& sig_packed = net->sig()->packed_dims();
if (prefix_indices.size()+2 <= sig_packed.size()) {
// Special case: this is a slice of a multi-dimensional
// packed array. For example:
@ -3872,7 +3888,7 @@ NetExpr* PEIdent::elaborate_expr_net_bit_(Design*des, NetScope*scope,
return res;
}
const list<netrange_t>& sig_packed = net->sig()->packed_dims();
const vector<netrange_t>& sig_packed = net->sig()->packed_dims();
if (prefix_indices.size()+2 <= sig_packed.size()) {
// Special case: this is a slice of a multi-dimensional
// packed array. For example:
@ -3965,7 +3981,7 @@ NetExpr* PEIdent::elaborate_expr_net(Design*des, NetScope*scope,
return node;
}
unsigned PENew::test_width(Design*des, NetScope*, width_mode_t&)
unsigned PENew::test_width(Design*, NetScope*, width_mode_t&)
{
expr_type_ = IVL_VT_DARRAY;
expr_width_ = 1;
@ -3974,6 +3990,23 @@ unsigned PENew::test_width(Design*des, NetScope*, width_mode_t&)
return 1;
}
NetExpr* PENew::elaborate_expr(Design*des, NetScope*scope,
ivl_type_t ntype, unsigned flags) const
{
// Elaborate the size expression.
width_mode_t mode = LOSSLESS;
unsigned use_wid = size_->test_width(des, scope, mode);
NetExpr*size = size_->elaborate_expr(des, scope, use_wid, flags);
NetESFunc*tmp = new NetESFunc("$ivl_darray_method$new", ntype, 1);
tmp->set_line(*this);
tmp->parm(0, size);
return tmp;
}
/*
* This method should never actually be called.
*/
NetExpr* PENew::elaborate_expr(Design*des, NetScope*scope,
unsigned, unsigned flags) const
{
@ -4503,9 +4536,9 @@ NetNet* Design::find_discipline_reference(ivl_discipline_t dis, NetScope*scope)
if (gnd) return gnd;
string name = string(dis->name()) + "$gnd";
gnd = new NetNet(scope, lex_strings.make(name), NetNet::WIRE, 1);
netvector_t*gnd_vec = new netvector_t(IVL_VT_REAL,0,0);
gnd = new NetNet(scope, lex_strings.make(name), NetNet::WIRE, gnd_vec);
gnd->set_discipline(dis);
gnd->data_type(IVL_VT_REAL);
discipline_references_[dis->name()] = gnd;
if (debug_elaborate)

View File

@ -507,7 +507,7 @@ bool PEIdent::elaborate_lval_net_part_(Design*des,
NetNet*reg = lv->sig();
ivl_assert(*this, reg);
const list<netrange_t>&packed = reg->packed_dims();
const vector<netrange_t>&packed = reg->packed_dims();
// Part selects cannot select slices. So there must be enough
// prefix_indices to get all the way to the final dimension.
@ -596,7 +596,7 @@ bool PEIdent::elaborate_lval_net_idx_(Design*des,
long lsv = base_c->value().as_long();
long offset = 0;
// Get the signal range.
const list<netrange_t>&packed = reg->packed_dims();
const vector<netrange_t>&packed = reg->packed_dims();
ivl_assert(*this, packed.size() == prefix_indices.size()+1);
// We want the last range, which is where we work.
@ -680,7 +680,7 @@ bool PEIdent::elaborate_lval_net_packed_member_(Design*des, NetScope*scope,
NetNet*reg = lv->sig();
ivl_assert(*this, reg);
netstruct_t*struct_type = reg->struct_type();
const netstruct_t*struct_type = reg->struct_type();
ivl_assert(*this, struct_type);
if (debug_elaborate) {

View File

@ -24,6 +24,7 @@
# include "netlist.h"
# include "netmisc.h"
# include "netstruct.h"
# include "netvector.h"
# include "compiler.h"
# include <cstdlib>
@ -98,12 +99,12 @@ NetNet* PEConcat::elaborate_lnet_common_(Design*des, NetScope*scope,
concat operator from most significant to least significant,
which is the order they are given in the concat list. */
netvector_t*tmp2_vec = new netvector_t(nets[0]->data_type(),width-1,0);
NetNet*osig = new NetNet(scope, scope->local_symbol(),
NetNet::IMPLICIT, width);
NetNet::IMPLICIT, tmp2_vec);
/* Assume that the data types of the nets are all the same, so
we can take the data type of any, the first will do. */
osig->data_type(nets[0]->data_type());
osig->local_flag(true);
osig->set_line(*this);
@ -154,8 +155,6 @@ NetNet* PEConcat::elaborate_lnet_common_(Design*des, NetScope*scope,
assert(width == 0);
}
osig->data_type(nets[0]->data_type());
osig->local_flag(true);
return osig;
}
@ -431,11 +430,18 @@ NetNet* PEIdent::elaborate_lnet_common_(Design*des, NetScope*scope,
remove the member and store it into method_name, and retry
the search with "a.b". */
if (sig == 0 && path_.size() >= 2) {
if (debug_elaborate) {
cerr << get_fileline() << ": PEIdent::elaborate_lnet_common_: "
"Symbol not found, try again with path_prefix=" << path_prefix
<< " and method_name=" << path_tail.name << endl;
}
method_name = path_tail.name;
symbol_search(this, des, scope, path_prefix, sig, par, eve);
// Whoops, not a struct signal, so give up on this avenue.
if (sig && sig->struct_type() == 0) {
cerr << get_fileline() << ": XXXXX: sig=" << sig->name()
<< " is found, but not a struct with member " << method_name << endl;
method_name = perm_string();
sig = 0;
}
@ -475,7 +481,7 @@ NetNet* PEIdent::elaborate_lnet_common_(Design*des, NetScope*scope,
list<long> unpacked_indices_const;
netstruct_t*struct_type = 0;
const netstruct_t*struct_type = 0;
if ((struct_type = sig->struct_type()) && !method_name.nil()) {
// Detect the variable is a structure and there was a
@ -655,11 +661,12 @@ NetNet* PEIdent::elaborate_lnet_common_(Design*des, NetScope*scope,
return 0;
}
netvector_t*tmp2_vec = new netvector_t(sig->data_type(),
sig->vector_width()-1,0);
NetNet*tmp = new NetNet(scope, scope->local_symbol(),
sig->type(), sig->vector_width());
sig->type(), tmp2_vec);
tmp->set_line(*this);
tmp->local_flag(true);
tmp->data_type( sig->data_type() );
connect(sig->pin(widx), tmp->pin(0));
sig = tmp;
}
@ -683,10 +690,11 @@ NetNet* PEIdent::elaborate_lnet_common_(Design*des, NetScope*scope,
<< " wid=" << subnet_wid <<"]"
<< endl;
netvector_t*tmp2_vec = new netvector_t(sig->data_type(),
subnet_wid-1,0);
NetNet*subsig = new NetNet(sig->scope(),
sig->scope()->local_symbol(),
NetNet::WIRE, subnet_wid);
subsig->data_type( sig->data_type() );
NetNet::WIRE, tmp2_vec);
subsig->local_flag(true);
subsig->set_line(*this);
@ -800,10 +808,10 @@ NetNet* PEIdent::elaborate_subport(Design*des, NetScope*scope) const
unsigned swid = abs(midx - lidx) + 1;
ivl_assert(*this, swid > 0 && swid < sig->vector_width());
netvector_t*tmp2_vec = new netvector_t(sig->data_type(),swid-1,0);
NetNet*tmp = new NetNet(scope, scope->local_symbol(),
NetNet::WIRE, swid);
NetNet::WIRE, tmp2_vec);
tmp->port_type(sig->port_type());
tmp->data_type(sig->data_type());
tmp->set_line(*this);
tmp->local_flag(true);
NetNode*ps = 0;

View File

@ -36,6 +36,7 @@
# include "netmisc.h"
# include "netenum.h"
# include "netstruct.h"
# include "netvector.h"
# include "netdarray.h"
# include "netparray.h"
# include "util.h"
@ -485,6 +486,7 @@ void PFunction::elaborate_sig(Design*des, NetScope*scope) const
}
NetNet*ret_sig = 0;
netvector_t*ret_vec = 0;
/* Create the signals/variables of the return value and write
them into the function scope. */
@ -520,50 +522,51 @@ void PFunction::elaborate_sig(Design*des, NetScope*scope) const
des->errors += 1;
}
list<netrange_t> packed;
vector<netrange_t> packed;
packed.push_back(netrange_t(mnum, lnum));
ret_sig = new NetNet(scope, fname, NetNet::REG, packed);
ret_sig->set_scalar(false);
ret_vec = new netvector_t(packed, IVL_VT_LOGIC);
ret_vec->set_signed(return_type_.type == PTF_REG_S);
ret_vec->set_scalar(false);
ret_sig = new NetNet(scope, fname, NetNet::REG, ret_vec);
} else {
ret_sig = new NetNet(scope, fname, NetNet::REG);
ret_sig->set_scalar(true);
ret_vec = new netvector_t(IVL_VT_LOGIC);
ret_vec->set_signed(return_type_.type == PTF_REG_S);
ret_vec->set_scalar(true);
ret_sig = new NetNet(scope, fname, NetNet::REG, ret_vec);
}
ret_sig->set_line(*this);
ret_sig->set_signed(return_type_.type == PTF_REG_S);
ret_sig->port_type(NetNet::POUTPUT);
ret_sig->data_type(IVL_VT_LOGIC);
break;
case PTF_INTEGER:
ret_sig = new NetNet(scope, fname, NetNet::REG, integer_width);
ret_vec = new netvector_t(IVL_VT_LOGIC, integer_width-1,0);
ret_vec->set_signed(true);
ret_vec->set_isint(true);
ret_vec->set_scalar(false);
ret_sig = new NetNet(scope, fname, NetNet::REG, ret_vec);
ret_sig->set_line(*this);
ret_sig->set_signed(true);
ret_sig->set_isint(true);
ret_sig->set_scalar(false);
ret_sig->port_type(NetNet::POUTPUT);
ret_sig->data_type(IVL_VT_LOGIC);
break;
case PTF_TIME:
ret_sig = new NetNet(scope, fname, NetNet::REG, 64);
ret_vec = new netvector_t(IVL_VT_LOGIC, 64-1,0);
ret_vec->set_isint(false);
ret_vec->set_scalar(false);
ret_sig = new NetNet(scope, fname, NetNet::REG, ret_vec);
ret_sig->set_line(*this);
ret_sig->set_signed(false);
ret_sig->set_isint(false);
ret_sig->set_scalar(false);
ret_sig->port_type(NetNet::POUTPUT);
ret_sig->data_type(IVL_VT_LOGIC);
break;
case PTF_REAL:
case PTF_REALTIME:
ret_sig = new NetNet(scope, fname, NetNet::REG, 1);
ret_vec = new netvector_t(IVL_VT_REAL);
ret_vec->set_signed(true);
ret_vec->set_isint(false);
ret_vec->set_scalar(true);
ret_sig = new NetNet(scope, fname, NetNet::REG, ret_vec);
ret_sig->set_line(*this);
ret_sig->set_signed(true);
ret_sig->set_isint(false);
ret_sig->set_scalar(true);
ret_sig->port_type(NetNet::POUTPUT);
ret_sig->data_type(IVL_VT_REAL);
break;
case PTF_ATOM2:
@ -598,13 +601,13 @@ void PFunction::elaborate_sig(Design*des, NetScope*scope) const
use_wid = mnum - lnum + 1;
}
ret_sig = new NetNet(scope, fname, NetNet::REG, use_wid);
ret_vec = new netvector_t(IVL_VT_BOOL, use_wid-1, 0);
ret_vec->set_isint(true);
ret_vec->set_scalar(false);
ret_vec->set_signed(return_type_.type == PTF_ATOM2_S? true : false);
ret_sig = new NetNet(scope, fname, NetNet::REG, ret_vec);
ret_sig->set_line(*this);
ret_sig->set_signed(return_type_.type == PTF_ATOM2_S? true : false);
ret_sig->set_isint(true);
ret_sig->set_scalar(false);
ret_sig->port_type(NetNet::POUTPUT);
ret_sig->data_type(IVL_VT_BOOL);
break;
case PTF_STRING:
@ -820,7 +823,7 @@ void PWhile::elaborate_sig(Design*des, NetScope*scope) const
}
static bool evaluate_ranges(Design*des, NetScope*scope,
list<netrange_t>&llist,
vector<netrange_t>&llist,
const list<pform_range_t>&rlist)
{
bool bad_msb = false, bad_lsb = false;
@ -871,7 +874,7 @@ static netstruct_t* elaborate_struct_type(Design*des, NetScope*scope,
for (list<struct_member_t*>::iterator cur = struct_type->members->begin()
; cur != struct_type->members->end() ; ++ cur) {
list<netrange_t>packed_dimensions;
vector<netrange_t>packed_dimensions;
struct_member_t*curp = *cur;
if (curp->range.get() && ! curp->range->empty()) {
@ -897,22 +900,8 @@ static netstruct_t* elaborate_struct_type(Design*des, NetScope*scope,
return res;
}
static netparray_t* elaborate_parray_type(Design*des, NetScope*scope,
parray_type_t*data_type)
{
list<netrange_t>packed_dimensions;
bool bad_range = evaluate_ranges(des, scope, packed_dimensions, * data_type->packed_dims);
ivl_assert(*data_type, !bad_range);
netparray_t*res = new netparray_t(packed_dimensions);
//res->set_line(*data_type);
return res;
}
static nettype_base_t*elaborate_type(Design*des, NetScope*scope,
data_type_t*pform_type)
static ivl_type_s*elaborate_type(Design*des, NetScope*scope,
data_type_t*pform_type)
{
if (struct_type_t*struct_type = dynamic_cast<struct_type_t*>(pform_type)) {
netstruct_t*use_type = elaborate_struct_type(des, scope, struct_type);
@ -926,13 +915,29 @@ static nettype_base_t*elaborate_type(Design*des, NetScope*scope,
return 0;
}
bool test_ranges_eeq(const list<netrange_t>&lef, const list<netrange_t>&rig)
static netparray_t* elaborate_parray_type(Design*des, NetScope*scope,
parray_type_t*data_type)
{
vector<netrange_t>packed_dimensions;
bool bad_range = evaluate_ranges(des, scope, packed_dimensions, * data_type->packed_dims);
ivl_assert(*data_type, !bad_range);
ivl_type_s*element_type = elaborate_type(des, scope, data_type->base_type);
netparray_t*res = new netparray_t(packed_dimensions, element_type);
//res->set_line(*data_type);
return res;
}
bool test_ranges_eeq(const vector<netrange_t>&lef, const vector<netrange_t>&rig)
{
if (lef.size() != rig.size())
return false;
list<netrange_t>::const_iterator lcur = lef.begin();
list<netrange_t>::const_iterator rcur = rig.begin();
vector<netrange_t>::const_iterator lcur = lef.begin();
vector<netrange_t>::const_iterator rcur = rig.begin();
while (lcur != lef.end()) {
if (lcur->get_msb() != rcur->get_msb())
return false;
@ -967,7 +972,7 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
}
unsigned wid = 1;
list<netrange_t>packed_dimensions;
vector<netrange_t>packed_dimensions;
des->errors += error_cnt_;
@ -1008,7 +1013,7 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
if (port_set_ || net_set_) {
bool bad_range = false;
list<netrange_t> plist, nlist;
vector<netrange_t> plist, nlist;
/* If they exist get the port definition MSB and LSB */
if (port_set_ && !port_.empty()) {
bad_range |= evaluate_ranges(des, scope, plist, port_);
@ -1095,9 +1100,10 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
// dimensions, then turn this into a dynamic array and
// put all the packed dimensions there.
if (use_lidx==0 && use_ridx==0) {
ivl_assert(*this, netarray==0);
netarray = new netdarray_t(packed_dimensions, data_type_, wid);
netvector_t*vec = new netvector_t(packed_dimensions, data_type_);
packed_dimensions.clear();
ivl_assert(*this, netarray==0);
netarray = new netdarray_t(vec);
continue;
}
@ -1218,7 +1224,8 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
<< " and packed_width=" << use_enum->packed_width() << endl;
}
sig = new NetNet(scope, name_, wtype, packed_dimensions, unpacked_dimensions, use_enum);
ivl_assert(*this, packed_dimensions.empty());
sig = new NetNet(scope, name_, wtype, unpacked_dimensions, use_enum);
} else if (netarray) {
@ -1252,14 +1259,7 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
<< " in scope " << scope_path(scope) << endl;
}
nettype_base_t*base_type = elaborate_type(des, scope, parray_type->base_type);
#if 0
cerr << get_fileline() << ": sorry: Packed array of "
<< typeid(*parray_type->base_type).name()
<< " not supported." << endl;
des->errors += 1;
#endif
sig = new NetNet(scope, name_, wtype, use_type->packed_dimensions(), unpacked_dimensions, base_type);
sig = new NetNet(scope, name_, wtype, unpacked_dimensions, use_type);
} else {
@ -1272,29 +1272,30 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
cerr << " in scope " << scope_path(scope) << endl;
}
sig = new NetNet(scope, name_, wtype, packed_dimensions, unpacked_dimensions);
ivl_variable_type_t use_data_type = data_type_;
if (use_data_type == IVL_VT_NO_TYPE) {
use_data_type = IVL_VT_LOGIC;
if (debug_elaborate) {
cerr << get_fileline() << ": debug: "
<< "Signal " << name_
<< " in scope " << scope_path(scope)
<< " defaults to data type " << use_data_type << endl;
}
}
netvector_t*vec = new netvector_t(packed_dimensions, use_data_type);
vec->set_signed(get_signed());
vec->set_isint(get_isint());
if (is_implicit_scalar) vec->set_scalar(true);
else vec->set_scalar(get_scalar());
packed_dimensions.clear();
sig = new NetNet(scope, name_, wtype, unpacked_dimensions, vec);
}
if (wtype == NetNet::WIRE) sig->devirtualize_pins();
ivl_variable_type_t use_data_type = data_type_;
if (use_data_type == IVL_VT_NO_TYPE) {
use_data_type = IVL_VT_LOGIC;
if (debug_elaborate) {
cerr << get_fileline() << ": debug: "
<< "Signal " << name_
<< " in scope " << scope_path(scope)
<< " defaults to data type " << use_data_type << endl;
}
}
sig->data_type(use_data_type);
sig->set_line(*this);
sig->port_type(port_type_);
sig->set_signed(get_signed());
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()) {
sig->set_discipline(dis);

View File

@ -35,6 +35,7 @@
# include "PGenerate.h"
# include "PSpec.h"
# include "netlist.h"
# include "netvector.h"
# include "netmisc.h"
# include "util.h"
# include "parse_api.h"
@ -75,8 +76,7 @@ void PGAssign::elaborate(Design*des, NetScope*scope) const
if (debug_elaborate) {
cerr << get_fileline() << ": debug: PGAssign: elaborated l-value"
<< " width=" << lval->vector_width()
<< ", type=" << lval->data_type() << endl;
<< " width=" << lval->vector_width() << endl;
}
NetExpr*rval_expr = elaborate_rval_expr(des, scope, lval->data_type(),
@ -115,7 +115,6 @@ void PGAssign::elaborate(Design*des, NetScope*scope) const
cerr << get_fileline() << ": debug: PGAssign: elaborated r-value"
<< " width="<< rval->vector_width()
<< ", type="<< rval->data_type()
<< ", signed="<< rval->get_signed()
<< ", expr=" << *rval_expr << endl;
}
@ -164,11 +163,12 @@ void PGAssign::elaborate(Design*des, NetScope*scope) const
NetPartSelect::VP);
des->add_node(tmp);
tmp->set_line(*this);
netvector_t*osig_vec = new netvector_t(rval->data_type(),
lval->vector_width()-1,0);
NetNet*osig = new NetNet(scope, scope->local_symbol(),
NetNet::TRI, lval->vector_width());
NetNet::TRI, osig_vec);
osig->set_line(*this);
osig->local_flag(true);
osig->data_type(rval->data_type());
connect(osig->pin(0), tmp->pin(0));
rval = osig;
need_driver_flag = false;
@ -190,10 +190,11 @@ void PGAssign::elaborate(Design*des, NetScope*scope) const
connect(rval->pin(0), driver->pin(1));
netvector_t*tmp_vec = new netvector_t(rval->data_type(),
rval->vector_width()-1,0);
NetNet*tmp = new NetNet(scope, scope->local_symbol(),
NetNet::WIRE, rval->vector_width());
NetNet::WIRE, tmp_vec);
tmp->set_line(*this);
tmp->data_type(rval->data_type());
tmp->local_flag(true);
connect(driver->pin(0), tmp->pin(0));
@ -868,10 +869,11 @@ void PGBuiltin::elaborate(Design*des, NetScope*scope) const
des->add_node(rep);
connect(rep->pin(1), sig->pin(0));
netvector_t*osig_vec = new netvector_t(IVL_VT_LOGIC,
instance_width-1,0);
sig = new NetNet(scope, scope->local_symbol(),
NetNet::WIRE, instance_width);
NetNet::WIRE, osig_vec);
sig->set_line(*this);
sig->data_type(IVL_VT_LOGIC);
sig->local_flag(true);
connect(rep->pin(0), sig->pin(0));
@ -948,12 +950,12 @@ void PGBuiltin::elaborate(Design*des, NetScope*scope) const
unsigned dev = gdx*gate_count;
connect(cur[dev+idx]->pin(0), cc->pin(gdx+1));
netvector_t*tmp2_vec = new netvector_t(IVL_VT_LOGIC);
NetNet*tmp2 = new NetNet(scope,
scope->local_symbol(),
NetNet::WIRE, 1);
NetNet::WIRE, tmp2_vec);
tmp2->set_line(*this);
tmp2->local_flag(true);
tmp2->data_type(IVL_VT_LOGIC);
connect(cc->pin(gdx+1), tmp2->pin(0));
}
@ -965,11 +967,11 @@ void PGBuiltin::elaborate(Design*des, NetScope*scope) const
tmp1->set_line(*this);
des->add_node(tmp1);
connect(tmp1->pin(1), sig->pin(0));
netvector_t*tmp2_vec = new netvector_t(sig->data_type());
NetNet*tmp2 = new NetNet(scope, scope->local_symbol(),
NetNet::WIRE, 1);
NetNet::WIRE, tmp2_vec);
tmp2->set_line(*this);
tmp2->local_flag(true);
tmp2->data_type(sig->data_type());
connect(tmp1->pin(0), tmp2->pin(0));
unsigned use_idx = idx - gate_count + 1;
unsigned dev = gdx*gate_count;
@ -996,8 +998,9 @@ NetNet*PGModule::resize_net_to_port_(Design*des, NetScope*scope,
ivl_assert(*this, dir != NetNet::NOT_A_PORT);
ivl_assert(*this, dir != NetNet::PIMPLICIT);
netvector_t*tmp_type = new netvector_t(IVL_VT_LOGIC, port_wid-1, 0);
NetNet*tmp = new NetNet(scope, scope->local_symbol(),
NetNet::WIRE, port_wid);
NetNet::WIRE, tmp_type);
tmp->local_flag(true);
tmp->set_line(*this);
@ -1415,6 +1418,12 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const
<< "too complicated for elaboration." << endl;
continue;
}
if (debug_elaborate) {
cerr << get_fileline() << ": debug: "
<< "Elaborating INPUT port expression: " << *tmp_expr << endl;
}
sig = tmp_expr->synthesize(des, scope, tmp_expr);
if (sig == 0) {
cerr << pins[idx]->get_fileline()
@ -1432,11 +1441,12 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const
des->add_node(tmp);
connect(tmp->pin(1), sig->pin(0));
netvector_t*tmp2_vec = new netvector_t(sig->data_type(),
sig->vector_width()-1,0);
NetNet*tmp2 = new NetNet(scope, scope->local_symbol(),
NetNet::WIRE, sig->vector_width());
NetNet::WIRE, tmp2_vec);
tmp2->local_flag(true);
tmp2->set_line(*this);
tmp2->data_type(sig->data_type());
connect(tmp->pin(0), tmp2->pin(0));
sig = tmp2;
}
@ -2184,6 +2194,17 @@ NetAssign_* PAssign_::elaborate_lval(Design*des, NetScope*scope) const
return lval_->elaborate_lval(des, scope, false);
}
NetExpr* PAssign_::elaborate_rval_(Design*des, NetScope*scope,
ivl_type_t net_type) const
{
ivl_assert(*this, rval_);
NetExpr*rv = rval_->elaborate_expr(des, scope, net_type, 0);
ivl_assert(*this, !is_constant_);
return rv;
}
NetExpr* PAssign_::elaborate_rval_(Design*des, NetScope*scope,
unsigned lv_width,
ivl_variable_type_t lv_type) const
@ -2355,9 +2376,20 @@ NetProc* PAssign::elaborate(Design*des, NetScope*scope) const
if (delay_ != 0)
delay = elaborate_delay_expr(delay_, des, scope);
NetExpr*rv;
if (lv->more==0 && dynamic_cast<const PENew*> (rval())) {
/* Special case: The l-value is a single signal, and the
r-value expression is a "new" expression. The l-value
has a new form of type, and the PENew expression
requires the extra information that it contains. So
handle it with this code instead. */
rv = elaborate_rval_(des, scope, lv->sig()->net_type());
} else {
/* Elaborate the r-value expression, then try to evaluate it. */
rv = elaborate_rval_(des, scope, count_lval_width(lv), lv->expr_type());
}
/* Elaborate the r-value expression, then try to evaluate it. */
NetExpr*rv = elaborate_rval_(des, scope, count_lval_width(lv), lv->expr_type());
if (rv == 0) return 0;
assert(rv);
@ -2382,11 +2414,11 @@ NetProc* PAssign::elaborate(Design*des, NetScope*scope) const
if (delay || event_) {
unsigned wid = count_lval_width(lv);
netvector_t*tmp2_vec = new netvector_t(rv->expr_type(),wid-1,0);
NetNet*tmp = new NetNet(scope, scope->local_symbol(),
NetNet::REG, wid);
NetNet::REG, tmp2_vec);
tmp->local_flag(true);
tmp->set_line(*this);
tmp->data_type(rv->expr_type());
NetESignal*sig = new NetESignal(tmp);
@ -2477,10 +2509,17 @@ NetProc* PAssign::elaborate(Design*des, NetScope*scope) const
if (lv->expr_type() == IVL_VT_BOOL && rv->expr_type() != IVL_VT_BOOL) {
if (debug_elaborate)
cerr << get_fileline() << ": debug: Cast expression to int2" << endl;
cerr << get_fileline() << ": debug: "
<< "Cast expression to int2" << endl;
rv = cast_to_int2(rv);
}
if (lv->expr_type() == IVL_VT_REAL && rv->expr_type() != IVL_VT_REAL) {
if (debug_elaborate)
cerr << get_fileline() << ": debug: "
<< "Cast expression to real." << endl;
rv = cast_to_real(rv);
}
if (lv->enumeration() && (lv->enumeration() != rv->enumeration())) {
cerr << get_fileline() << ": error: "
<< "Enumeration type mismatch in assignment." << endl;

View File

@ -53,6 +53,9 @@ static bool get_real_arg_(const NetExpr*expr, verireal&val)
break;
}
case IVL_VT_DARRAY:
return false;
default:
assert(0);
}

View File

@ -24,6 +24,7 @@
# include <iostream>
# include "netlist.h"
# include "netvector.h"
# include "netmisc.h"
# include "ivl_assert.h"
@ -118,11 +119,11 @@ NetNet* NetEBAdd::synthesize(Design*des, NetScope*scope, NetExpr*root)
}
perm_string path = lsig->scope()->local_symbol();
NetNet*osig = new NetNet(lsig->scope(), path, NetNet::IMPLICIT, width);
netvector_t*osig_vec = new netvector_t(expr_type(), width-1, 0);
osig_vec->set_signed(has_sign());
NetNet*osig = new NetNet(lsig->scope(), path, NetNet::IMPLICIT, osig_vec);
osig->set_line(*this);
osig->local_flag(true);
osig->data_type(expr_type());
osig->set_signed(has_sign());
perm_string oname = osig->scope()->local_symbol();
NetAddSub *adder = new NetAddSub(lsig->scope(), oname, width);
@ -173,11 +174,11 @@ NetNet* NetEBBits::synthesize(Design*des, NetScope*scope, NetExpr*root)
rsig = pad_to_width(des, rsig, width, *this);
assert(lsig->vector_width() == rsig->vector_width());
netvector_t*osig_vec = new netvector_t(expr_type(), width-1, 0);
NetNet*osig = new NetNet(scope, scope->local_symbol(),
NetNet::IMPLICIT, width);
NetNet::IMPLICIT, osig_vec);
osig->set_line(*this);
osig->local_flag(true);
osig->data_type(expr_type());
perm_string oname = scope->local_symbol();
NetLogic*gate;
@ -243,11 +244,11 @@ NetNet* NetEBComp::synthesize(Design*des, NetScope*scope, NetExpr*root)
rsig = pad_to_width(des, rsig, width, *this);
}
netvector_t*osig_vec = new netvector_t(IVL_VT_LOGIC);
NetNet*osig = new NetNet(scope, scope->local_symbol(),
NetNet::IMPLICIT, 1);
NetNet::IMPLICIT, osig_vec);
osig->set_line(*this);
osig->local_flag(true);
osig->data_type(IVL_VT_LOGIC);
// Test if the comparison is signed.
//
@ -390,11 +391,11 @@ NetNet* NetEBPow::synthesize(Design*des, NetScope*scope, NetExpr*root)
connect(powr->pin_DataA(), lsig->pin(0));
connect(powr->pin_DataB(), rsig->pin(0));
netvector_t*osig_vec = new netvector_t(expr_type(), width-1, 0);
osig_vec->set_signed(has_sign());
NetNet*osig = new NetNet(scope, scope->local_symbol(),
NetNet::IMPLICIT, width);
NetNet::IMPLICIT, osig_vec);
osig->set_line(*this);
osig->data_type(expr_type());
osig->set_signed(has_sign());
osig->local_flag(true);
connect(powr->pin_Result(), osig->pin(0));
@ -427,11 +428,11 @@ NetNet* NetEBMult::synthesize(Design*des, NetScope*scope, NetExpr*root)
connect(mult->pin_DataA(), lsig->pin(0));
connect(mult->pin_DataB(), rsig->pin(0));
netvector_t*osig_vec = new netvector_t(expr_type(), width-1, 0);
osig_vec->set_signed(has_sign());
NetNet*osig = new NetNet(scope, scope->local_symbol(),
NetNet::IMPLICIT, width);
NetNet::IMPLICIT, osig_vec);
osig->set_line(*this);
osig->data_type(expr_type());
osig->set_signed(has_sign());
osig->local_flag(true);
connect(mult->pin_Result(), osig->pin(0));
@ -452,11 +453,11 @@ NetNet* NetEBDiv::synthesize(Design*des, NetScope*scope, NetExpr*root)
if (real_args) width = 1;
else width = expr_width();
netvector_t*osig_vec = new netvector_t(lsig->data_type(), width-1, 0);
osig_vec->set_signed(has_sign());
NetNet*osig = new NetNet(scope, scope->local_symbol(),
NetNet::IMPLICIT, width);
NetNet::IMPLICIT, osig_vec);
osig->set_line(*this);
osig->data_type(lsig->data_type());
osig->set_signed(has_sign());
osig->local_flag(true);
switch (op()) {
@ -530,10 +531,10 @@ NetNet* NetEBLogic::synthesize(Design*des, NetScope*scope, NetExpr*root)
return 0;
}
netvector_t*osig_tmp = new netvector_t(expr_type());
NetNet*osig = new NetNet(scope, scope->local_symbol(),
NetNet::IMPLICIT, 1);
NetNet::IMPLICIT, osig_tmp);
osig->set_line(*this);
osig->data_type(expr_type());
osig->local_flag(true);
NetLogic*olog;
@ -597,10 +598,10 @@ NetNet* NetEBShift::synthesize(Design*des, NetScope*scope, NetExpr*root)
if (shift == 0)
return lsig;
netvector_t*osig_vec = new netvector_t(expr_type(), expr_width()-1,0);
NetNet*osig = new NetNet(scope, scope->local_symbol(),
NetNet::IMPLICIT, expr_width());
NetNet::IMPLICIT, osig_vec);
osig->set_line(*this);
osig->data_type(expr_type());
osig->local_flag(true);
// ushift is the amount of pad created by the shift.
@ -618,10 +619,10 @@ NetNet* NetEBShift::synthesize(Design*des, NetScope*scope, NetExpr*root)
psel->set_line(*this);
des->add_node(psel);
netvector_t*psig_vec = new netvector_t(expr_type(), part_width-1, 0);
NetNet*psig = new NetNet(scope, scope->local_symbol(),
NetNet::IMPLICIT, part_width);
NetNet::IMPLICIT, psig_vec);
psig->set_line(*this);
psig->data_type(expr_type());
psig->local_flag(true);
connect(psig->pin(0), psel->pin(0));
@ -646,10 +647,11 @@ NetNet* NetEBShift::synthesize(Design*des, NetScope*scope, NetExpr*root)
znum);
des->add_node(zcon);
netvector_t*zsig_vec = new netvector_t(osig->data_type(),
znum.len()-1, 0);
NetNet*zsig = new NetNet(scope, scope->local_symbol(),
NetNet::WIRE, znum.len());
NetNet::WIRE, zsig_vec);
zsig->set_line(*this);
zsig->data_type(osig->data_type());
zsig->local_flag(true);
connect(zcon->pin(0), zsig->pin(0));
@ -676,10 +678,10 @@ NetNet* NetEBShift::synthesize(Design*des, NetScope*scope, NetExpr*root)
if (rsig == 0) return 0;
netvector_t*osig_vec = new netvector_t(expr_type(), expr_width()-1, 0);
NetNet*osig = new NetNet(scope, scope->local_symbol(),
NetNet::IMPLICIT, expr_width());
NetNet::IMPLICIT, osig_vec);
osig->set_line(*this);
osig->data_type(expr_type());
osig->local_flag(true);
NetCLShift*dev = new NetCLShift(scope, scope->local_symbol(),
@ -739,10 +741,10 @@ NetNet* NetEConcat::synthesize(Design*des, NetScope*scope, NetExpr*root)
/* Make a NetNet object to carry the output vector. */
perm_string path = scope->local_symbol();
NetNet*osig = new NetNet(scope, path, NetNet::IMPLICIT, expr_width());
netvector_t*osig_vec = new netvector_t(data_type, expr_width()-1, 0);
NetNet*osig = new NetNet(scope, path, NetNet::IMPLICIT, osig_vec);
osig->set_line(*this);
osig->local_flag(true);
osig->data_type(data_type);
NetConcat*concat = new NetConcat(scope, scope->local_symbol(),
osig->vector_width(),
@ -785,11 +787,11 @@ NetNet* NetEConst::synthesize(Design*des, NetScope*scope, NetExpr*)
return 0;
}
NetNet*osig = new NetNet(scope, path, NetNet::IMPLICIT, width);
netvector_t*osig_vec = new netvector_t(expr_type(), width-1, 0);
osig_vec->set_signed(has_sign());
NetNet*osig = new NetNet(scope, path, NetNet::IMPLICIT, osig_vec);
osig->set_line(*this);
osig->local_flag(true);
osig->data_type(expr_type());
osig->set_signed(has_sign());
NetConst*con = new NetConst(scope, scope->local_symbol(), value());
con->set_line(*this);
@ -806,11 +808,11 @@ NetNet* NetECReal::synthesize(Design*des, NetScope*scope, NetExpr*)
{
perm_string path = scope->local_symbol();
NetNet*osig = new NetNet(scope, path, NetNet::WIRE, 1);
netvector_t*osig_vec = new netvector_t(IVL_VT_REAL);
osig_vec->set_signed(has_sign());
NetNet*osig = new NetNet(scope, path, NetNet::WIRE, osig_vec);
osig->set_line(*this);
osig->local_flag(true);
osig->data_type(IVL_VT_REAL);
osig->set_signed(has_sign());
NetLiteral*con = new NetLiteral(scope, scope->local_symbol(), value_);
con->set_line(*this);
@ -839,10 +841,10 @@ NetNet* NetEUBits::synthesize(Design*des, NetScope*scope, NetExpr*root)
}
unsigned width = isig->vector_width();
netvector_t*osig_vec = new netvector_t(expr_type(), width-1, 0);
NetNet*osig = new NetNet(scope, scope->local_symbol(),
NetNet::IMPLICIT, width);
NetNet::IMPLICIT, osig_vec);
osig->set_line(*this);
osig->data_type(expr_type());
osig->local_flag(true);
perm_string oname = scope->local_symbol();
@ -882,11 +884,12 @@ NetNet* NetEUnary::synthesize(Design*des, NetScope*scope, NetExpr*root)
if (expr_->has_sign() == false)
return sub;
netvector_t*sig_vec = new netvector_t(sub->data_type(),
sub->vector_width()-1, 0);
NetNet*sig = new NetNet(scope, scope->local_symbol(),
NetNet::WIRE, sub->vector_width());
NetNet::WIRE, sig_vec);
sig->set_line(*this);
sig->local_flag(true);
sig->data_type(sub->data_type());
NetAbs*tmp = new NetAbs(scope, scope->local_symbol(), sub->vector_width());
tmp->set_line(*this);
@ -956,10 +959,10 @@ NetNet* NetEUReduce::synthesize(Design*des, NetScope*scope, NetExpr*root)
gate->set_line(*this);
des->add_node(gate);
netvector_t*osig_vec = new netvector_t(expr_type());
NetNet*osig = new NetNet(scope, scope->local_symbol(),
NetNet::IMPLICIT, 1);
NetNet::IMPLICIT, osig_vec);
osig->set_line(*this);
osig->data_type(expr_type());
osig->local_flag(true);
connect(gate->pin(0), osig->pin(0));
@ -1063,10 +1066,11 @@ NetNet* NetESelect::synthesize(Design *des, NetScope*scope, NetExpr*root)
des->add_node(sel);
ivl_assert(*this, select_width > 0);
netvector_t*tmp_vec = new netvector_t(sub->data_type(),
select_width-1, 0);
NetNet*tmp = new NetNet(scope, scope->local_symbol(),
NetNet::WIRE, select_width);
NetNet::WIRE, tmp_vec);
tmp->set_line(*this);
tmp->data_type(sub->data_type());
tmp->local_flag(true);
connect(sel->pin(0), tmp->pin(0));
@ -1090,10 +1094,10 @@ NetNet* NetESelect::synthesize(Design *des, NetScope*scope, NetExpr*root)
connect(cat->pin(concat_count), above->pin(0));
}
tmp_vec = new netvector_t(sub->data_type(), expr_width()-1, 0);
tmp = new NetNet(scope, scope->local_symbol(),
NetNet::WIRE, expr_width());
NetNet::WIRE, tmp_vec);
tmp->set_line(*this);
tmp->data_type(sub->data_type());
tmp->local_flag(true);
connect(cat->pin(0), tmp->pin(0));
}
@ -1111,9 +1115,10 @@ NetNet* NetESelect::synthesize(Design *des, NetScope*scope, NetExpr*root)
sel->set_line(*this);
des->add_node(sel);
netvector_t*tmp_vec = new netvector_t(sub->data_type(),
expr_width()-1, 0);
NetNet*tmp = new NetNet(scope, scope->local_symbol(),
NetNet::IMPLICIT, expr_width());
tmp->data_type(sub->data_type());
NetNet::IMPLICIT, tmp_vec);
tmp->local_flag(true);
tmp->set_line(*this);
sub = tmp;
@ -1134,10 +1139,11 @@ NetNet* NetESelect::synthesize(Design *des, NetScope*scope, NetExpr*root)
// extension or 0 extension, depending on the has_sign() mode
// of the expression.
netvector_t*net_vec = new netvector_t(expr_type(), expr_width()-1, 0);
net_vec->set_signed(has_sign());
NetNet*net = new NetNet(scope, scope->local_symbol(),
NetNet::IMPLICIT, expr_width());
NetNet::IMPLICIT, net_vec);
net->set_line(*this);
net->data_type(expr_type());
net->local_flag(true);
if (has_sign()) {
NetSignExtend*pad = new NetSignExtend(scope,
@ -1148,7 +1154,6 @@ NetNet* NetESelect::synthesize(Design *des, NetScope*scope, NetExpr*root)
connect(pad->pin(1), sub->pin(0));
connect(pad->pin(0), net->pin(0));
net->set_signed(true);
} else {
@ -1165,10 +1170,10 @@ NetNet* NetESelect::synthesize(Design *des, NetScope*scope, NetExpr*root)
con->set_line(*this);
des->add_node(con);
netvector_t*tmp_vec = new netvector_t(expr_type(), pad_width-1, 0);
NetNet*tmp = new NetNet(scope, scope->local_symbol(),
NetNet::IMPLICIT, pad_width);
NetNet::IMPLICIT, tmp_vec);
tmp->set_line(*this);
tmp->data_type(expr_type());
tmp->local_flag(true);
connect(tmp->pin(0), con->pin(0));
@ -1220,9 +1225,9 @@ NetNet* NetETernary::synthesize(Design *des, NetScope*scope, NetExpr*root)
ivl_assert(*this, csig->vector_width() == 1);
unsigned width=expr_width();
NetNet*osig = new NetNet(csig->scope(), path, NetNet::IMPLICIT, width);
netvector_t*osig_vec = new netvector_t(expr_type(), width-1, 0);
NetNet*osig = new NetNet(csig->scope(), path, NetNet::IMPLICIT, osig_vec);
osig->set_line(*this);
osig->data_type(expr_type());
osig->local_flag(true);
/* Make sure the types match. */
@ -1265,11 +1270,12 @@ NetNet* NetESignal::synthesize(Design*des, NetScope*scope, NetExpr*root)
if (word_ == 0)
return net_;
netvector_t*tmp_vec = new netvector_t(net_->data_type(),
net_->vector_width()-1, 0);
NetNet*tmp = new NetNet(scope, scope->local_symbol(),
NetNet::IMPLICIT, net_->vector_width());
NetNet::IMPLICIT, tmp_vec);
tmp->set_line(*this);
tmp->local_flag(true);
tmp->data_type(net_->data_type());
// For NetExpr objects, the word index is already converted to
// a canonical (lsb==0) address. Just use the index directly.
@ -1354,12 +1360,12 @@ NetNet* NetESFunc::synthesize(Design*des, NetScope*scope, NetExpr*root)
net->set_line(*this);
des->add_node(net);
netvector_t*osig_vec = new netvector_t(def->type, def->wid-1, 0);
osig_vec->set_signed(def->type==IVL_VT_REAL? true : false);
NetNet*osig = new NetNet(scope, scope->local_symbol(),
NetNet::WIRE, def->wid);
NetNet::WIRE, osig_vec);
osig->set_line(*this);
osig->local_flag(true);
osig->set_signed(def->type==IVL_VT_REAL? true : false);
osig->data_type(def->type);
connect(net->pin(0), osig->pin(0));
@ -1422,11 +1428,12 @@ NetNet* NetEUFunc::synthesize(Design*des, NetScope*scope, NetExpr*root)
des->add_node(net);
/* Create an output signal and connect it to the function. */
netvector_t*osig_vec = new netvector_t(result_sig_->expr_type(),
result_sig_->vector_width()-1, 0);
NetNet*osig = new NetNet(scope_, scope_->local_symbol(), NetNet::WIRE,
result_sig_->vector_width());
osig_vec);
osig->set_line(*this);
osig->local_flag(true);
osig->data_type(result_sig_->expr_type());
connect(net->pin(0), osig->pin(0));
/* Connect the pins to the arguments. */

View File

@ -21,12 +21,19 @@
# include <inttypes.h>
/* Re the _CLASS define: clang++ wants this to be class to match the
* definition, but clang (the C) compiler needs it to be a struct
* since class is not defined in C. They are effecively both pointers
* to an object so everything works out. */
#ifdef __cplusplus
#define _BEGIN_DECL extern "C" {
#define _END_DECL }
#define _CLASS class
#else
#define _BEGIN_DECL
#define _END_DECL
#define _CLASS struct
#endif
#ifndef __GNUC__
@ -157,21 +164,8 @@ typedef struct ivl_array_s *ivl_array_t;
typedef struct ivl_branch_s *ivl_branch_t;
typedef struct ivl_delaypath_s*ivl_delaypath_t;
typedef struct ivl_design_s *ivl_design_t;
/* clang++ wants this to be class to match the definition, but clang
* (the C) compiler needs it to be a struct since class is not defined
* in C. They are effecively both pointers to an object so everything
* works out. */
#ifdef __cplusplus
typedef class ivl_discipline_s*ivl_discipline_t;
#else
typedef struct ivl_discipline_s*ivl_discipline_t;
#endif
/* See the comments above. */
#ifdef __cplusplus
typedef class netenum_t *ivl_enumtype_t;
#else
typedef struct netenum_t *ivl_enumtype_t;
#endif
typedef _CLASS ivl_discipline_s*ivl_discipline_t;
typedef _CLASS netenum_t *ivl_enumtype_t;
typedef struct ivl_event_s *ivl_event_t;
typedef struct ivl_expr_s *ivl_expr_t;
typedef struct ivl_island_s *ivl_island_t;
@ -180,12 +174,7 @@ typedef struct ivl_lval_s *ivl_lval_t;
typedef struct ivl_net_const_s*ivl_net_const_t;
typedef struct ivl_net_logic_s*ivl_net_logic_t;
typedef struct ivl_udp_s *ivl_udp_t;
/* See the comments above. */
#ifdef __cplusplus
typedef class ivl_nature_s *ivl_nature_t;
#else
typedef struct ivl_nature_s *ivl_nature_t;
#endif
typedef _CLASS ivl_nature_s *ivl_nature_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;
@ -193,10 +182,11 @@ typedef struct ivl_parameter_s*ivl_parameter_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;
typedef struct ivl_port_info_s *ivl_port_info_t;
typedef struct ivl_port_info_s*ivl_port_info_t;
typedef struct ivl_switch_s *ivl_switch_t;
typedef struct ivl_memory_s *ivl_memory_t; //XXXX __attribute__((deprecated));
typedef struct ivl_statement_s*ivl_statement_t;
typedef const _CLASS ivl_type_s*ivl_type_t;
/*
* These are types that are defined as enumerations. These have
@ -774,6 +764,11 @@ extern unsigned ivl_event_lineno(ivl_event_t net);
* Get the data type of the expression node. This uses the variable
* type enum to express the type of the expression node.
*
* ivl_expr_net_type
* This is used in some cases to carry more advanced type
* descriptions. Over the long run, all type informatino will be
* moved into the ivl_type_t type description method.
*
* ivl_expr_width
* This method returns the bit width of the expression at this
* node. It can be applied to any expression node, and returns the
@ -851,6 +846,7 @@ extern unsigned ivl_event_lineno(ivl_event_t net);
*/
extern ivl_expr_type_t ivl_expr_type(ivl_expr_t net);
extern ivl_type_t ivl_expr_net_type(ivl_expr_t net);
extern ivl_variable_type_t ivl_expr_value(ivl_expr_t net);
extern const char*ivl_expr_file(ivl_expr_t net);
extern unsigned ivl_expr_lineno(ivl_expr_t net);
@ -1907,6 +1903,7 @@ extern unsigned ivl_signal_npath(ivl_signal_t net);
extern ivl_delaypath_t ivl_signal_path(ivl_signal_t net, unsigned idx);
extern ivl_signal_type_t ivl_signal_type(ivl_signal_t net);
extern ivl_variable_type_t ivl_signal_data_type(ivl_signal_t net);
extern ivl_type_t ivl_signal_net_type(ivl_signal_t net);
extern const char* ivl_signal_name(ivl_signal_t net);
extern const char* ivl_signal_basename(ivl_signal_t net);
extern const char* ivl_signal_attr(ivl_signal_t net, const char*key);
@ -1994,7 +1991,7 @@ extern unsigned ivl_stmt_lineno(ivl_statement_t net);
* Statements that have event arguments (TRIGGER and WAIT) make
* those event objects available through these methods.
*
* ivl_stmt_lval
* ivl_stmt_lval
* ivl_stmt_lvals
* Return the number of l-values for an assignment statement, or
* the specific l-value. If there is more than 1 l-value, then the
@ -2195,6 +2192,25 @@ extern ivl_attribute_t ivl_switch_attr_val(ivl_switch_t net, unsigned idx);
extern const char* ivl_switch_file(ivl_switch_t net);
extern unsigned ivl_switch_lineno(ivl_switch_t net);
/* TYPES
*
* ivl_type_base
* This returns the base type for the type. See the
* ivl_variable_type_t definition for the various base types.
*
* ivl_type_element
* Return the type of the element of an array. This is only valid
* for array types.
*
* SEMANTIC NOTES
*/
extern ivl_variable_type_t ivl_type_base(ivl_type_t net);
extern ivl_type_t ivl_type_element(ivl_type_t net);
extern unsigned ivl_type_packed_dimensions(ivl_type_t net);
extern int ivl_type_packed_lsb(ivl_type_t net, unsigned dim);
extern int ivl_type_packed_msb(ivl_type_t net, unsigned dim);
#if defined(__MINGW32__) || defined (__CYGWIN32__)
# define DLLEXPORT __declspec(dllexport)
#else

View File

@ -89,7 +89,7 @@ unsigned NetAssign_::lwidth() const
if (word_ == 0)
return 1;
else
return darray->vector_width();
return darray->element_width();
}
return lwid_;
@ -101,7 +101,7 @@ ivl_variable_type_t NetAssign_::expr_type() const
if (word_ == 0)
return IVL_VT_DARRAY;
else
return darray->data_type();
return darray->element_base_type();
}
return sig_->data_type();

View File

@ -20,9 +20,40 @@
# include "config.h"
# include "netlist.h"
# include "netenum.h"
# include "netdarray.h"
# include "compiler.h"
# include "netmisc.h"
# include <iostream>
# include "ivl_assert.h"
NetExpr::NetExpr(unsigned w)
: net_type_(0), width_(w), signed_flag_(false)
{
}
NetExpr::NetExpr(ivl_type_t t)
: net_type_(t), width_(0), signed_flag_(false)
{
}
NetExpr::~NetExpr()
{
}
ivl_type_t NetExpr::net_type() const
{
return net_type_;
}
void NetExpr::cast_signed(bool flag)
{
cast_signed_base_(flag);
}
bool NetExpr::has_width() const
{
return true;
}
/*
* the grand default data type is a logic vector.
@ -317,6 +348,32 @@ ivl_select_type_t NetESelect::select_type() const
return sel_type_;
}
ivl_variable_type_t NetESelect::expr_type() const
{
ivl_variable_type_t type = expr_->expr_type();
// Special case: If the sub-expression is an IVL_VT_STRING,
// then this node is representing a character select. The
// width is the width of a byte, and the data type is BOOL.
if (type == IVL_VT_STRING && expr_width()==8)
return IVL_VT_BOOL;
if (type != IVL_VT_DARRAY)
return type;
ivl_assert(*this, type == IVL_VT_DARRAY);
// Special case: If the expression is a DARRAY, then the
// sub-expression must be a NetESignal and the type of the
// NetESelect expression is the element type of the arrayed signal.
NetESignal*sig = dynamic_cast<NetESignal*>(expr_);
ivl_assert(*this, sig);
const netarray_t*array_type = dynamic_cast<const netarray_t*> (sig->sig()->net_type());
ivl_assert(*this, array_type);
return array_type->element_type()->base_type();
}
bool NetESelect::has_width() const
{
return true;
@ -330,6 +387,18 @@ NetESFunc::NetESFunc(const char*n, ivl_variable_type_t t,
expr_width(width);
}
NetESFunc::NetESFunc(const char*n, ivl_type_t rtype, unsigned np)
: NetExpr(rtype), name_(0), type_(IVL_VT_NO_TYPE), enum_type_(0), parms_(np)
{
name_ = lex_strings.add(n);
expr_width(rtype->packed_width());
// FIXME: For now, assume that all uses of this constructor
// are for the IVL_VT_DARRAY type. Eventually, the type_
// member will go away.
ivl_assert(*this, dynamic_cast<const netdarray_t*>(rtype));
type_ = IVL_VT_DARRAY;
}
NetESFunc::NetESFunc(const char*n, netenum_t*enum_type, unsigned np)
: name_(0), type_(enum_type->base_type()), enum_type_(enum_type), parms_(np)
{

View File

@ -21,12 +21,16 @@
using namespace std;
netdarray_t::netdarray_t(const std::list<netrange_t>&packed,
ivl_variable_type_t type, unsigned long wid)
: packed_dims_(packed), type_(type), width_(wid)
netdarray_t::netdarray_t(ivl_type_t vec)
: netarray_t(vec)
{
}
netdarray_t::~netdarray_t()
{
}
ivl_variable_type_t netdarray_t::base_type(void) const
{
return IVL_VT_DARRAY;
}

View File

@ -21,23 +21,30 @@
# include "nettypes.h"
# include "ivl_target.h"
# include <list>
class netdarray_t : public nettype_base_t {
class netdarray_t : public netarray_t {
public:
explicit netdarray_t(const std::list<netrange_t>&packed,
ivl_variable_type_t type,
unsigned long wid);
explicit netdarray_t(ivl_type_t vec);
~netdarray_t();
inline ivl_variable_type_t data_type() const { return type_; }
inline unsigned long vector_width(void) const { return width_; }
// This is the "base_type()" virtual method of the
// nettype_base_t. The ivl_target api expects this to return
// IVL_VT_DARRAY for dynamic arrays?
ivl_variable_type_t base_type() const;
// This is the base_type() of the element of the array. We
// need this in some cases in order to get the base type of
// the element, and not the IVL_VT_DARRAY of the array itself.
inline ivl_variable_type_t element_base_type() const { return element_type()->base_type(); }
// This is a convenience function for getting the width of an
// element. Strictly speaking it's not necessary.
inline unsigned long element_width(void) const { return element_type()->packed_width(); }
std::ostream& debug_dump(std::ostream&) const;
private:
std::list<netrange_t> packed_dims_;
ivl_variable_type_t type_;
unsigned long width_;
};
#endif

View File

@ -21,6 +21,8 @@
# include "compiler.h"
# include <cassert>
using namespace std;
netenum_t::netenum_t(ivl_variable_type_t btype, bool signed_flag,
long msb, long lsb, size_t name_count)
: base_type_(btype), signed_flag_(signed_flag), msb_(msb), lsb_(lsb),
@ -32,6 +34,11 @@ netenum_t::~netenum_t()
{
}
bool netenum_t::get_signed() const
{
return signed_flag_;
}
long netenum_t::packed_width() const
{
if (msb_ >= lsb_)
@ -40,6 +47,14 @@ long netenum_t::packed_width() const
return lsb_ - msb_ + 1;
}
vector<netrange_t> netenum_t::slice_dimensions() const
{
vector<netrange_t> tmp (1);
tmp[0] = netrange_t(msb_, lsb_);
return tmp;
}
bool netenum_t::insert_name(size_t name_idx, perm_string name, const verinum&val)
{
std::pair<std::map<perm_string,verinum>::iterator, bool> res;

View File

@ -29,7 +29,7 @@
class NetScope;
class netenum_t : public LineInfo, public nettype_base_t {
class netenum_t : public LineInfo, public ivl_type_s {
public:
explicit netenum_t(ivl_variable_type_t base_type, bool signed_flag,
@ -38,7 +38,8 @@ class netenum_t : public LineInfo, public nettype_base_t {
ivl_variable_type_t base_type() const;
long packed_width() const;
bool has_sign() const;
std::vector<netrange_t> slice_dimensions() const;
bool get_signed() const;
// The size() is the number of enumeration literals.
size_t size() const;
@ -75,6 +76,4 @@ inline ivl_variable_type_t netenum_t::base_type() const
inline size_t netenum_t::size() const { return names_.size(); }
inline bool netenum_t::has_sign() const { return signed_flag_; }
#endif

View File

@ -29,7 +29,9 @@
# include "netmisc.h"
# include "netdarray.h"
# include "netenum.h"
# include "netparray.h"
# include "netstruct.h"
# include "netvector.h"
# include "ivl_assert.h"
@ -463,44 +465,6 @@ PortType::Enum PortType::merged( Enum lhs, Enum rhs )
return PINOUT;
}
NetNet::NetNet(NetScope*s, perm_string n, Type t, unsigned npins)
: NetObj(s, n, 1),
type_(t), port_type_(NOT_A_PORT), data_type_(IVL_VT_NO_TYPE),
signed_(false), isint_(false), is_scalar_(false), local_flag_(false),
net_type_(0), discipline_(0),
eref_count_(0), lref_count_(0),
port_index_(-1)
{
assert(s);
assert(npins>0);
// Synthesize a single range to describe this canonical vector.
packed_dims_.push_back(netrange_t(npins-1, 0));
calculate_slice_widths_from_packed_dims_();
Link::DIR dir = Link::PASSIVE;
switch (t) {
case REG:
case INTEGER:
case IMPLICIT_REG:
dir = Link::OUTPUT;
break;
case SUPPLY0:
dir = Link::OUTPUT;
break;
case SUPPLY1:
dir = Link::OUTPUT;
break;
default:
break;
}
pin(0).set_dir(dir);
s->add_signal(this);
}
void NetNet::initialize_dir_(Link::DIR dir)
{
if (pins_are_virtual()) {
@ -513,40 +477,6 @@ void NetNet::initialize_dir_(Link::DIR dir)
}
}
NetNet::NetNet(NetScope*s, perm_string n, Type t,
const list<netrange_t>&packed)
: NetObj(s, n, 1), type_(t),
port_type_(NOT_A_PORT), data_type_(IVL_VT_NO_TYPE), signed_(false),
isint_(false), is_scalar_(false), local_flag_(false),
net_type_(0), discipline_(0),
eref_count_(0), lref_count_(0)
{
packed_dims_ = packed;
calculate_slice_widths_from_packed_dims_();
assert(s);
Link::DIR dir = Link::PASSIVE;
switch (t) {
case REG:
case IMPLICIT_REG:
dir = Link::OUTPUT;
break;
case SUPPLY0:
dir = Link::OUTPUT;
break;
case SUPPLY1:
dir = Link::OUTPUT;
break;
default:
break;
}
initialize_dir_(dir);
s->add_signal(this);
}
static unsigned calculate_count(const list<netrange_t>&unpacked)
{
unsigned long sum = 1;
@ -577,35 +507,35 @@ template <class T> static unsigned calculate_count(T*type)
void NetNet::calculate_slice_widths_from_packed_dims_(void)
{
if (packed_dims_.empty()) {
slice_wids_.clear();
ivl_assert(*this, net_type_);
slice_dims_ = net_type_->slice_dimensions();
// Special case: There are no actual packed dimensions, so
// build up a fake dimension of "1".
if (slice_dims_.size() == 0) {
slice_wids_.resize(1);
slice_wids_[0] = net_type_->packed_width();
return;
}
slice_wids_.resize(packed_dims_.size());
slice_wids_.resize(slice_dims_.size());
slice_wids_[0] = netrange_width(packed_dims_);
list<netrange_t>::const_iterator cur = packed_dims_.begin();
ivl_assert(*this, slice_wids_.size() >= 1);
slice_wids_[0] = netrange_width(slice_dims_);
vector<netrange_t>::const_iterator cur = slice_dims_.begin();
for (size_t idx = 1 ; idx < slice_wids_.size() ; idx += 1) {
slice_wids_[idx] = slice_wids_[idx-1] / cur->width();
}
}
NetNet::NetNet(NetScope*s, perm_string n, Type t,
const list<netrange_t>&packed,
const list<netrange_t>&unpacked,
nettype_base_t*net_type)
const list<netrange_t>&unpacked, ivl_type_s*use_net_type)
: NetObj(s, n, calculate_count(unpacked)),
type_(t), port_type_(NOT_A_PORT),
data_type_(IVL_VT_NO_TYPE), signed_(false), isint_(false),
is_scalar_(false), local_flag_(false), net_type_(net_type),
local_flag_(false), net_type_(use_net_type),
discipline_(0), unpacked_dims_(unpacked.size()),
eref_count_(0), lref_count_(0)
{
packed_dims_ = packed;
if (net_type)
packed_dims_.push_back(netrange_t(calculate_count(net_type)-1, 0));
calculate_slice_widths_from_packed_dims_();
size_t idx = 0;
for (list<netrange_t>::const_iterator cur = unpacked.begin()
@ -650,12 +580,11 @@ NetNet::NetNet(NetScope*s, perm_string n, Type t,
NetNet::NetNet(NetScope*s, perm_string n, Type t, netstruct_t*ty)
: NetObj(s, n, 1),
type_(t), port_type_(NOT_A_PORT),
data_type_(IVL_VT_NO_TYPE), signed_(false), isint_(false),
is_scalar_(false), local_flag_(false), net_type_(ty),
local_flag_(false), net_type_(ty),
discipline_(0),
eref_count_(0), lref_count_(0)
{
packed_dims_.push_back(netrange_t(calculate_count(ty)-1, 0));
//XXXX packed_dims_.push_back(netrange_t(calculate_count(ty)-1, 0));
calculate_slice_widths_from_packed_dims_();
Link::DIR dir = Link::PASSIVE;
@ -682,8 +611,7 @@ NetNet::NetNet(NetScope*s, perm_string n, Type t, netstruct_t*ty)
NetNet::NetNet(NetScope*s, perm_string n, Type t, netdarray_t*ty)
: NetObj(s, n, 1),
type_(t), port_type_(NOT_A_PORT),
data_type_(IVL_VT_NO_TYPE), signed_(false), isint_(false),
is_scalar_(false), local_flag_(false), net_type_(ty),
local_flag_(false), net_type_(ty),
discipline_(0),
eref_count_(0), lref_count_(0)
{
@ -709,6 +637,36 @@ NetNet::NetNet(NetScope*s, perm_string n, Type t, netdarray_t*ty)
s->add_signal(this);
}
NetNet::NetNet(NetScope*s, perm_string n, Type t, netvector_t*ty)
: NetObj(s, n, 1),
type_(t), port_type_(NOT_A_PORT),
local_flag_(false), net_type_(ty),
discipline_(0),
eref_count_(0), lref_count_(0)
{
calculate_slice_widths_from_packed_dims_();
Link::DIR dir = Link::PASSIVE;
switch (t) {
case REG:
case IMPLICIT_REG:
dir = Link::OUTPUT;
break;
case SUPPLY0:
dir = Link::OUTPUT;
break;
case SUPPLY1:
dir = Link::OUTPUT;
break;
default:
break;
}
initialize_dir_(dir);
s->add_signal(this);
}
NetNet::~NetNet()
{
if (eref_count_ > 0) {
@ -787,45 +745,34 @@ void NetNet::set_module_port_index(unsigned idx)
ivl_variable_type_t NetNet::data_type() const
{
return data_type_;
}
void NetNet::data_type(ivl_variable_type_t t)
{
data_type_ = t;
if (net_type_==0)
return IVL_VT_LOGIC;
else
return net_type_->base_type();
}
bool NetNet::get_signed() const
{
if (data_type_ == IVL_VT_REAL)
return true;
if (net_type_==0)
return false;
else
return signed_;
}
void NetNet::set_signed(bool flag)
{
signed_ = flag;
return net_type_->get_signed();
}
bool NetNet::get_isint() const
{
return isint_;
}
void NetNet::set_isint(bool flag)
{
isint_ = flag;
if (netvector_t*vec = dynamic_cast<netvector_t*> (net_type_))
return vec->get_isint();
else
return false;
}
bool NetNet::get_scalar() const
{
return is_scalar_;
}
void NetNet::set_scalar(bool flag)
{
is_scalar_ = flag;
if (netvector_t*vec = dynamic_cast<netvector_t*> (net_type_))
return vec->get_scalar();
else
return false;
}
netenum_t*NetNet::enumeration(void) const
@ -833,9 +780,26 @@ netenum_t*NetNet::enumeration(void) const
return dynamic_cast<netenum_t*> (net_type_);
}
netstruct_t*NetNet::struct_type(void) const
const netstruct_t*NetNet::struct_type(void) const
{
return dynamic_cast<netstruct_t*> (net_type_);
const ivl_type_s*cur_type = net_type_;
while (cur_type) {
if (const netdarray_t*da = dynamic_cast<const netdarray_t*> (cur_type)) {
cur_type = da->element_type();
continue;
}
if (const netparray_t*da = dynamic_cast<const netparray_t*> (cur_type)) {
cur_type = da->element_type();
continue;
}
if (const netstruct_t*st = dynamic_cast<const netstruct_t*> (cur_type))
return st;
else
return 0;
}
assert(0);
return 0;
}
netdarray_t* NetNet::darray_type(void) const
@ -875,9 +839,9 @@ void NetNet::set_discipline(ivl_discipline_t dis)
bool NetNet::sb_is_valid(const list<long>&indices, long sb) const
{
ivl_assert(*this, indices.size()+1 == packed_dims_.size());
assert(packed_dims_.size() == 1);
const netrange_t&rng = packed_dims_.back();
ivl_assert(*this, indices.size()+1 == packed_dims().size());
assert(packed_dims().size() == 1);
const netrange_t&rng = packed_dims().back();
if (rng.get_msb() >= rng.get_lsb())
return (sb <= rng.get_msb()) && (sb >= rng.get_lsb());
else
@ -886,9 +850,9 @@ bool NetNet::sb_is_valid(const list<long>&indices, long sb) const
long NetNet::sb_to_idx(const list<long>&indices, long sb) const
{
ivl_assert(*this, indices.size()+1 == packed_dims_.size());
ivl_assert(*this, indices.size()+1 == packed_dims().size());
list<netrange_t>::const_iterator pcur = packed_dims_.end();
vector<netrange_t>::const_iterator pcur = packed_dims().end();
-- pcur;
long acc_off;
@ -924,8 +888,8 @@ long NetNet::sb_to_idx(const list<long>&indices, long sb) const
bool NetNet::sb_to_slice(const list<long>&indices, long sb, long&loff, unsigned long&lwid) const
{
ivl_assert(*this, indices.size() < packed_dims_.size());
return prefix_to_slice(packed_dims_, indices, sb, loff, lwid);
ivl_assert(*this, indices.size() < packed_dims().size());
return prefix_to_slice(packed_dims(), indices, sb, loff, lwid);
}
unsigned NetNet::unpacked_count() const
@ -2265,25 +2229,6 @@ const NetScope* NetFree::scope() const
return scope_;
}
NetExpr::NetExpr(unsigned w)
: width_(w), signed_flag_(false)
{
}
NetExpr::~NetExpr()
{
}
void NetExpr::cast_signed(bool flag)
{
cast_signed_base_(flag);
}
bool NetExpr::has_width() const
{
return true;
}
/*
* Create a bitwise operator node from the opcode and the left and
* right expressions.
@ -2480,14 +2425,14 @@ NetNet* NetESignal::sig()
*/
long NetESignal::lsi() const
{
const list<netrange_t>&packed = net_->packed_dims();
const vector<netrange_t>&packed = net_->packed_dims();
ivl_assert(*this, packed.size() == 1);
return packed.back().get_lsb();
}
long NetESignal::msi() const
{
const list<netrange_t>&packed = net_->packed_dims();
const vector<netrange_t>&packed = net_->packed_dims();
ivl_assert(*this, packed.size() == 1);
return packed.back().get_msb();
}

View File

@ -80,6 +80,7 @@ class netdarray_t;
class netparray_t;
class netenum_t;
class netstruct_t;
class netvector_t;
struct target;
struct functor_t;
@ -596,26 +597,18 @@ class NetNet : public NetObj, public PortType {
typedef PortType::Enum PortType;
public:
// The width in this case is a shorthand for ms=width-1 and
// ls=0. Only one pin is created, the width is of the vector
// that passed through.
explicit NetNet(NetScope*s, perm_string n, Type t, unsigned width =1);
// This form supports an array of vectors. The [ms:ls] define
// the base vector, and the [s0:e0] define the array
// dimensions. If s0==e0, then this is not an array after
// all.
// This form is the more generic form of the constructor. For
// now, the unpacked type is not burried into an ivl_type_s object.
explicit NetNet(NetScope*s, perm_string n, Type t,
const std::list<netrange_t>&packed);
explicit NetNet(NetScope*s, perm_string n, Type t,
const std::list<netrange_t>&packed,
const std::list<netrange_t>&unpacked,
nettype_base_t*type =0);
ivl_type_s*type =0);
// This form builds a NetNet from its record/enum definition.
// This form builds a NetNet from its record/enum/darray
// definition. They should probably be replaced with a single
// version that takes an ivl_type_s* base.
explicit NetNet(NetScope*s, perm_string n, Type t, netstruct_t*type);
explicit NetNet(NetScope*s, perm_string n, Type t, netdarray_t*type);
//explicit NetNet(NetScope*s, perm_string n, Type t, netparray_t*type);
explicit NetNet(NetScope*s, perm_string n, Type t, netvector_t*type);
virtual ~NetNet();
@ -631,23 +624,20 @@ class NetNet : public NetObj, public PortType {
void set_module_port_index(unsigned idx);
ivl_variable_type_t data_type() const;
void data_type(ivl_variable_type_t t);
/* If a NetNet is signed, then its value is to be treated as
signed. Otherwise, it is unsigned. */
bool get_signed() const;
void set_signed(bool);
/* Used to maintain original type of net since integers are
implemented as 'reg signed [31:0]' in Icarus */
bool get_isint() const;
void set_isint(bool);
bool get_scalar() const;
void set_scalar(bool);
inline const ivl_type_s* net_type(void) const { return net_type_; }
netenum_t*enumeration(void) const;
netstruct_t*struct_type(void) const;
const netstruct_t*struct_type(void) const;
netdarray_t*darray_type(void) const;
/* Attach a discipline to the net. */
@ -657,8 +647,9 @@ class NetNet : public NetObj, public PortType {
/* This method returns a reference to the packed dimensions
for the vector. These are arranged as a list where the
first range in the list (front) is the left-most range in
the verilog declaration. */
const std::list<netrange_t>& packed_dims() const { return packed_dims_; }
the verilog declaration. These packed dims are compressed
to represent the dimensions of all the subtypes. */
const std::vector<netrange_t>& packed_dims() const { return slice_dims_; }
const std::vector<netrange_t>& unpacked_dims() const { return unpacked_dims_; }
@ -698,7 +689,7 @@ class NetNet : public NetObj, public PortType {
/* This methor returns 0 for scalars, but vectors and other
PACKED arrays have packed dimensions. */
inline size_t packed_dimensions() const { return packed_dims_.size(); }
inline size_t packed_dimensions() const { return slice_dims_.size(); }
// This is the number of array elements.
unsigned unpacked_count() const;
@ -733,15 +724,10 @@ class NetNet : public NetObj, public PortType {
private:
Type type_ : 5;
PortType port_type_ : 3;
ivl_variable_type_t data_type_ : 3;
bool signed_ : 1;
bool isint_ : 1; // original type of integer
bool is_scalar_ : 1;
bool local_flag_: 1;
nettype_base_t*net_type_;
ivl_type_s*net_type_;
ivl_discipline_t discipline_;
std::list<netrange_t> packed_dims_;
std::vector<netrange_t> unpacked_dims_;
// These are the widths of the various slice depths. There is
@ -750,6 +736,7 @@ class NetNet : public NetObj, public PortType {
//
// For example: slice_wids_[0] is vector_width().
void calculate_slice_widths_from_packed_dims_(void);
std::vector<netrange_t> slice_dims_;
std::vector<unsigned long> slice_wids_;
unsigned eref_count_;
@ -764,7 +751,6 @@ class NetNet : public NetObj, public PortType {
int port_index_;
};
extern std::ostream&operator << (std::ostream&out, const std::list<netrange_t>&rlist);
/*
* This object type is used to contain a logical scope within a
@ -1753,11 +1739,18 @@ class NetTran : public NetNode, public IslandBranch {
class NetExpr : public LineInfo {
public:
explicit NetExpr(unsigned w =0);
explicit NetExpr(ivl_type_t t);
virtual ~NetExpr() =0;
virtual void expr_scan(struct expr_scan_t*) const =0;
virtual void dump(ostream&) const;
// This is the advanced description of the type. I think I
// want to replace the other type description members with
// this single method. The default for this method returns
// nil.
ivl_type_t net_type() const;
// Expressions have type.
virtual ivl_variable_type_t expr_type() const;
@ -1826,6 +1819,7 @@ class NetExpr : public LineInfo {
void cast_signed_base_(bool flag) { signed_flag_ = flag; }
private:
ivl_type_t net_type_;
unsigned width_;
bool signed_flag_;
@ -3813,6 +3807,10 @@ class NetESelect : public NetExpr {
const NetExpr*select() const;
ivl_select_type_t select_type() const;
// The type of a NetESelect is the base type of the
// sub-expression.
virtual ivl_variable_type_t expr_type() const;
virtual NexusSet* nex_input(bool rem_out = true);
virtual bool has_width() const;
virtual void expr_scan(struct expr_scan_t*) const;
@ -3906,6 +3904,7 @@ class NetESFunc : public NetExpr {
public:
NetESFunc(const char*name, ivl_variable_type_t t,
unsigned width, unsigned nprms);
NetESFunc(const char*name, ivl_type_t rtype, unsigned nprms);
NetESFunc(const char*name, netenum_t*enum_type, unsigned nprms);
~NetESFunc();

View File

@ -21,6 +21,7 @@
# include <cstdlib>
# include "netlist.h"
# include "netvector.h"
# include "netmisc.h"
# include "PExpr.h"
# include "pform_types.h"
@ -30,10 +31,11 @@
NetNet* sub_net_from(Design*des, NetScope*scope, long val, NetNet*sig)
{
netvector_t*zero_vec = new netvector_t(sig->data_type(),
sig->vector_width()-1, 0);
NetNet*zero_net = new NetNet(scope, scope->local_symbol(),
NetNet::WIRE, sig->vector_width());
NetNet::WIRE, zero_vec);
zero_net->set_line(*sig);
zero_net->data_type(sig->data_type());
zero_net->local_flag(true);
if (sig->data_type() == IVL_VT_REAL) {
@ -62,10 +64,11 @@ NetNet* sub_net_from(Design*des, NetScope*scope, long val, NetNet*sig)
connect(zero_net->pin(0), adder->pin_DataA());
connect(adder->pin_DataB(), sig->pin(0));
netvector_t*tmp_vec = new netvector_t(sig->data_type(),
sig->vector_width()-1, 0);
NetNet*tmp = new NetNet(scope, scope->local_symbol(),
NetNet::WIRE, sig->vector_width());
NetNet::WIRE, tmp_vec);
tmp->set_line(*sig);
tmp->data_type(sig->data_type());
tmp->local_flag(true);
connect(adder->pin_Result(), tmp->pin(0));
@ -78,9 +81,9 @@ NetNet* cast_to_int2(Design*des, NetScope*scope, NetNet*src, unsigned wid)
if (src->data_type() == IVL_VT_BOOL)
return src;
NetNet*tmp = new NetNet(scope, scope->local_symbol(), NetNet::WIRE, wid);
netvector_t*tmp_vec = new netvector_t(IVL_VT_BOOL, wid-1, 0);
NetNet*tmp = new NetNet(scope, scope->local_symbol(), NetNet::WIRE, tmp_vec);
tmp->set_line(*src);
tmp->data_type(IVL_VT_BOOL);
tmp->local_flag(true);
NetCastInt2*cast = new NetCastInt2(scope, scope->local_symbol(), wid);
@ -98,9 +101,9 @@ NetNet* cast_to_int4(Design*des, NetScope*scope, NetNet*src, unsigned wid)
if (src->data_type() != IVL_VT_REAL)
return src;
NetNet*tmp = new NetNet(scope, scope->local_symbol(), NetNet::WIRE, wid);
netvector_t*tmp_vec = new netvector_t(IVL_VT_LOGIC, wid-1, 0);
NetNet*tmp = new NetNet(scope, scope->local_symbol(), NetNet::WIRE, tmp_vec);
tmp->set_line(*src);
tmp->data_type(IVL_VT_LOGIC);
tmp->local_flag(true);
NetCastInt4*cast = new NetCastInt4(scope, scope->local_symbol(), wid);
@ -118,9 +121,9 @@ NetNet* cast_to_real(Design*des, NetScope*scope, NetNet*src)
if (src->data_type() == IVL_VT_REAL)
return src;
NetNet*tmp = new NetNet(scope, scope->local_symbol(), NetNet::WIRE);
netvector_t*tmp_vec = new netvector_t(IVL_VT_REAL);
NetNet*tmp = new NetNet(scope, scope->local_symbol(), NetNet::WIRE, tmp_vec);
tmp->set_line(*src);
tmp->data_type(IVL_VT_REAL);
tmp->local_flag(true);
NetCastReal*cast = new NetCastReal(scope, scope->local_symbol(), src->get_signed());
@ -149,6 +152,16 @@ NetExpr* cast_to_int2(NetExpr*expr)
return cast;
}
NetExpr* cast_to_real(NetExpr*expr)
{
if (expr->expr_type() == IVL_VT_REAL)
return expr;
NetECast*cast = new NetECast('r', expr, 1, true);
cast->set_line(*expr);
return cast;
}
/*
* Add a signed constant to an existing expression. Generate a new
* NetEBAdd node that has the input expression and an expression made
@ -350,7 +363,7 @@ NetExpr *normalize_variable_base(NetExpr *base,
NetExpr *normalize_variable_bit_base(const list<long>&indices, NetExpr*base,
const NetNet*reg)
{
const list<netrange_t>&packed_dims = reg->packed_dims();
const vector<netrange_t>&packed_dims = reg->packed_dims();
ivl_assert(*base, indices.size()+1 == packed_dims.size());
// Get the canonical offset of the slice within which we are
@ -366,7 +379,7 @@ NetExpr *normalize_variable_part_base(const list<long>&indices, NetExpr*base,
const NetNet*reg,
unsigned long wid, bool is_up)
{
const list<netrange_t>&packed_dims = reg->packed_dims();
const vector<netrange_t>&packed_dims = reg->packed_dims();
ivl_assert(*base, indices.size()+1 == packed_dims.size());
// Get the canonical offset of the slice within which we are
@ -381,10 +394,10 @@ NetExpr *normalize_variable_part_base(const list<long>&indices, NetExpr*base,
NetExpr *normalize_variable_slice_base(const list<long>&indices, NetExpr*base,
const NetNet*reg, unsigned long&lwid)
{
const list<netrange_t>&packed_dims = reg->packed_dims();
const vector<netrange_t>&packed_dims = reg->packed_dims();
ivl_assert(*base, indices.size() < packed_dims.size());
list<netrange_t>::const_iterator pcur = packed_dims.end();
vector<netrange_t>::const_iterator pcur = packed_dims.end();
for (size_t idx = indices.size() ; idx < packed_dims.size(); idx += 1) {
-- pcur;
}
@ -630,9 +643,9 @@ NetNet* make_const_x(Design*des, NetScope*scope, unsigned long wid)
NetConst*res = new NetConst(scope, scope->local_symbol(), xxx);
des->add_node(res);
NetNet*sig = new NetNet(scope, scope->local_symbol(), NetNet::WIRE, wid);
netvector_t*sig_vec = new netvector_t(IVL_VT_LOGIC, wid-1, 0);
NetNet*sig = new NetNet(scope, scope->local_symbol(), NetNet::WIRE, sig_vec);
sig->local_flag(true);
sig->data_type(IVL_VT_LOGIC);
connect(sig->pin(0), res->pin(0));
return sig;
@ -1179,8 +1192,8 @@ NetExpr*collapse_array_exprs(Design*des, NetScope*scope,
return *exprs.begin();
}
const std::list<netrange_t>&pdims = net->packed_dims();
std::list<netrange_t>::const_iterator pcur = pdims.begin();
const std::vector<netrange_t>&pdims = net->packed_dims();
std::vector<netrange_t>::const_iterator pcur = pdims.begin();
list<NetExpr*>::iterator ecur = exprs.begin();
NetExpr* base = 0;

View File

@ -79,6 +79,7 @@ extern NetNet*cast_to_int2(Design*des, NetScope*scope, NetNet*src, unsigned wid)
extern NetNet*cast_to_real(Design*des, NetScope*scope, NetNet*src);
extern NetExpr*cast_to_int2(NetExpr*expr);
extern NetExpr*cast_to_real(NetExpr*expr);
/*
* Take the input expression and return a variation that assures that

57
netparray.cc Normal file
View File

@ -0,0 +1,57 @@
/*
* Copyright (c) 2012 Picture Elements, Inc.
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
# include "netparray.h"
using namespace std;
netparray_t::~netparray_t()
{
}
/*
* The packed width of a packed array is the packed width of the
* element times the dimension width of the array itself.
*/
long netparray_t::packed_width(void) const
{
long cur_width = element_type()->packed_width();
for (vector<netrange_t>::const_iterator cur = packed_dims_.begin()
; cur != packed_dims_.end() ; ++cur) {
cur_width *= cur->width();
}
return cur_width;
}
vector<netrange_t> netparray_t::slice_dimensions() const
{
vector<netrange_t> elem_dims = element_type()->slice_dimensions();
vector<netrange_t> res (packed_dims_.size() + elem_dims.size());
for (size_t idx = 0 ; idx < packed_dims_.size() ; idx += 1)
res[idx] = packed_dims_[0];
for (size_t idx = 0 ; idx < elem_dims.size() ; idx += 1)
res[idx+packed_dims_.size()] = elem_dims[idx];
return res;
}

View File

@ -20,33 +20,36 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
# include "LineInfo.h"
# include "nettypes.h"
# include <vector>
/*
* Packed arrays.
*/
class netparray_t : public nettype_base_t, public LineInfo {
class netparray_t : public netarray_t {
public:
explicit netparray_t(const std::list<netrange_t>&packed);
explicit netparray_t(const std::vector<netrange_t>&packed,
ivl_type_t etype);
~netparray_t();
inline const std::list<netrange_t>& packed_dimensions() const
public:
// Virtual methods from the ivl_type_s type...
long packed_width(void) const;
std::vector<netrange_t> slice_dimensions() const;
public:
inline const std::vector<netrange_t>& packed_dimensions() const
{ return packed_dims_; }
private:
std::list<netrange_t> packed_dims_;
std::vector<netrange_t> packed_dims_;
};
inline netparray_t::netparray_t(const std::list<netrange_t>&packed)
: packed_dims_(packed)
{
}
inline netparray_t::~netparray_t()
inline netparray_t::netparray_t(const std::vector<netrange_t>&packed,
ivl_type_t etype)
: netarray_t(etype), packed_dims_(packed)
{
}

View File

@ -66,3 +66,23 @@ long netstruct_t::packed_width(void) const
return res;
}
vector<netrange_t> netstruct_t::slice_dimensions() const
{
vector<netrange_t> tmp;
tmp .push_back(netrange_t(packed_width()-1, 0));
return tmp;
}
ivl_variable_type_t netstruct_t::base_type() const
{
if (! packed_)
return IVL_VT_NO_TYPE;
for (size_t idx = 0 ; idx < members_.size() ; idx += 1) {
if (members_[idx].data_type() != IVL_VT_BOOL)
return members_[idx].data_type();
}
return IVL_VT_BOOL;
}

View File

@ -20,17 +20,17 @@
*/
# include "LineInfo.h"
# include <vector>
# include <vector>
# include "ivl_target.h"
# include "nettypes.h"
class netstruct_t : public LineInfo, public nettype_base_t {
class netstruct_t : public LineInfo, public ivl_type_s {
public:
struct member_t {
perm_string name;
ivl_variable_type_t type;
list<netrange_t> packed_dims;
std::vector<netrange_t> packed_dims;
long width() const;
ivl_variable_type_t data_type() const { return type; };
// We need to keep the individual element sign information.
@ -54,6 +54,11 @@ class netstruct_t : public LineInfo, public nettype_base_t {
// Return the width (in bits) of the packed record, or -1 if
// the record is not packed.
long packed_width() const;
std::vector<netrange_t> slice_dimensions() const;
// Return the base type of the packed record, or
// IVL_VT_NO_TYPE if the record is not packed.
ivl_variable_type_t base_type() const;
private:
bool packed_;

View File

@ -22,19 +22,43 @@
using namespace std;
nettype_base_t::~nettype_base_t()
ivl_type_s::~ivl_type_s()
{
}
long nettype_base_t::packed_width(void) const
long ivl_type_s::packed_width(void) const
{
return 0;
return 1;
}
unsigned long netrange_width(const list<netrange_t>&packed)
vector<netrange_t> ivl_type_s::slice_dimensions() const
{
return vector<netrange_t>();
}
ivl_variable_type_t ivl_type_s::base_type() const
{
return IVL_VT_NO_TYPE;
}
bool ivl_type_s::get_signed() const
{
return false;
}
netarray_t::~netarray_t()
{
}
ivl_variable_type_t netarray_t::base_type() const
{
return element_type_->base_type();
}
unsigned long netrange_width(const vector<netrange_t>&packed)
{
unsigned wid = 1;
for (list<netrange_t>::const_iterator cur = packed.begin()
for (vector<netrange_t>::const_iterator cur = packed.begin()
; cur != packed.end() ; ++cur) {
unsigned use_wid = cur->width();
wid *= use_wid;
@ -49,14 +73,14 @@ unsigned long netrange_width(const list<netrange_t>&packed)
* and width of the resulting slice. In this case, the "sb" argument
* is an extra index of the prefix.
*/
bool prefix_to_slice(const std::list<netrange_t>&dims,
bool prefix_to_slice(const std::vector<netrange_t>&dims,
const std::list<long>&prefix, long sb,
long&loff, unsigned long&lwid)
{
assert(prefix.size() < dims.size());
size_t acc_wid = 1;
list<netrange_t>::const_iterator pcur = dims.end();
vector<netrange_t>::const_iterator pcur = dims.end();
for (size_t idx = prefix.size()+1 ; idx < dims.size() ; idx += 1) {
-- pcur;
acc_wid *= pcur->width();

View File

@ -19,20 +19,58 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
# include <list>
# include <climits>
# include <cassert>
# include "ivl_target.h"
# include <list>
# include <vector>
# include <climits>
# include <ostream>
# include <cassert>
class netrange_t;
/*
* This is a fully abstract type that is a type that can be attached
* to a NetNet object.
*/
class nettype_base_t {
class ivl_type_s {
public:
virtual ~nettype_base_t() =0;
virtual ~ivl_type_s() =0;
virtual long packed_width(void) const;
virtual std::vector<netrange_t> slice_dimensions() const;
// Some types have a base variable type.
virtual ivl_variable_type_t base_type() const;
virtual bool get_signed() const;
virtual std::ostream& debug_dump(std::ostream&) const;
};
/*
* There are a couple types of array types. This class represents the
* common bits of array types.
*/
class netarray_t : public ivl_type_s {
public:
inline explicit netarray_t(ivl_type_t etype) : element_type_(etype) { }
~netarray_t();
public:
// Some virtual methods have a common implementation for arrays.
ivl_variable_type_t base_type() const;
public:
inline ivl_type_t element_type() const { return element_type_; }
private:
ivl_type_t element_type_;
};
inline static std::ostream& operator << (std::ostream&out, const ivl_type_s&obj)
{
return obj.debug_dump(out);
}
class netrange_t {
public:
@ -65,14 +103,17 @@ class netrange_t {
long lsb_;
};
extern unsigned long netrange_width(const std::list<netrange_t>&dims);
extern std::ostream&operator << (std::ostream&out, const std::list<netrange_t>&rlist);
extern std::ostream&operator << (std::ostream&out, const std::vector<netrange_t>&rlist);
extern unsigned long netrange_width(const std::vector<netrange_t>&dims);
/*
* Take as input a list of packed dimensions and a list of prefix
* indices, and calculate the offset/width of the resulting slice into
* the packed array.
*/
extern bool prefix_to_slice(const std::list<netrange_t>&dims,
extern bool prefix_to_slice(const std::vector<netrange_t>&dims,
const std::list<long>&prefix, long sb,
long&loff, unsigned long&lwid);

52
netvector.cc Normal file
View File

@ -0,0 +1,52 @@
/*
* Copyright (c) 2012 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
# include "netvector.h"
using namespace std;
netvector_t::netvector_t(ivl_variable_type_t type, long msb, long lsb)
: type_(type), signed_(false)
{
packed_dims_.push_back(netrange_t(msb,lsb));
}
netvector_t::netvector_t(ivl_variable_type_t type)
: type_(type), signed_(false)
{
}
netvector_t::~netvector_t()
{
}
ivl_variable_type_t netvector_t::base_type() const
{
return type_;
}
long netvector_t::packed_width() const
{
return netrange_width(packed_dims_);
}
vector<netrange_t> netvector_t::slice_dimensions() const
{
return packed_dims_;
}

91
netvector.h Normal file
View File

@ -0,0 +1,91 @@
#ifndef __netvector_H
#define __netvector_H
/*
* Copyright (c) 2012 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
# include "nettypes.h"
# include "ivl_target.h"
# include <vector>
class netvector_t : public ivl_type_s {
public:
explicit netvector_t(const std::vector<netrange_t>&packed,
ivl_variable_type_t type);
// This is a variant of the vector form. Some code processes
// the list of packed ranges as a list, but we will store them
// as a vector in this constructor.
explicit netvector_t(const std::list<netrange_t>&packed,
ivl_variable_type_t type);
// special case: there is a single packed dimension and we
// know it in the form [<msb>:<lsb>]. This step saves me
// creating a netrange_t for this single item.
explicit netvector_t(ivl_variable_type_t type, long msb, long lsb);
// Special case: scaler object--no packed dimenions at all.
explicit netvector_t(ivl_variable_type_t type);
~netvector_t();
// Vectors can be interpreted as signed or unsigned when
// handled as vectors.
inline void set_signed(bool flag) { signed_ = flag; }
inline bool get_signed(void) const { return signed_; }
inline void set_isint(bool flag) { isint_ = flag; }
inline bool get_isint(void) const { return isint_; }
inline void set_scalar(bool flag) { is_scalar_ = flag; }
inline bool get_scalar(void) const { return is_scalar_; }
ivl_variable_type_t base_type() const;
const std::vector<netrange_t>&packed_dims() const;
long packed_width() const;
std::vector<netrange_t> slice_dimensions() const;
std::ostream& debug_dump(std::ostream&) const;
private:
std::vector<netrange_t> packed_dims_;
ivl_variable_type_t type_;
bool signed_ : 1;
bool isint_ : 1; // original type of integer
bool is_scalar_ : 1;
};
inline netvector_t::netvector_t(const std::vector<netrange_t>&packed,
ivl_variable_type_t type)
: packed_dims_(packed), type_(type), signed_(false)
{
}
inline const std::vector<netrange_t>& netvector_t::packed_dims() const
{
return packed_dims_;
}
inline static std::ostream& operator << (std::ostream&out, const netvector_t&obj)
{
return obj.debug_dump(out);
}
#endif

View File

@ -20,6 +20,7 @@
# include "config.h"
# include "netlist.h"
# include "netvector.h"
# include "netmisc.h"
@ -77,19 +78,20 @@ NetNet*pad_to_width(Design*des, NetNet*net, unsigned wid, const LineInfo&info)
connect(cc->pin(2), con->pin(0));
// Make a NetNet for the NetConst to NetConcat link.
netvector_t*tmp_vec = new netvector_t(net->data_type(),
wid - net->vector_width() - 1, 0);
NetNet*tmp = new NetNet(scope, scope->local_symbol(),
NetNet::WIRE, wid - net->vector_width());
NetNet::WIRE, tmp_vec);
tmp->set_line(info);
tmp->data_type( net->data_type() );
tmp->local_flag(true);
connect(cc->pin(2), tmp->pin(0));
// Create a NetNet of the output width and connect it to the
// NetConcat node output pin.
tmp_vec = new netvector_t(net->data_type(), wid-1, 0);
tmp = new NetNet(scope, scope->local_symbol(),
NetNet::WIRE, wid);
NetNet::WIRE, tmp_vec);
tmp->set_line(info);
tmp->data_type( net->data_type() );
tmp->local_flag(true);
connect(cc->pin(0), tmp->pin(0));
@ -109,11 +111,11 @@ NetNet*pad_to_width_signed(Design*des, NetNet*net, unsigned wid,
se->set_line(info);
des->add_node(se);
NetNet*tmp = new NetNet(scope, scope->local_symbol(), NetNet::WIRE, wid);
netvector_t*tmp_vec = new netvector_t(net->data_type(), wid-1, 0);
tmp_vec->set_signed(true);
NetNet*tmp = new NetNet(scope, scope->local_symbol(), NetNet::WIRE, tmp_vec);
tmp->set_line(info);
tmp->local_flag(true);
tmp->data_type(net->data_type());
tmp->set_signed(true);
connect(tmp->pin(0), se->pin(0));
connect(se->pin(1), net->pin(0));
@ -132,10 +134,10 @@ NetNet*crop_to_width(Design*des, NetNet*net, unsigned wid)
ps->set_line(*net);
des->add_node(ps);
netvector_t*tmp_vec = new netvector_t(net->data_type(), wid-1, 0);
NetNet*tmp = new NetNet(scope, scope->local_symbol(),
NetNet::WIRE, wid);
NetNet::WIRE, tmp_vec);
tmp->set_line(*net);
tmp->data_type(net->data_type());
tmp->local_flag(true);
connect(ps->pin(0), tmp->pin(0));

View File

@ -153,6 +153,28 @@ void parray_type_t::pform_dump(ostream&out, unsigned indent) const
base_type->pform_dump(out, indent+4);
}
void struct_type_t::pform_dump(ostream&out, unsigned indent) const
{
out << setw(indent) << "" << "Struct " << (packed_flag?"packed":"unpacked")
<< " with " << members->size() << " members" << endl;
for (list<struct_member_t*>::iterator cur = members->begin()
; cur != members->end() ; ++ cur) {
struct_member_t*curp = *cur;
curp->pform_dump(out, indent+4);
}
}
void struct_member_t::pform_dump(ostream&out, unsigned indent) const
{
out << setw(indent) << "" << type;
for (list<decl_assignment_t*>::iterator cur = names->begin()
; cur != names->end() ; ++cur) {
decl_assignment_t*curp = *cur;
out << " " << curp->name;
}
out << ";" << endl;
}
static void dump_attributes_map(ostream&out,
const map<perm_string,PExpr*>&attributes,
int ind)

View File

@ -97,10 +97,13 @@ struct struct_member_t : public LineInfo {
ivl_variable_type_t type;
std::auto_ptr< list<pform_range_t> > range;
std::auto_ptr< list<decl_assignment_t*> > names;
void pform_dump(std::ostream&out, unsigned indent) const;
};
struct struct_type_t : public data_type_t {
virtual ivl_variable_type_t figure_packed_base_type(void)const;
virtual void pform_dump(std::ostream&out, unsigned indent) const;
bool packed_flag;
std::auto_ptr< list<struct_member_t*> > members;
};

View File

@ -21,6 +21,7 @@
# include "functor.h"
# include "netlist.h"
# include "netvector.h"
# include "netmisc.h"
# include "compiler.h"
# include <cassert>
@ -221,10 +222,10 @@ bool NetCase::synth_async(Design*des, NetScope*scope,
continue;
}
netvector_t*isig_vec = new netvector_t(mux_data_type, mux_width-1, 0);
isig = new NetNet(scope, scope->local_symbol(),
NetNet::TRI, mux_width);
NetNet::TRI, isig_vec);
isig->local_flag(true);
isig->data_type(mux_data_type);
connect(mux->pin_Data(idx), isig->pin(0));

View File

@ -21,7 +21,9 @@
# include "StringHeap.h"
# include "t-dll.h"
# include "discipline.h"
# include "netdarray.h"
# include "netenum.h"
# include "netvector.h"
# include <cstdlib>
# include <cstdio>
# include <cstring>
@ -265,7 +267,7 @@ extern "C" unsigned ivl_enum_width(ivl_enumtype_t net)
extern "C" int ivl_enum_signed(ivl_enumtype_t net)
{
assert(net);
return net->has_sign();
return net->get_signed();
}
extern "C" const char*ivl_enum_file(ivl_enumtype_t net)
@ -411,6 +413,11 @@ extern "C" ivl_enumtype_t ivl_expr_enumtype(ivl_expr_t net)
return net->u_.enumtype_.type;
}
extern "C" ivl_type_t ivl_expr_net_type(ivl_expr_t net)
{
return net->net_type;
}
extern "C" const char* ivl_expr_name(ivl_expr_t net)
{
switch (net->type_) {
@ -1422,7 +1429,7 @@ extern "C" int ivl_lpm_signed(ivl_lpm_t net)
case IVL_LPM_REPEAT:
return 0;
case IVL_LPM_ARRAY: // Array ports take the signedness of the array.
return net->u_.array.sig->signed_;
return net->u_.array.sig->net_type->get_signed()? 1 : 0;
default:
assert(0);
return 0;
@ -2231,7 +2238,7 @@ extern "C" ivl_scope_t ivl_signal_scope(ivl_signal_t net)
extern "C" unsigned ivl_signal_width(ivl_signal_t net)
{
return net->width_;
return net->net_type->packed_width();
}
extern "C" ivl_signal_port_t ivl_signal_port(ivl_signal_t net)
@ -2251,7 +2258,7 @@ extern "C" int ivl_signal_local(ivl_signal_t net)
extern "C" int ivl_signal_signed(ivl_signal_t net)
{
return net->signed_;
return net->net_type->get_signed()? 1 : 0;
}
extern "C" unsigned ivl_signal_forced_net(ivl_signal_t net)
@ -2273,12 +2280,20 @@ extern "C" unsigned ivl_signal_lineno(ivl_signal_t net)
extern "C" int ivl_signal_integer(ivl_signal_t net)
{
return net->isint_;
if (const netvector_t*vec = dynamic_cast<const netvector_t*> (net->net_type))
return vec->get_isint()? 1 : 0;
else
return 0;
}
extern "C" ivl_variable_type_t ivl_signal_data_type(ivl_signal_t net)
{
return net->data_type;
return net->net_type->base_type();
}
extern "C" ivl_type_t ivl_signal_net_type(ivl_signal_t net)
{
return net->net_type;
}
extern "C" unsigned ivl_signal_npath(ivl_signal_t net)
@ -2773,3 +2788,38 @@ extern "C" unsigned ivl_switch_lineno(ivl_switch_t net)
{
return net->lineno;
}
extern "C" ivl_variable_type_t ivl_type_base(ivl_type_t net)
{
if (net == 0) return IVL_VT_NO_TYPE;
else return net->base_type();
}
extern "C" ivl_type_t ivl_type_element(ivl_type_t net)
{
if (const netarray_t*da = dynamic_cast<const netarray_t*> (net))
return da->element_type();
assert(0);
return 0;
}
extern "C" unsigned ivl_type_packed_dimensions(ivl_type_t net)
{
vector<netrange_t> slice = net->slice_dimensions();
return slice.size();
}
extern "C" int ivl_type_packed_lsb(ivl_type_t net, unsigned dim)
{
vector<netrange_t> slice = net->slice_dimensions();
assert(dim < slice.size());
return slice[dim].get_lsb();
}
extern "C" int ivl_type_packed_msb(ivl_type_t net, unsigned dim)
{
vector<netrange_t> slice = net->slice_dimensions();
assert(dim < slice.size());
return slice[dim].get_msb();
}

View File

@ -56,6 +56,7 @@ void dll_target::sub_off_from_expr_(long off)
ivl_expr_t tmpc = (ivl_expr_t)calloc(1, sizeof(struct ivl_expr_s));
tmpc->type_ = IVL_EX_NUMBER;
tmpc->value_ = IVL_VT_VECTOR;
tmpc->net_type= 0;
tmpc->width_ = expr_->width_;
tmpc->signed_ = expr_->signed_;
tmpc->sized_ = 1;
@ -71,6 +72,7 @@ void dll_target::sub_off_from_expr_(long off)
ivl_expr_t tmps = (ivl_expr_t)calloc(1, sizeof(struct ivl_expr_s));
tmps->type_ = IVL_EX_BINARY;
tmps->value_ = IVL_VT_VECTOR;
tmps->net_type= 0;
tmps->width_ = tmpc->width_;
tmps->signed_ = tmpc->signed_;
tmps->sized_ = 1;
@ -90,6 +92,7 @@ void dll_target::mul_expr_by_const_(long val)
ivl_expr_t tmpc = (ivl_expr_t)calloc(1, sizeof(struct ivl_expr_s));
tmpc->type_ = IVL_EX_NUMBER;
tmpc->value_ = IVL_VT_VECTOR;
tmpc->net_type= 0;
tmpc->width_ = expr_->width_;
tmpc->signed_ = expr_->signed_;
tmpc->sized_ = 1;
@ -105,6 +108,7 @@ void dll_target::mul_expr_by_const_(long val)
ivl_expr_t tmps = (ivl_expr_t)calloc(1, sizeof(struct ivl_expr_s));
tmps->type_ = IVL_EX_BINARY;
tmps->value_ = IVL_VT_VECTOR;
tmpc->net_type= 0;
tmps->width_ = tmpc->width_;
tmps->signed_ = tmpc->signed_;
tmps->sized_ = 1;
@ -124,6 +128,7 @@ ivl_expr_t dll_target::expr_from_value_(const verinum&val)
char*bits;
expr->type_ = IVL_EX_NUMBER;
expr->value_= IVL_VT_VECTOR;
expr->net_type=0;
expr->width_= val.len();
expr->signed_ = val.has_sign()? 1 : 0;
expr->sized_= 1;
@ -158,6 +163,7 @@ void dll_target::expr_access_func(const NetEAccess*net)
expr_ = (ivl_expr_t)calloc(1, sizeof(struct ivl_expr_s));
expr_->type_ = IVL_EX_BACCESS;
expr_->value_ = IVL_VT_REAL;
expr_->net_type=0;
expr_->width_ = 1;
expr_->signed_= 1;
expr_->sized_ = 1;
@ -182,6 +188,7 @@ void dll_target::expr_binary(const NetEBinary*net)
expr_->type_ = IVL_EX_BINARY;
expr_->value_= get_expr_type(net);
expr_->net_type=0;
expr_->width_= net->expr_width();
expr_->signed_ = net->has_sign()? 1 : 0;
expr_->sized_= 1;
@ -201,6 +208,7 @@ void dll_target::expr_concat(const NetEConcat*net)
cur->type_ = IVL_EX_CONCAT;
cur->value_ = net->expr_type();
cur->net_type=0;
cur->width_ = net->expr_width();
cur->signed_ = net->has_sign() ? 1 : 0;
cur->sized_ = 1;
@ -226,6 +234,7 @@ void dll_target::expr_const(const NetEConst*net)
expr_ = (ivl_expr_t)calloc(1, sizeof(struct ivl_expr_s));
expr_->value_= net->expr_type();
expr_->net_type=0;
FILE_NAME(expr_, net);
if (net->value().is_string()) {
@ -303,6 +312,7 @@ void dll_target::expr_creal(const NetECReal*net)
expr_->type_ = IVL_EX_REALNUM;
FILE_NAME(expr_, net);
expr_->value_= IVL_VT_REAL;
expr_->net_type=0;
expr_->u_.real_.value = net->value().as_double();
}
@ -315,6 +325,7 @@ void dll_target::expr_event(const NetEEvent*net)
expr_->type_ = IVL_EX_EVENT;
FILE_NAME(expr_, net);
expr_->value_= IVL_VT_VOID;
expr_->net_type=0;
/* Locate the event by name. Save the ivl_event_t in the
expression so that the generator can find it easily. */
@ -339,6 +350,7 @@ void dll_target::expr_scope(const NetEScope*net)
expr_->type_ = IVL_EX_SCOPE;
FILE_NAME(expr_, net);
expr_->value_= IVL_VT_VOID;
expr_->net_type=0;
expr_->u_.scope_.scope = lookup_scope_(net->scope());
}
@ -351,6 +363,7 @@ void dll_target::expr_netenum(const NetENetenum*net)
expr_->type_ = IVL_EX_ENUMTYPE;
FILE_NAME(expr_, net);
expr_->value_= IVL_VT_VOID;
expr_->net_type=0;
expr_->u_.enumtype_.type = net->netenum();
}
@ -370,7 +383,8 @@ void dll_target::expr_select(const NetESelect*net)
expr_ = (ivl_expr_t)calloc(1, sizeof(struct ivl_expr_s));
expr_->type_ = IVL_EX_SELECT;
expr_->value_= IVL_VT_VECTOR;
expr_->value_= net->expr_type();
expr_->net_type=0;
expr_->width_= net->expr_width();
expr_->signed_ = net->has_sign()? 1 : 0;
expr_->sized_= 1;
@ -390,6 +404,7 @@ void dll_target::expr_sfunc(const NetESFunc*net)
expr->type_ = IVL_EX_SFUNC;
FILE_NAME(expr, net);
expr->value_= net->expr_type();
expr->net_type=net->net_type();
expr->width_= net->expr_width();
expr->signed_ = net->has_sign()? 1 : 0;
expr->sized_= 1;
@ -420,6 +435,7 @@ void dll_target::expr_ternary(const NetETernary*net)
expr->type_ = IVL_EX_TERNARY;
expr->value_= net->expr_type();
expr->net_type=0;
expr->width_ = net->expr_width();
expr->signed_ = net->has_sign()? 1 : 0;
expr->sized_ = 1;
@ -461,6 +477,7 @@ void dll_target::expr_signal(const NetESignal*net)
expr_->type_ = IVL_EX_SIGNAL;
expr_->value_= net->expr_type();
expr_->net_type=0;
expr_->width_= net->expr_width();
expr_->signed_ = net->has_sign()? 1 : 0;
expr_->sized_= 1;
@ -488,6 +505,7 @@ void dll_target::expr_ufunc(const NetEUFunc*net)
expr->type_ = IVL_EX_UFUNC;
expr->value_= net->expr_type();
expr->net_type=0;
expr->width_= net->expr_width();
expr->signed_ = net->has_sign()? 1 : 0;
expr->sized_= 1;
@ -523,6 +541,7 @@ void dll_target::expr_unary(const NetEUnary*net)
expr_ = (ivl_expr_t)calloc(1, sizeof(struct ivl_expr_s));
expr_->type_ = IVL_EX_UNARY;
expr_->value_= net->expr_type();
expr_->net_type=0;
expr_->width_ = net->expr_width();
expr_->signed_ = net->has_sign()? 1 : 0;
expr_->sized_ = 1;

View File

@ -2374,7 +2374,7 @@ void dll_target::signal(const NetNet*net)
ivl_signal_t object. */
{ size_t idx = 0;
list<netrange_t>::const_iterator cur;
vector<netrange_t>::const_iterator cur;
obj->packed_dims.resize(net->packed_dims().size());
for (cur = net->packed_dims().begin(), idx = 0
; cur != net->packed_dims().end() ; ++cur, idx += 1) {
@ -2382,9 +2382,7 @@ void dll_target::signal(const NetNet*net)
}
}
obj->width_ = net->vector_width();
obj->signed_= net->get_signed()? 1 : 0;
obj->isint_ = false;
obj->net_type = net->net_type();
obj->local_ = net->local_flag()? 1 : 0;
obj->forced_net_ = (net->type() != NetNet::REG) &&
(net->peek_lref() > 0) ? 1 : 0;
@ -2418,7 +2416,6 @@ void dll_target::signal(const NetNet*net)
case NetNet::REG:
obj->type_ = IVL_SIT_REG;
obj->isint_ = net->get_isint();
break;
/* The SUPPLY0/1 net types are replaced with pulldown/up
@ -2469,15 +2466,9 @@ void dll_target::signal(const NetNet*net)
obj->npath = 0;
obj->path = 0;
obj->data_type = net->data_type();
obj->nattr = net->attr_cnt();
obj->attr = fill_in_attributes(net);
/* If this is a dynamic array, then set the type to DARRAY. */
if (net->darray_type()) {
obj->data_type = IVL_VT_DARRAY;
}
/* 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

View File

@ -218,6 +218,7 @@ struct ivl_event_s {
struct ivl_expr_s {
ivl_expr_type_t type_;
ivl_variable_type_t value_;
ivl_type_t net_type;
perm_string file;
unsigned lineno;
@ -677,14 +678,12 @@ struct ivl_signal_s {
ivl_signal_type_t type_;
ivl_signal_port_t port_;
int module_port_index_;
ivl_variable_type_t data_type;
ivl_discipline_t discipline;
perm_string file;
unsigned lineno;
unsigned width_;
unsigned signed_ : 1;
unsigned isint_ : 1;
// This is the type for the signal
ivl_type_t net_type;
unsigned local_ : 1;
unsigned forced_net_ : 1;

View File

@ -44,7 +44,7 @@ CPPFLAGS = $(INCLUDE_PATH) @CPPFLAGS@ @DEFS@ @PICFLAG@
CFLAGS = @WARNING_FLAGS@ @CFLAGS@
LDFLAGS = @LDFLAGS@
O = stub.o enumerate.o expression.o statement.o switches.o
O = stub.o enumerate.o expression.o statement.o switches.o types.o
all: dep stub.tgt

View File

@ -169,6 +169,7 @@ static void show_select_expression(ivl_expr_t net, unsigned ind)
{
unsigned width = ivl_expr_width(net);
const char*sign = ivl_expr_signed(net)? "signed" : "unsigned";
const char*vt = vt_type_string(net);
ivl_expr_t oper1 = ivl_expr_oper1(net);
ivl_expr_t oper2 = ivl_expr_oper2(net);
@ -177,17 +178,26 @@ static void show_select_expression(ivl_expr_t net, unsigned ind)
substring and the code generator will handle it
differently. */
fprintf(out, "%*s<substring: width=%u bits, %u bytes>\n", ind, "", width, width/8);
if (width%8 != 0)
if (width%8 != 0) {
fprintf(out, "%*sERROR: Width should be a multiple of 8 bits.\n", ind, "");
stub_errors += 1;
}
assert(oper1);
show_expression(oper1, ind+3);
show_expression(oper2, ind+3);
if (oper2) {
show_expression(oper2, ind+3);
} else {
fprintf(out, "%*sERROR: oper2 missing! Pad makes no sense for IVL_VT_STRING expressions.\n", ind+3, "");
stub_errors += 1;
}
} else if (oper2) {
/* If oper2 is present, then it is the base of a part
select. The width of the expression defines the range
of the part select. */
fprintf(out, "%*s<select: width=%u, %s>\n", ind, "",
width, sign);
fprintf(out, "%*s<select: width=%u, %s, type=%s>\n", ind, "",
width, sign, vt);
show_expression(oper1, ind+3);
show_expression(oper2, ind+3);
@ -233,6 +243,14 @@ static void show_signal_expression(ivl_expr_t net, unsigned ind)
fprintf(out, "%*sERROR: Missing word expression\n", ind+2, "");
stub_errors += 1;
}
/* If this is not an array, then the expression with must
match the signal width. We have IVL_EX_SELECT expressions
for casting signal widths. */
if (dimensions == 0 && ivl_signal_width(sig) != width) {
fprintf(out, "%*sERROR: Expression width (%u) doesn't match ivl_signal_width(sig)=%u\n",
ind+2, "", width, ivl_signal_width(sig));
stub_errors += 1;
}
if (word != 0) {
fprintf(out, "%*sAddress-0 word address:\n", ind+2, "");
@ -294,9 +312,10 @@ void show_unary_expression(ivl_expr_t net, unsigned ind)
void show_expression(ivl_expr_t net, unsigned ind)
{
assert(net);
unsigned idx;
const ivl_expr_type_t code = ivl_expr_type(net);
ivl_parameter_t par = ivl_expr_parameter(net);
const ivl_expr_type_t code = ivl_expr_type(net);
unsigned width = ivl_expr_width(net);
const char*sign = ivl_expr_signed(net)? "signed" : "unsigned";
const char*sized = ivl_expr_sized(net)? "sized" : "unsized";

View File

@ -61,6 +61,11 @@ extern void show_expression(ivl_expr_t net, unsigned ind);
*/
extern void show_statement(ivl_statement_t net, unsigned ind);
/*
* Show the type of the signal, in one line.
*/
extern void show_type_of_signal(ivl_signal_t);
extern void show_switch(ivl_switch_t net);
/*

View File

@ -31,7 +31,9 @@ static unsigned show_assign_lval_darray(ivl_lval_t lval, unsigned ind)
assert(sig);
if (ivl_lval_idx(lval)) {
fprintf(out, "%*sAddress-0 select of dynamic array:\n", ind+4, "");
fprintf(out, "%*sAddress-0 select of ", ind+4, "");
show_type_of_signal(sig);
fprintf(out, ":\n");
show_expression(ivl_lval_idx(lval), ind+6);
}

View File

@ -1222,7 +1222,6 @@ static void show_signal(ivl_signal_t net)
const char*type = "?";
const char*port = "";
const char*data_type = "?";
const char*sign = ivl_signal_signed(net)? "signed" : "unsigned";
switch (ivl_signal_type(net)) {
@ -1263,32 +1262,6 @@ static void show_signal(ivl_signal_t net)
break;
}
data_type = "?data?";
switch (ivl_signal_data_type(net)) {
case IVL_VT_NO_TYPE:
data_type = "<no-type>";
break;
case IVL_VT_BOOL:
data_type = "bool";
break;
case IVL_VT_LOGIC:
data_type = "logic";
break;
case IVL_VT_REAL:
data_type = "real";
break;
case IVL_VT_STRING:
data_type = "string";
break;
case IVL_VT_DARRAY:
data_type = "darray";
break;
case IVL_VT_VOID:
data_type = "void";
break;
}
const char*discipline_txt = "NONE";
if (ivl_signal_discipline(net)) {
ivl_discipline_t dis = ivl_signal_discipline(net);
@ -1298,13 +1271,9 @@ static void show_signal(ivl_signal_t net)
for (idx = 0 ; idx < ivl_signal_array_count(net) ; idx += 1) {
ivl_nexus_t nex = ivl_signal_nex(net, idx);
unsigned dim;
fprintf(out, " %s %s %s%s", type, sign, port, data_type);
for (dim = 0 ; dim < ivl_signal_packed_dimensions(net) ; dim += 1) {
fprintf(out, "[%d:%d]", ivl_signal_packed_msb(net,dim),
ivl_signal_packed_lsb(net,dim));
}
fprintf(out, " %s %s %s", type, sign, port);
show_type_of_signal(net);
fprintf(out, " %s[word=%u, adr=%d] <width=%u%s> <discipline=%s> ",
ivl_signal_basename(net),
idx, ivl_signal_array_base(net)+idx,
@ -1371,7 +1340,7 @@ static void show_signal(ivl_signal_t net)
switch (ivl_signal_data_type(net)) {
case IVL_VT_NO_TYPE:
case IVL_VT_VOID:
fprintf(out, " ERROR: Invalid type for signal: %s\n", data_type);
fprintf(out, " ERROR: Invalid type for signal.\n");
stub_errors += 1;
break;
default:

123
tgt-stub/types.c Normal file
View File

@ -0,0 +1,123 @@
/*
* Copyright (c) 2012 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
# include "config.h"
# include "priv.h"
# include <string.h>
static void show_net_type(ivl_type_t net_type);
static void show_net_type_darray(ivl_type_t net_type)
{
/* Dynamic arrays have a single element type. */
ivl_type_t element_type = ivl_type_element(net_type);
fprintf(out, "darray of ");
show_net_type(element_type);
}
static void show_net_type(ivl_type_t net_type)
{
ivl_variable_type_t data_type = ivl_type_base(net_type);
switch (data_type) {
case IVL_VT_NO_TYPE:
fprintf(out, "<ERROR-no-type>");
stub_errors += 1;
break;
case IVL_VT_BOOL:
fprintf(out, "bool");
break;
case IVL_VT_LOGIC:
fprintf(out, "logic");
break;
case IVL_VT_REAL:
fprintf(out, "real");
break;
case IVL_VT_STRING:
fprintf(out, "string");
break;
case IVL_VT_DARRAY:
show_net_type_darray(net_type);
break;
case IVL_VT_VOID:
fprintf(out, "void");
break;
}
unsigned packed_dimensions = ivl_type_packed_dimensions(net_type);
unsigned idx;
for (idx = 0 ; idx < packed_dimensions ; idx += 1) {
fprintf(out, "[%d:%d]", ivl_type_packed_msb(net_type, idx),
ivl_type_packed_lsb(net_type, idx));
}
}
void show_type_of_signal(ivl_signal_t net)
{
unsigned dim;
/* The data_type is the base type of the signal. This the the
starting point for the type. In the long run I think I want
to remove this in favor of the ivl_signal_net_type below. */
ivl_variable_type_t data_type = ivl_signal_data_type(net);
/* This gets the more general type description. This is a
newer form so doesn't yet handle all the cases. Newer
types, such DARRAY types, REQUIRE this method to get at the
type details. */
ivl_type_t net_type = ivl_signal_net_type(net);
if (net_type) {
show_net_type(net_type);
return;
}
switch (data_type) {
case IVL_VT_NO_TYPE:
fprintf(out, "<no-type>");
break;
case IVL_VT_BOOL:
fprintf(out, "bool");
break;
case IVL_VT_LOGIC:
fprintf(out, "logic");
break;
case IVL_VT_REAL:
fprintf(out, "real");
break;
case IVL_VT_STRING:
fprintf(out, "string");
break;
case IVL_VT_DARRAY:
/* The DARRAY type MUST be described by an
ivl_signal_net_type object. */
fprintf(out, "ERROR-DARRAY");
stub_errors += 1;
break;
case IVL_VT_VOID:
fprintf(out, "void");
break;
}
for (dim = 0 ; dim < ivl_signal_packed_dimensions(net) ; dim += 1) {
fprintf(out, "[%d:%d]", ivl_signal_packed_msb(net,dim),
ivl_signal_packed_lsb(net,dim));
}
}

View File

@ -419,6 +419,9 @@ static void draw_vpi_taskfunc_args(const char*call_string,
buffer[0] = 0;
break;
default:
fprintf(vvp_out, "\nXXXX Unexpected argument: call_string=<%s>, arg=%d, type=%d\n",
call_string, idx, ivl_expr_value(expr));
fflush(vvp_out);
assert(0);
}
args[idx].text = strdup(buffer);

View File

@ -2471,6 +2471,17 @@ static struct vector_info draw_select_signal(ivl_expr_t expr,
unsigned use_word = 0;
unsigned use_wid, lab_x, lab_end;
/* Special case: the sub expression is a DARRAY variable, so
do a dynamic array word load. */
if (ivl_signal_data_type(sig) == IVL_VT_DARRAY) {
res.base = allocate_vector(wid);
res.wid = wid;
draw_eval_expr_into_integer(bit_idx, 3);
fprintf(vvp_out, " %%load/dar %u, v%p_0, %u;\n",
res.base, sig, res.wid);
return res;
}
/* If this is an access to an array, try to get the index as a
constant. If it is (and the array is not a reg array then
this reduces to a signal access and we stay here. If it is

View File

@ -28,8 +28,41 @@ static int eval_darray_new(ivl_expr_t ex)
draw_eval_expr_into_integer(size_expr, size_reg);
clr_word(size_reg);
// XXXX: Assume elements are 32bit integers.
fprintf(vvp_out, " %%new/darray %u, \"sb32\";\n", size_reg);
// The new function has a net_type that contains the details
// of the type.
ivl_type_t net_type = ivl_expr_net_type(ex);
assert(net_type);
ivl_type_t element_type = ivl_type_element(net_type);
assert(element_type);
switch (ivl_type_base(element_type)) {
case IVL_VT_REAL:
// REAL objects are not packable.
assert(ivl_type_packed_dimensions(element_type) == 0);
fprintf(vvp_out, " %%new/darray %u, \"r\";\n", size_reg);
break;
case IVL_VT_STRING:
// STRING objects are not packable.
assert(ivl_type_packed_dimensions(element_type) == 0);
fprintf(vvp_out, " %%new/darray %u, \"S\";\n", size_reg);
break;
case IVL_VT_BOOL:
// bool objects are vectorable, but for now only support
// a single dimensions.
assert(ivl_type_packed_dimensions(element_type) == 1);
int msb = ivl_type_packed_msb(element_type, 0);
int lsb = ivl_type_packed_lsb(element_type, 0);
int wid = msb>=lsb? msb - lsb : lsb - msb;
wid += 1;
fprintf(vvp_out, " %%new/darray %u, \"sb%d\";\n", size_reg, wid);
break;
default:
assert(0);
break;
}
return 0;
}

View File

@ -256,6 +256,21 @@ static void draw_real_logic_expr(ivl_expr_t expr, int stuff_ok_flag)
clr_vector(sv);
}
static void draw_select_real(ivl_expr_t expr)
{
/* The sube references the expression to be selected from. */
ivl_expr_t sube = ivl_expr_oper1(expr);
/* This is the select expression */
ivl_expr_t shift= ivl_expr_oper2(expr);
/* Assume the sub-expression is a signal */
ivl_signal_t sig = ivl_expr_signal(sube);
assert(ivl_signal_data_type(sig) == IVL_VT_DARRAY);
draw_eval_expr_into_integer(shift, 3);
fprintf(vvp_out, " %%load/dar/r v%p_0;\n", sig);
}
static void draw_sfunc_real(ivl_expr_t expr)
{
switch (ivl_expr_value(expr)) {
@ -492,6 +507,10 @@ void draw_eval_real(ivl_expr_t expr)
draw_realnum_real(expr);
break;
case IVL_EX_SELECT:
draw_select_real(expr);
break;
case IVL_EX_SFUNC:
draw_sfunc_real(expr);
break;

View File

@ -71,6 +71,21 @@ static void string_ex_signal(ivl_expr_t expr)
fallback_eval(expr);
}
static void string_ex_select(ivl_expr_t expr)
{
/* The sube references the expression to be selected from. */
ivl_expr_t sube = ivl_expr_oper1(expr);
/* This is the select expression */
ivl_expr_t shift= ivl_expr_oper2(expr);
/* Assume the sub-expression is a signal */
ivl_signal_t sig = ivl_expr_signal(sube);
assert(ivl_signal_data_type(sig) == IVL_VT_DARRAY);
draw_eval_expr_into_integer(shift, 3);
fprintf(vvp_out, " %%load/dar/str v%p_0;\n", sig);
}
void draw_eval_string(ivl_expr_t expr)
{
@ -87,6 +102,10 @@ void draw_eval_string(ivl_expr_t expr)
string_ex_concat(expr);
break;
case IVL_EX_SELECT:
string_ex_select(expr);
break;
default:
fallback_eval(expr);
break;

View File

@ -767,6 +767,10 @@ static int show_stmt_assign_sig_darray(ivl_statement_t net)
ivl_expr_t rval = ivl_stmt_rval(net);
ivl_expr_t part = ivl_lval_part_off(lval);
ivl_signal_t var= ivl_lval_sig(lval);
ivl_type_t var_type= ivl_signal_net_type(var);
assert(ivl_type_base(var_type) == IVL_VT_DARRAY);
ivl_type_t element_type = ivl_type_element(var_type);
ivl_expr_t mux = ivl_lval_idx(lval);
assert(ivl_stmt_lvals(net) == 1);
@ -774,7 +778,27 @@ static int show_stmt_assign_sig_darray(ivl_statement_t net)
assert(ivl_lval_mux(lval) == 0);
assert(part == 0);
if (mux) {
if (mux && (ivl_type_base(element_type)==IVL_VT_REAL)) {
draw_eval_real(rval);
/* The %set/dar expects the array index to be in index
register 3. Calculate the index in place. */
draw_eval_expr_into_integer(mux, 3);
fprintf(vvp_out, " %%store/dar/r v%p_0;\n", var);
} else if (mux && ivl_type_base(element_type)==IVL_VT_STRING) {
/* Evaluate the rval into the top of the string stack. */
draw_eval_string(rval);
/* The %store/dar/s expects the array index to me in index
register 3. Calculate the index in place. */
draw_eval_expr_into_integer(mux, 3);
fprintf(vvp_out, " %%store/dar/str v%p_0;\n", var);
} else if (mux) {
struct vector_info rvec = draw_eval_expr_wid(rval, ivl_lval_width(lval),
STUFF_OK_XZ);
/* The %set/dar expects the array index to be in index

View File

@ -128,6 +128,8 @@ extern bool of_LOAD_AVP0_S(vthread_t thr, vvp_code_t code);
extern bool of_LOAD_AVX_P(vthread_t thr, vvp_code_t code);
extern bool of_LOAD_DAR(vthread_t thr, vvp_code_t code);
extern bool of_LOAD_REAL(vthread_t thr, vvp_code_t code);
extern bool of_LOAD_DAR_R(vthread_t thr, vvp_code_t code);
extern bool of_LOAD_DAR_STR(vthread_t thr, vvp_code_t code);
extern bool of_LOAD_STR(vthread_t thr, vvp_code_t code);
extern bool of_LOAD_VEC(vthread_t thr, vvp_code_t code);
extern bool of_LOAD_VP0(vthread_t thr, vvp_code_t code);
@ -173,6 +175,8 @@ extern bool of_SET_X0_X(vthread_t thr, vvp_code_t code);
extern bool of_SHIFTL_I0(vthread_t thr, vvp_code_t code);
extern bool of_SHIFTR_I0(vthread_t thr, vvp_code_t code);
extern bool of_SHIFTR_S_I0(vthread_t thr, vvp_code_t code);
extern bool of_STORE_DAR_R(vthread_t thr, vvp_code_t code);
extern bool of_STORE_DAR_STR(vthread_t thr, vvp_code_t code);
extern bool of_STORE_OBJ(vthread_t thr, vvp_code_t code);
extern bool of_STORE_REAL(vthread_t thr, vvp_code_t code);
extern bool of_STORE_REALA(vthread_t thr, vvp_code_t code);

View File

@ -171,13 +171,15 @@ static const struct opcode_table_s opcode_table[] = {
{ "%join/detach",of_JOIN_DETACH,1,{OA_NUMBER,OA_NONE, OA_NONE} },
{ "%load/ar",of_LOAD_AR,2, {OA_ARR_PTR, OA_BIT1, OA_NONE} },
{ "%load/av",of_LOAD_AV,3, {OA_BIT1, OA_ARR_PTR, OA_BIT2} },
{ "%load/avp0",of_LOAD_AVP0,3, {OA_BIT1, OA_ARR_PTR, OA_BIT2} },
{ "%load/avp0/s",of_LOAD_AVP0_S,3,{OA_BIT1, OA_ARR_PTR, OA_BIT2} },
{ "%load/avp0",of_LOAD_AVP0,3, {OA_BIT1, OA_ARR_PTR, OA_BIT2} },
{ "%load/avp0/s",of_LOAD_AVP0_S,3,{OA_BIT1,OA_ARR_PTR, OA_BIT2} },
{ "%load/avx.p",of_LOAD_AVX_P,3,{OA_BIT1, OA_ARR_PTR, OA_BIT2} },
{ "%load/dar",of_LOAD_DAR,3,{OA_BIT1, OA_FUNC_PTR, OA_BIT2} },
{ "%load/real", of_LOAD_REAL,1,{OA_VPI_PTR, OA_NONE, OA_NONE} },
{ "%load/str", of_LOAD_STR, 1,{OA_FUNC_PTR,OA_NONE, OA_NONE} },
{ "%load/v", of_LOAD_VEC,3, {OA_BIT1, OA_FUNC_PTR, OA_BIT2} },
{ "%load/dar/r", of_LOAD_DAR_R, 1, {OA_FUNC_PTR, OA_NONE, OA_NONE}},
{ "%load/dar/str",of_LOAD_DAR_STR, 1, {OA_FUNC_PTR, OA_NONE, OA_NONE} },
{ "%load/real", of_LOAD_REAL,1,{OA_VPI_PTR, OA_NONE, OA_NONE} },
{ "%load/str", of_LOAD_STR, 1,{OA_FUNC_PTR,OA_NONE, OA_NONE} },
{ "%load/v", of_LOAD_VEC,3, {OA_BIT1, OA_FUNC_PTR, OA_BIT2} },
{ "%load/vp0",of_LOAD_VP0,3,{OA_BIT1, OA_FUNC_PTR, OA_BIT2} },
{ "%load/vp0/s",of_LOAD_VP0_S,3,{OA_BIT1, OA_FUNC_PTR, OA_BIT2} },
{ "%load/x1p",of_LOAD_X1P,3,{OA_BIT1, OA_FUNC_PTR, OA_BIT2} },
@ -220,6 +222,8 @@ static const struct opcode_table_s opcode_table[] = {
{ "%shiftl/i0", of_SHIFTL_I0, 2, {OA_BIT1,OA_NUMBER, OA_NONE} },
{ "%shiftr/i0", of_SHIFTR_I0, 2, {OA_BIT1,OA_NUMBER, OA_NONE} },
{ "%shiftr/s/i0", of_SHIFTR_S_I0,2,{OA_BIT1,OA_NUMBER, OA_NONE} },
{ "%store/dar/r", of_STORE_DAR_R, 1, {OA_FUNC_PTR, OA_NONE, OA_NONE} },
{ "%store/dar/str",of_STORE_DAR_STR, 1, {OA_FUNC_PTR, OA_NONE, OA_NONE} },
{ "%store/obj", of_STORE_OBJ, 1,{OA_FUNC_PTR,OA_NONE, OA_NONE} },
{ "%store/real", of_STORE_REAL, 1,{OA_FUNC_PTR,OA_NONE, OA_NONE} },
{ "%store/reala",of_STORE_REALA,2,{OA_ARR_PTR, OA_BIT1, OA_NONE} },

View File

@ -612,12 +612,15 @@ out of range, then x is loaded. The index value is incremented by one
if it is defined (bit 4 is not 1).
* %load/dar <bit>, <functor-label>, <wid>
* %load/dar/r <functor-label>
This instruction loads an array word from a dynamic array. The
<label> refers to the variable object, and the <bit>/<wid> are the
location in local vector space where the extracted word goes. The
index is implicitly extracted from index register 3.
The dar/r variant reads a real-value into a real-valued register.
(See also %set/dar)
* %load/real <vpi-label>
@ -625,6 +628,16 @@ index is implicitly extracted from index register 3.
The %load/real instruction reads a real value from the vpi-like object
and pushes it to the top of the real value stack.
* %load/str <var-label>
* %load/dar/str <var-label>
The %load/str instruction gets the string from the string variable and
pushes in to the string stack. (See also %store/str)
The %load/dar/str is similar, but the variable is a dynamic array of
strings, and there is an index value in index register 3.
(See also %store/dar/str)
* %load/v <bit>, <functor-label>, <wid>
@ -760,7 +773,10 @@ the array. See also %delete/obj
The supported types are:
"sb32" - signed bool 32bits
"b<N>" - unsigned bool <N>-bits
"sb<N>" - signed bool <N>-bits
"r" - real
"S" - SystemVerilog string
* %nor <dst>, <src>, <wid>
@ -961,9 +977,14 @@ The areal version is similar, but writes to a real array using the
index in the index register <index>
* %store/str <var-label>
* %store/dar/r <var-label>
* %store/dar/str <var-label>
This pops the top of the string stack and writes it to the string
varible.
The %store/str instruction pops the top of the string stack and writes
it to the string variable.
The %store/dar/str is similar, but the target is a dynamic array of
string string. The index is taken from signed index register 3.
* %sub <bit-l>, <bit-r>, <wid>

View File

@ -3192,9 +3192,50 @@ bool of_LOAD_DAR(vthread_t thr, vvp_code_t cp)
return true;
}
/*
* %load/dar/r <array-label>;
*/
bool of_LOAD_DAR_R(vthread_t thr, vvp_code_t cp)
{
unsigned adr = thr->words[3].w_int;
vvp_net_t*net = cp->net;
assert(net);
vvp_fun_signal_object*obj = dynamic_cast<vvp_fun_signal_object*> (net->fun);
assert(obj);
vvp_darray*darray = dynamic_cast<vvp_darray*> (obj->get_object());
assert(darray);
double word;
darray->get_word(adr, word);
thr->push_real(word);
return true;
}
bool of_LOAD_DAR_STR(vthread_t thr, vvp_code_t cp)
{
unsigned adr = thr->words[3].w_int;
vvp_net_t*net = cp->net;
assert(net);
vvp_fun_signal_object*obj = dynamic_cast<vvp_fun_signal_object*> (net->fun);
assert(obj);
vvp_darray*darray = dynamic_cast<vvp_darray*> (obj->get_object());
assert(darray);
string word;
darray->get_word(adr, word);
thr->push_str(word);
return true;
}
/*
* %load/vp0, %load/vp0/s, %load/avp0 and %load/avp0/s share this function.
*/
*/
#if (SIZEOF_UNSIGNED_LONG >= 8)
# define CPU_WORD_STRIDE CPU_WORD_BITS - 1 // avoid a warning
#else
@ -4019,8 +4060,26 @@ bool of_NEW_DARRAY(vthread_t thr, vvp_code_t cp)
size_t size = thr->words[cp->bit_idx[0]].w_int;
vvp_object_t obj;
if (strcmp(text,"sb32") == 0) {
if (strcmp(text,"b8") == 0) {
obj = new vvp_darray_atom<uint8_t>(size);
} else if (strcmp(text,"b16") == 0) {
obj = new vvp_darray_atom<uint16_t>(size);
} else if (strcmp(text,"b32") == 0) {
obj = new vvp_darray_atom<uint32_t>(size);
} else if (strcmp(text,"b64") == 0) {
obj = new vvp_darray_atom<uint64_t>(size);
} else if (strcmp(text,"sb8") == 0) {
obj = new vvp_darray_atom<int8_t>(size);
} else if (strcmp(text,"sb16") == 0) {
obj = new vvp_darray_atom<int16_t>(size);
} else if (strcmp(text,"sb32") == 0) {
obj = new vvp_darray_atom<int32_t>(size);
} else if (strcmp(text,"sb64") == 0) {
obj = new vvp_darray_atom<int64_t>(size);
} else if (strcmp(text,"r") == 0) {
obj = new vvp_darray_real(size);
} else if (strcmp(text,"S") == 0) {
obj = new vvp_darray_string(size);
} else {
obj = new vvp_darray (size);
}
@ -4821,6 +4880,48 @@ bool of_SHIFTR_S_I0(vthread_t thr, vvp_code_t cp)
return true;
}
bool of_STORE_DAR_R(vthread_t thr, vvp_code_t cp)
{
long adr = thr->words[3].w_int;
// Pop the real value to be store...
double value = thr->pop_real();
vvp_net_t*net = cp->net;
vvp_fun_signal_object*obj = dynamic_cast<vvp_fun_signal_object*> (net->fun);
assert(obj);
vvp_darray*darray = dynamic_cast<vvp_darray*>(obj->get_object());
assert(darray);
darray->set_word(adr, value);
return true;
}
/*
* %store/dar/str <var>
* In this case, <var> is the name of a dynamic array. Signed index
* register 3 contains the index into the dynamic array.
*/
bool of_STORE_DAR_STR(vthread_t thr, vvp_code_t cp)
{
long adr = thr->words[3].w_int;
// Pop the string to be stored...
string value = thr->pop_str();
vvp_net_t*net = cp->net;
vvp_fun_signal_object*obj = dynamic_cast<vvp_fun_signal_object*> (net->fun);
assert(obj);
vvp_darray*darray = dynamic_cast<vvp_darray*>(obj->get_object());
assert(darray);
darray->set_word(adr, value);
return true;
}
bool of_STORE_OBJ(vthread_t thr, vvp_code_t cp)
{
/* set the value into port 0 of the destination. */

View File

@ -1619,8 +1619,8 @@ ostream& operator<< (ostream&out, const vvp_vector4_t&that)
return out;
}
template <class INT>bool do_vector4_to_value(const vvp_vector4_t&vec, INT&val,
bool is_signed, bool is_arithmetic)
template <class INT>bool vector4_to_value(const vvp_vector4_t&vec, INT&val,
bool is_signed, bool is_arithmetic)
{
long res = 0;
INT msk = 1;
@ -1654,22 +1654,27 @@ template <class INT>bool do_vector4_to_value(const vvp_vector4_t&vec, INT&val,
return rc_flag;
}
bool vector4_to_value(const vvp_vector4_t&vec, long&val,
bool is_signed, bool is_arithmetic)
{
return do_vector4_to_value(vec, val, is_signed, is_arithmetic);
}
template bool vector4_to_value(const vvp_vector4_t&vec, int8_t&val,
bool is_signed, bool is_arithmetic);
template bool vector4_to_value(const vvp_vector4_t&vec, int16_t&val,
bool is_signed, bool is_arithmetic);
template bool vector4_to_value(const vvp_vector4_t&vec, int32_t&val,
bool is_signed, bool is_arithmetic);
template bool vector4_to_value(const vvp_vector4_t&vec, int64_t&val,
bool is_signed, bool is_arithmetic);
template bool vector4_to_value(const vvp_vector4_t&vec, uint8_t&val,
bool is_signed, bool is_arithmetic);
template bool vector4_to_value(const vvp_vector4_t&vec, uint16_t&val,
bool is_signed, bool is_arithmetic);
template bool vector4_to_value(const vvp_vector4_t&vec, uint32_t&val,
bool is_signed, bool is_arithmetic);
template bool vector4_to_value(const vvp_vector4_t&vec, uint64_t&val,
bool is_signed, bool is_arithmetic);
bool vector4_to_value(const vvp_vector4_t&vec, int32_t&val,
bool is_signed, bool is_arithmetic)
template <class T> bool vector4_to_value(const vvp_vector4_t&vec, T&val)
{
return do_vector4_to_value(vec, val, is_signed, is_arithmetic);
}
bool vector4_to_value(const vvp_vector4_t&vec, unsigned long&val)
{
unsigned long res = 0;
unsigned long msk = 1;
T res = 0;
T msk = 1;
unsigned size = vec.size();
if (size > 8*sizeof(val)) size = 8*sizeof(val);
@ -1684,44 +1689,16 @@ bool vector4_to_value(const vvp_vector4_t&vec, unsigned long&val)
return false;
}
msk <<= 1UL;
msk <<= static_cast<T>(1);
}
val = res;
return true;
}
template bool vector4_to_value(const vvp_vector4_t&vec, unsigned long&val);
#ifndef UL_AND_TIME64_SAME
bool vector4_to_value(const vvp_vector4_t&vec, int64_t&val,
bool is_signed, bool is_arithmetic)
{
return do_vector4_to_value(vec, val, is_signed, is_arithmetic);
}
bool vector4_to_value(const vvp_vector4_t&vec, vvp_time64_t&val)
{
vvp_time64_t res = 0;
vvp_time64_t msk = 1;
unsigned size = vec.size();
if (size > 8*sizeof(val)) size = 8*sizeof(val);
for (unsigned idx = 0 ; idx < size ; idx += 1) {
switch (vec.value(idx)) {
case BIT4_0:
break;
case BIT4_1:
res |= msk;
break;
default:
return false;
}
msk <<= 1UL;
}
val = res;
return true;
}
template bool vector4_to_value(const vvp_vector4_t&vec, vvp_time64_t&val);
#endif
bool vector4_to_value(const vvp_vector4_t&vec, double&val, bool signed_flag)

View File

@ -510,13 +510,12 @@ template <class T> extern T coerce_to_width(const T&that, unsigned width);
* value will be "false", but the other bits will be transferred. This
* is what you want if you are doing "vpi_get_value", for example.
*/
extern bool vector4_to_value(const vvp_vector4_t&a, long&val, bool is_signed, bool is_arithmetic =true);
extern bool vector4_to_value(const vvp_vector4_t&a, unsigned long&val);
extern bool vector4_to_value(const vvp_vector4_t&a, int32_t&val, bool is_signed, bool is_arithmetic =true);
#ifndef UL_AND_TIME64_SAME
extern bool vector4_to_value(const vvp_vector4_t&a, int64_t&val, bool is_signed, bool is_arithmetic =true);
extern bool vector4_to_value(const vvp_vector4_t&a, vvp_time64_t&val);
#endif
template <class T> extern bool vector4_to_value(const vvp_vector4_t&a, T&val,
bool is_signed,
bool is_arithmetic =true);
template <class T> extern bool vector4_to_value(const vvp_vector4_t&a, T&val);
extern bool vector4_to_value(const vvp_vector4_t&a, double&val, bool is_signed);
extern bool vector2_to_value(const vvp_vector2_t&a, int32_t&val, bool is_signed);

View File

@ -32,39 +32,112 @@ vvp_darray::~vvp_darray()
{
}
void vvp_darray::set_word(unsigned adr, const vvp_vector4_t&)
void vvp_darray::set_word(unsigned, const vvp_vector4_t&)
{
cerr << "XXXX set_word not implemented for " << typeid(*this).name() << endl;
cerr << "XXXX set_word(vvp_vector4_t) not implemented for " << typeid(*this).name() << endl;
}
void vvp_darray::set_word(unsigned, double)
{
cerr << "XXXX set_word(double) not implemented for " << typeid(*this).name() << endl;
}
void vvp_darray::set_word(unsigned, const string&)
{
cerr << "XXXX set_word(string) not implemented for " << typeid(*this).name() << endl;
}
void vvp_darray::get_word(unsigned, vvp_vector4_t&)
{
cerr << "XXXX get_word not implemented for " << typeid(*this).name() << endl;
cerr << "XXXX get_word(vvp_vector4_t) not implemented for " << typeid(*this).name() << endl;
}
template <> vvp_darray_atom<int32_t>::~vvp_darray_atom()
void vvp_darray::get_word(unsigned, double&)
{
cerr << "XXXX get_word(double) not implemented for " << typeid(*this).name() << endl;
}
void vvp_darray::get_word(unsigned, string&)
{
cerr << "XXXX get_word(string) not implemented for " << typeid(*this).name() << endl;
}
template <class TYPE> vvp_darray_atom<TYPE>::~vvp_darray_atom()
{
}
template <> void vvp_darray_atom<int32_t>::set_word(unsigned adr, const vvp_vector4_t&value)
template <class TYPE> void vvp_darray_atom<TYPE>::set_word(unsigned adr, const vvp_vector4_t&value)
{
if (adr >= array_.size())
return;
vector4_to_value(value, array_[adr], true, false);
TYPE tmp;
vector4_to_value(value, tmp, true, false);
array_[adr] = tmp;
}
template <> void vvp_darray_atom<int32_t>::get_word(unsigned adr, vvp_vector4_t&value)
template <class TYPE> void vvp_darray_atom<TYPE>::get_word(unsigned adr, vvp_vector4_t&value)
{
if (adr >= array_.size()) {
value = vvp_vector4_t(32, BIT4_X);
value = vvp_vector4_t(8*sizeof(TYPE), BIT4_X);
return;
}
uint32_t word = array_[adr];
vvp_vector4_t tmp (32, BIT4_0);
for (unsigned idx = 0 ; idx < 32 ; idx += 1) {
TYPE word = array_[adr];
vvp_vector4_t tmp (8*sizeof(TYPE), BIT4_0);
for (unsigned idx = 0 ; idx < tmp.size() ; idx += 1) {
if (word&1) tmp.set_bit(idx, BIT4_1);
word >>= 1;
}
value = tmp;
}
template class vvp_darray_atom<uint8_t>;
template class vvp_darray_atom<uint16_t>;
template class vvp_darray_atom<uint32_t>;
template class vvp_darray_atom<uint64_t>;
template class vvp_darray_atom<int8_t>;
template class vvp_darray_atom<int16_t>;
template class vvp_darray_atom<int32_t>;
template class vvp_darray_atom<int64_t>;
vvp_darray_real::~vvp_darray_real()
{
}
void vvp_darray_real::set_word(unsigned adr, double value)
{
if (adr >= array_.size())
return;
array_[adr] = value;
}
void vvp_darray_real::get_word(unsigned adr, double&value)
{
if (adr >= array_.size()) {
value = 0.0;
return;
}
value = array_[adr];
}
vvp_darray_string::~vvp_darray_string()
{
}
void vvp_darray_string::set_word(unsigned adr, const string&value)
{
if (adr >= array_.size())
return;
array_[adr] = value;
}
void vvp_darray_string::get_word(unsigned adr, string&value)
{
if (adr >= array_.size()) {
value = 0.0;
return;
}
value = array_[adr];
}

View File

@ -20,6 +20,7 @@
*/
# include <stdlib.h>
# include <string>
# include <vector>
typedef class vvp_object*vvp_object_t;
@ -40,9 +41,14 @@ class vvp_darray : public vvp_object {
inline size_t get_size(void) const { return size_; }
virtual void set_word(unsigned adr, const vvp_vector4_t&value);
virtual void get_word(unsigned adr, vvp_vector4_t&value);
virtual void set_word(unsigned adr, double value);
virtual void get_word(unsigned adr, double&value);
virtual void set_word(unsigned adr, const std::string&value);
virtual void get_word(unsigned adr, std::string&value);
private:
size_t size_;
};
@ -54,11 +60,36 @@ template <class TYPE> class vvp_darray_atom : public vvp_darray {
~vvp_darray_atom();
void set_word(unsigned adr, const vvp_vector4_t&value);
void get_word(unsigned adr, vvp_vector4_t&value);
private:
std::vector<TYPE> array_;
};
class vvp_darray_real : public vvp_darray {
public:
inline vvp_darray_real(size_t siz) : vvp_darray(siz), array_(siz) { }
~vvp_darray_real();
void set_word(unsigned adr, double value);
void get_word(unsigned adr, double&value);
private:
std::vector<double> array_;
};
class vvp_darray_string : public vvp_darray {
public:
inline vvp_darray_string(size_t siz) : vvp_darray(siz), array_(siz) { }
~vvp_darray_string();
void set_word(unsigned adr, const std::string&value);
void get_word(unsigned adr, std::string&value);
private:
std::vector<std::string> array_;
};
#endif