The NetNet class carries multiple packed dimensions.
This commit is contained in:
parent
ae11010707
commit
e5c49022b4
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 1998-2011 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 1998-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
|
||||
|
|
@ -187,6 +187,15 @@ void NetDelaySrc::dump(ostream&o, unsigned ind) const
|
|||
dump_node_pins(o, ind+4);
|
||||
}
|
||||
|
||||
ostream&operator<<(ostream&out, const list<NetNet::range_t>&rlist)
|
||||
{
|
||||
for (list<NetNet::range_t>::const_iterator cur = rlist.begin()
|
||||
; cur != rlist.end() ; ++cur) {
|
||||
out << "[" << cur->msb << ":" << cur->lsb << "]";
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
/* Dump a net. This can be a wire or register. */
|
||||
void NetNet::dump_net(ostream&o, unsigned ind) const
|
||||
{
|
||||
|
|
@ -217,6 +226,8 @@ void NetNet::dump_net(ostream&o, unsigned ind) const
|
|||
if (ivl_discipline_t dis = get_discipline())
|
||||
o << " discipline=" << dis->name();
|
||||
|
||||
o << " packed dims: " << packed_dims_;
|
||||
|
||||
o << " (eref=" << peek_eref() << ", lref=" << peek_lref() << ")";
|
||||
if (scope())
|
||||
o << " scope=" << scope_path(scope());
|
||||
|
|
@ -1045,8 +1056,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_->msb() << ":"
|
||||
<< result_sig_->lsb() << "]" << endl;
|
||||
o << result_sig_->name() << result_sig_->packed_dims() << endl;
|
||||
}
|
||||
o << setw(ind+2) << "" << "Arguments: ";
|
||||
if (port_count() == 0) o << "<none>";
|
||||
|
|
@ -1068,8 +1078,7 @@ void NetFuncDef::dump(ostream&o, unsigned ind) const
|
|||
break;
|
||||
}
|
||||
if (port(idx)->get_signed()) o << "+";
|
||||
o << port(idx)->name() << "[" << port(idx)->msb() << ":"
|
||||
<< port(idx)->lsb() << "]" << endl;
|
||||
o << port(idx)->name() << port(idx)->packed_dims() << endl;
|
||||
}
|
||||
if (statement_)
|
||||
statement_->dump(o, ind+2);
|
||||
|
|
|
|||
|
|
@ -3435,8 +3435,7 @@ NetExpr* PEIdent::elaborate_expr_net_bit_(Design*des, NetScope*scope,
|
|||
else cerr << "vector ";
|
||||
cerr << net->name();
|
||||
if (net->word_index()) cerr << "[]";
|
||||
cerr << "[" << net->sig()->msb() << ":"
|
||||
<< net->sig()->lsb() << "]." << endl;
|
||||
cerr << net->sig()->packed_dims() << "." << endl;
|
||||
cerr << get_fileline() << ": : "
|
||||
<< "Replacing select with a constant 1'bx."
|
||||
<< endl;
|
||||
|
|
@ -3470,8 +3469,9 @@ NetExpr* PEIdent::elaborate_expr_net_bit_(Design*des, NetScope*scope,
|
|||
// complicated task because we need to generate
|
||||
// expressions to convert calculated bit select
|
||||
// values to canonical values that are used internally.
|
||||
ex = normalize_variable_base(ex, net->sig()->msb(), net->sig()->lsb(),
|
||||
1, true);
|
||||
const list<NetNet::range_t>& sig_packed = net->sig()->packed_dims();
|
||||
assert(sig_packed.size() == 1);
|
||||
ex = normalize_variable_base(ex, sig_packed, 1, true);
|
||||
|
||||
NetESelect*ss = new NetESelect(net, ex, 1);
|
||||
ss->set_line(*this);
|
||||
|
|
|
|||
33
elab_lval.cc
33
elab_lval.cc
|
|
@ -365,14 +365,20 @@ bool PEIdent::elaborate_lval_net_bit_(Design*des,
|
|||
mux = 0;
|
||||
}
|
||||
|
||||
// For now, we only understand 1-dim packed arrays.
|
||||
const list<NetNet::range_t>&packed = reg->packed_dims();
|
||||
ivl_assert(*this, packed.size() == 1);
|
||||
const NetNet::range_t rng = packed.back();
|
||||
|
||||
if (mux) {
|
||||
// Non-constant bit mux. Correct the mux for the range
|
||||
// of the vector, then set the l-value part select expression.
|
||||
mux = normalize_variable_base(mux, reg->msb(), reg->lsb(), 1, true);
|
||||
// of the vector, then set the l-value part select
|
||||
// expression.
|
||||
mux = normalize_variable_base(mux, reg->packed_dims(), 1, true);
|
||||
|
||||
lv->set_part(mux, 1);
|
||||
|
||||
} else if (lsb == reg->msb() && lsb == reg->lsb()) {
|
||||
} else if (lsb == rng.msb && lsb == rng.lsb) {
|
||||
// Constant bit mux that happens to select the only bit
|
||||
// of the l-value. Don't bother with any select at all.
|
||||
|
||||
|
|
@ -410,9 +416,13 @@ bool PEIdent::elaborate_lval_net_part_(Design*des,
|
|||
ivl_assert(*this, parts_defined_flag);
|
||||
|
||||
NetNet*reg = lv->sig();
|
||||
assert(reg);
|
||||
ivl_assert(*this, reg);
|
||||
|
||||
if (msb == reg->msb() && lsb == reg->lsb()) {
|
||||
const list<NetNet::range_t>&packed = reg->packed_dims();
|
||||
ivl_assert(*this, packed.size() == 1);
|
||||
const NetNet::range_t&rng = packed.back();
|
||||
|
||||
if (msb == rng.msb && lsb == rng.lsb) {
|
||||
|
||||
/* Part select covers the entire vector. Simplest case. */
|
||||
|
||||
|
|
@ -487,9 +497,14 @@ bool PEIdent::elaborate_lval_net_idx_(Design*des,
|
|||
if (base_c->value().is_defined()) {
|
||||
long lsv = base_c->value().as_long();
|
||||
long offset = 0;
|
||||
if (((reg->msb() < reg->lsb()) &&
|
||||
// This is a work-around for limited dimenions support.
|
||||
const list<NetNet::range_t>&packed = reg->packed_dims();
|
||||
ivl_assert(*this, packed.size() == 1);
|
||||
const NetNet::range_t&rng = packed.back();
|
||||
|
||||
if (((rng.msb < rng.lsb) &&
|
||||
use_sel == index_component_t::SEL_IDX_UP) ||
|
||||
((reg->msb() > reg->lsb()) &&
|
||||
((rng.msb > rng.lsb) &&
|
||||
use_sel == index_component_t::SEL_IDX_DO)) {
|
||||
offset = -wid + 1;
|
||||
}
|
||||
|
|
@ -538,12 +553,12 @@ bool PEIdent::elaborate_lval_net_idx_(Design*des,
|
|||
} else {
|
||||
/* Correct the mux for the range of the vector. */
|
||||
if (use_sel == index_component_t::SEL_IDX_UP) {
|
||||
base = normalize_variable_base(base, reg->msb(), reg->lsb(),
|
||||
base = normalize_variable_base(base, reg->packed_dims(),
|
||||
wid, true);
|
||||
sel_type = IVL_SEL_IDX_UP;
|
||||
} else {
|
||||
// This is assumed to be a SEL_IDX_DO.
|
||||
base = normalize_variable_base(base, reg->msb(), reg->lsb(),
|
||||
base = normalize_variable_base(base, reg->packed_dims(),
|
||||
wid, false);
|
||||
sel_type = IVL_SEL_IDX_DOWN;
|
||||
}
|
||||
|
|
|
|||
41
elab_sig.cc
41
elab_sig.cc
|
|
@ -494,7 +494,9 @@ void PFunction::elaborate_sig(Design*des, NetScope*scope) const
|
|||
des->errors += 1;
|
||||
}
|
||||
|
||||
ret_sig = new NetNet(scope, fname, NetNet::REG, mnum, lnum);
|
||||
list<NetNet::range_t> packed;
|
||||
packed.push_back(NetNet::range_t(mnum, lnum));
|
||||
ret_sig = new NetNet(scope, fname, NetNet::REG, packed);
|
||||
ret_sig->set_scalar(false);
|
||||
|
||||
} else {
|
||||
|
|
@ -888,31 +890,6 @@ bool test_ranges_eeq(const list<NetNet::range_t>&lef, const list<NetNet::range_t
|
|||
return true;
|
||||
}
|
||||
|
||||
static unsigned packed_ranges_to_wid(const list<NetNet::range_t>&packed)
|
||||
{
|
||||
unsigned wid = 1;
|
||||
for (list<NetNet::range_t>::const_iterator cur = packed.begin()
|
||||
; cur != packed.begin() ; ++cur) {
|
||||
unsigned use_wid;
|
||||
if (cur->msb >= cur->lsb)
|
||||
use_wid = cur->msb - cur->lsb + 1;
|
||||
else
|
||||
use_wid = cur->lsb - cur->msb + 1;
|
||||
wid *= use_wid;
|
||||
}
|
||||
|
||||
return wid;
|
||||
}
|
||||
|
||||
static ostream&operator<<(ostream&out, const list<NetNet::range_t>&rlist)
|
||||
{
|
||||
for (list<NetNet::range_t>::const_iterator cur = rlist.begin()
|
||||
; cur != rlist.end() ; ++cur) {
|
||||
out << "[" << cur->msb << ":" << cur->lsb << "]";
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
/*
|
||||
* Elaborate a source wire. The "wire" is the declaration of wires,
|
||||
* registers, ports and memories. The parser has already merged the
|
||||
|
|
@ -1041,7 +1018,7 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
|
|||
}
|
||||
|
||||
packed_dimensions = nlist;
|
||||
wid = packed_ranges_to_wid(packed_dimensions);
|
||||
wid = NetNet::vector_width(packed_dimensions);
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -1177,14 +1154,10 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
|
|||
<< "packed arrays not supported." << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
long msb = 0, lsb = 0;
|
||||
if (packed_dimensions.size() >= 1) {
|
||||
msb = packed_dimensions.front().msb;
|
||||
lsb = packed_dimensions.front().lsb;
|
||||
}
|
||||
|
||||
sig = array_dimensions > 0
|
||||
? new NetNet(scope, name_, wtype, msb, lsb, array_s0, array_e0)
|
||||
: new NetNet(scope, name_, wtype, msb, lsb);
|
||||
? new NetNet(scope, name_, wtype, packed_dimensions, array_s0, array_e0)
|
||||
: new NetNet(scope, name_, wtype, packed_dimensions);
|
||||
}
|
||||
|
||||
// If this is an enumeration, then set the enumeration set for
|
||||
|
|
|
|||
72
netlist.cc
72
netlist.cc
|
|
@ -452,12 +452,14 @@ NetNet::NetNet(NetScope*s, perm_string n, Type t, unsigned npins)
|
|||
type_(t), port_type_(NOT_A_PORT), data_type_(IVL_VT_NO_TYPE),
|
||||
signed_(false), isint_(false), is_scalar_(false), local_flag_(false),
|
||||
enumeration_(0), struct_type_(0), discipline_(0),
|
||||
msb_(npins-1), lsb_(0), dimensions_(0),
|
||||
s0_(0), e0_(0), eref_count_(0), lref_count_(0)
|
||||
dimensions_(0), s0_(0), e0_(0), eref_count_(0), lref_count_(0)
|
||||
{
|
||||
assert(s);
|
||||
assert(npins>0);
|
||||
|
||||
// Synthesize a single range to describe this canonical vector.
|
||||
packed_dims_.push_back(NetNet::range_t(npins-1, 0));
|
||||
|
||||
Link::DIR dir = Link::PASSIVE;
|
||||
|
||||
switch (t) {
|
||||
|
|
@ -494,15 +496,15 @@ void NetNet::initialize_dir_(Link::DIR dir)
|
|||
}
|
||||
|
||||
NetNet::NetNet(NetScope*s, perm_string n, Type t,
|
||||
long ms, long ls)
|
||||
const list<NetNet::range_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),
|
||||
enumeration_(0), struct_type_(0), discipline_(0),
|
||||
msb_(ms), lsb_(ls),
|
||||
dimensions_(0), s0_(0), e0_(0),
|
||||
eref_count_(0), lref_count_(0)
|
||||
{
|
||||
packed_dims_ = packed;
|
||||
assert(s);
|
||||
|
||||
Link::DIR dir = Link::PASSIVE;
|
||||
|
|
@ -542,16 +544,16 @@ static unsigned calculate_count(long s, long e)
|
|||
}
|
||||
|
||||
NetNet::NetNet(NetScope*s, perm_string n, Type t,
|
||||
long ms, long ls, long array_s, long array_e)
|
||||
const list<NetNet::range_t>&packed, long array_s, long array_e)
|
||||
: NetObj(s, n, calculate_count(array_s, array_e)),
|
||||
type_(t), port_type_(NOT_A_PORT),
|
||||
data_type_(IVL_VT_NO_TYPE), signed_(false), isint_(false),
|
||||
is_scalar_(false), local_flag_(false), enumeration_(0), struct_type_(0),
|
||||
discipline_(0),
|
||||
msb_(ms), lsb_(ls),
|
||||
dimensions_(1), s0_(array_s), e0_(array_e),
|
||||
eref_count_(0), lref_count_(0)
|
||||
{
|
||||
packed_dims_ = packed;
|
||||
ivl_assert(*this, s);
|
||||
if (pin_count() == 0) {
|
||||
cerr << "Array too big [" << array_s << ":" << array_e << "]" << endl;
|
||||
|
|
@ -599,10 +601,11 @@ NetNet::NetNet(NetScope*s, perm_string n, Type t, netstruct_t*ty)
|
|||
type_(t), port_type_(NOT_A_PORT),
|
||||
data_type_(IVL_VT_NO_TYPE), signed_(false), isint_(false),
|
||||
is_scalar_(false), local_flag_(false), enumeration_(0), struct_type_(ty),
|
||||
discipline_(0), msb_(calculate_count(ty)-1), lsb_(0),
|
||||
discipline_(0),
|
||||
dimensions_(0), s0_(0), e0_(0),
|
||||
eref_count_(0), lref_count_(0)
|
||||
{
|
||||
packed_dims_.push_back(range_t(calculate_count(ty)-1, 0));
|
||||
Link::DIR dir = Link::PASSIVE;
|
||||
|
||||
switch (t) {
|
||||
|
|
@ -761,38 +764,40 @@ void NetNet::set_discipline(ivl_discipline_t dis)
|
|||
discipline_ = dis;
|
||||
}
|
||||
|
||||
long NetNet::lsb() const
|
||||
unsigned long NetNet::vector_width(const list<NetNet::range_t>&packed)
|
||||
{
|
||||
return lsb_;
|
||||
}
|
||||
unsigned wid = 1;
|
||||
for (list<NetNet::range_t>::const_iterator cur = packed.begin()
|
||||
; cur != packed.end() ; ++cur) {
|
||||
unsigned use_wid;
|
||||
if (cur->msb >= cur->lsb)
|
||||
use_wid = cur->msb - cur->lsb + 1;
|
||||
else
|
||||
use_wid = cur->lsb - cur->msb + 1;
|
||||
wid *= use_wid;
|
||||
}
|
||||
|
||||
long NetNet::msb() const
|
||||
{
|
||||
return msb_;
|
||||
}
|
||||
|
||||
unsigned long NetNet::vector_width() const
|
||||
{
|
||||
if (msb_ > lsb_)
|
||||
return msb_ - lsb_ + 1;
|
||||
else
|
||||
return lsb_ - msb_ + 1;
|
||||
return wid;
|
||||
}
|
||||
|
||||
bool NetNet::sb_is_valid(long sb) const
|
||||
{
|
||||
if (msb_ >= lsb_)
|
||||
return (sb <= msb_) && (sb >= lsb_);
|
||||
assert(packed_dims_.size() == 1);
|
||||
const range_t&rng = packed_dims_.back();
|
||||
if (rng.msb >= rng.lsb)
|
||||
return (sb <= rng.msb) && (sb >= rng.lsb);
|
||||
else
|
||||
return (sb <= lsb_) && (sb >= msb_);
|
||||
return (sb <= rng.lsb) && (sb >= rng.msb);
|
||||
}
|
||||
|
||||
long NetNet::sb_to_idx(long sb) const
|
||||
{
|
||||
if (msb_ >= lsb_)
|
||||
return sb - lsb_;
|
||||
assert(packed_dims_.size() == 1);
|
||||
const range_t&rng = packed_dims_.back();
|
||||
if (rng.msb >= rng.lsb)
|
||||
return sb - rng.lsb;
|
||||
else
|
||||
return lsb_ - sb;
|
||||
return rng.lsb - sb;
|
||||
}
|
||||
|
||||
unsigned NetNet::array_dimensions() const
|
||||
|
|
@ -2370,14 +2375,23 @@ NetNet* NetESignal::sig()
|
|||
return net_;
|
||||
}
|
||||
|
||||
/*
|
||||
* The lsi() and msi() methods should be removed from the NetESignal
|
||||
* class, to be replaced with packed dimensions aware methods of
|
||||
* getting at dimensions.
|
||||
*/
|
||||
long NetESignal::lsi() const
|
||||
{
|
||||
return net_->lsb();
|
||||
const list<NetNet::range_t>&packed = net_->packed_dims();
|
||||
ivl_assert(*this, packed.size() == 1);
|
||||
return packed.back().lsb;
|
||||
}
|
||||
|
||||
long NetESignal::msi() const
|
||||
{
|
||||
return net_->msb();
|
||||
const list<NetNet::range_t>&packed = net_->packed_dims();
|
||||
ivl_assert(*this, packed.size() == 1);
|
||||
return packed.back().msb;
|
||||
}
|
||||
|
||||
ivl_variable_type_t NetESignal::expr_type() const
|
||||
|
|
|
|||
34
netlist.h
34
netlist.h
|
|
@ -564,6 +564,13 @@ class NetNet : public NetObj {
|
|||
enum PortType { NOT_A_PORT, PIMPLICIT, PINPUT, POUTPUT, PINOUT };
|
||||
|
||||
struct range_t {
|
||||
inline range_t() : msb(0), lsb(0) { }
|
||||
inline range_t(long m, long l) : msb(m), lsb(l) { }
|
||||
inline range_t(const range_t&that)
|
||||
: msb(that.msb), lsb(that.lsb) { }
|
||||
inline range_t& operator = (const range_t&that)
|
||||
{ msb = that.msb; lsb = that.lsb; return *this; }
|
||||
|
||||
long msb;
|
||||
long lsb;
|
||||
};
|
||||
|
|
@ -579,9 +586,9 @@ class NetNet : public NetObj {
|
|||
// dimensions. If s0==e0, then this is not an array after
|
||||
// all.
|
||||
explicit NetNet(NetScope*s, perm_string n, Type t,
|
||||
long ms, long ls);
|
||||
const std::list<range_t>&packed);
|
||||
explicit NetNet(NetScope*s, perm_string n, Type t,
|
||||
long ms, long ls, long s0, long e0);
|
||||
const std::list<range_t>&packed, long s0, long e0);
|
||||
|
||||
// This form builds a NetNet from its record definition.
|
||||
explicit NetNet(NetScope*s, perm_string n, Type t, netstruct_t*type);
|
||||
|
|
@ -619,13 +626,18 @@ class NetNet : public NetObj {
|
|||
ivl_discipline_t get_discipline() const;
|
||||
void set_discipline(ivl_discipline_t dis);
|
||||
|
||||
/* These methods return the msb and lsb indices for the most
|
||||
significant and least significant bits. These are signed
|
||||
longs, and may be different from pin numbers. For example,
|
||||
reg [1:8] has 8 bits, msb==1 and lsb==8. */
|
||||
long msb() const;
|
||||
long lsb() const;
|
||||
unsigned long vector_width() const;
|
||||
/* 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<range_t>& packed_dims() const { return packed_dims_; }
|
||||
|
||||
/* The vector_width returns the bit width of the packed array,
|
||||
vector or scaler that is this NetNet object. The static
|
||||
method is also a convenient way to convert a range list to
|
||||
a vector width. */
|
||||
static unsigned long vector_width(const std::list<NetNet::range_t>&);
|
||||
unsigned long vector_width() const { return vector_width(packed_dims_); }
|
||||
|
||||
/* This method converts a signed index (the type that might be
|
||||
found in the Verilog source) to a pin number. It accounts
|
||||
|
|
@ -692,7 +704,7 @@ class NetNet : public NetObj {
|
|||
netstruct_t*struct_type_;
|
||||
ivl_discipline_t discipline_;
|
||||
|
||||
long msb_, lsb_;
|
||||
std::list<range_t> packed_dims_;
|
||||
const unsigned dimensions_;
|
||||
long s0_, e0_;
|
||||
|
||||
|
|
@ -706,6 +718,8 @@ class NetNet : public NetObj {
|
|||
vector<class NetDelaySrc*> delay_paths_;
|
||||
};
|
||||
|
||||
extern std::ostream&operator << (std::ostream&out, const std::list<NetNet::range_t>&rlist);
|
||||
|
||||
/*
|
||||
* This object type is used to contain a logical scope within a
|
||||
* design. The scope doesn't represent any executable hardware, but is
|
||||
|
|
|
|||
64
netmisc.cc
64
netmisc.cc
|
|
@ -27,55 +27,6 @@
|
|||
# include "compiler.h"
|
||||
# include "ivl_assert.h"
|
||||
|
||||
// This routines is not currently used!
|
||||
#if 0
|
||||
NetNet* add_to_net(Design*des, NetNet*sig, long val)
|
||||
{
|
||||
if (val == 0)
|
||||
return sig;
|
||||
cerr << sig->get_fileline() << ": XXXX: Forgot how to implement add_to_net" << endl;
|
||||
return 0;
|
||||
NetScope*scope = sig->scope();
|
||||
unsigned long abs_val = (val >= 0)? val : (-val);
|
||||
unsigned width = sig->pin_count();
|
||||
|
||||
verinum val_v (abs_val, width);
|
||||
|
||||
NetConst*val_c = new NetConst(scope, scope->local_symbol(), val_v);
|
||||
|
||||
NetNet*val_s = new NetNet(scope, scope->local_symbol(),
|
||||
NetNet::IMPLICIT, width);
|
||||
val_s->local_flag(true);
|
||||
|
||||
NetNet*res = new NetNet(scope, scope->local_symbol(),
|
||||
NetNet::IMPLICIT, width);
|
||||
res->local_flag(true);
|
||||
|
||||
NetAddSub*add = new NetAddSub(scope, scope->local_symbol(), width);
|
||||
|
||||
for (unsigned idx = 0 ; idx < width ; idx += 1)
|
||||
connect(sig->pin(idx), add->pin_DataA(idx));
|
||||
|
||||
for (unsigned idx = 0 ; idx < width ; idx += 1)
|
||||
connect(val_c->pin(idx), add->pin_DataB(idx));
|
||||
|
||||
for (unsigned idx = 0 ; idx < width ; idx += 1)
|
||||
connect(val_s->pin(idx), add->pin_DataB(idx));
|
||||
|
||||
for (unsigned idx = 0 ; idx < width ; idx += 1)
|
||||
connect(res->pin(idx), add->pin_Result(idx));
|
||||
|
||||
if (val < 0)
|
||||
add->attribute(perm_string::literal("LPM_Direction"), verinum("SUB"));
|
||||
else
|
||||
add->attribute(perm_string::literal("LPM_Direction"), verinum("ADD"));
|
||||
|
||||
des->add_node(add);
|
||||
des->add_node(val_c);
|
||||
|
||||
return res;
|
||||
}
|
||||
#endif
|
||||
|
||||
NetNet* sub_net_from(Design*des, NetScope*scope, long val, NetNet*sig)
|
||||
{
|
||||
|
|
@ -344,6 +295,21 @@ NetExpr *normalize_variable_base(NetExpr *base, long msb, long lsb,
|
|||
return base;
|
||||
}
|
||||
|
||||
/*
|
||||
* This method is how indices should work except that the base should
|
||||
* be a vector of expressions that matches the size of the dims list,
|
||||
* so that we can generate an expression based on the entire packed
|
||||
* vector. For now, we assert that there is only one set of dimensions.
|
||||
*/
|
||||
NetExpr *normalize_variable_base(NetExpr *base,
|
||||
const list<NetNet::range_t>&dims,
|
||||
unsigned long wid, bool is_up)
|
||||
{
|
||||
ivl_assert(*base, dims.size() == 1);
|
||||
const NetNet::range_t&rng = dims.back();
|
||||
return normalize_variable_base(base, rng.msb, rng.lsb, wid, is_up);
|
||||
}
|
||||
|
||||
/*
|
||||
* This routine generates the normalization expression needed for a variable
|
||||
* array word select.
|
||||
|
|
|
|||
|
|
@ -100,6 +100,9 @@ extern NetNet*crop_to_width(Design*des, NetNet*n, unsigned w);
|
|||
*/
|
||||
extern NetExpr*normalize_variable_base(NetExpr *base, long msb, long lsb,
|
||||
unsigned long wid, bool is_up);
|
||||
extern NetExpr*normalize_variable_base(NetExpr *base,
|
||||
const list<NetNet::range_t>&dims,
|
||||
unsigned long wid, bool is_up);
|
||||
extern NetExpr*normalize_variable_array_base(NetExpr *base, long offset,
|
||||
unsigned count);
|
||||
|
||||
|
|
|
|||
12
t-dll.cc
12
t-dll.cc
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2000-2011 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2000-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
|
||||
|
|
@ -2399,10 +2399,16 @@ void dll_target::signal(const NetNet*net)
|
|||
/* Save the primitive properties of the signal in the
|
||||
ivl_signal_t object. */
|
||||
|
||||
// FIX ME: This is a temporary workaround until the ivl_target
|
||||
// API gets a way to represent multiple packed dimensions.
|
||||
const list<NetNet::range_t>&packed = net->packed_dims();
|
||||
ivl_assert(*net, packed.size() <= 1);
|
||||
const NetNet::range_t rng = packed.empty()? NetNet::range_t(0,0) : packed.back();
|
||||
|
||||
obj->width_ = net->vector_width();
|
||||
obj->signed_= net->get_signed()? 1 : 0;
|
||||
obj->lsb_index = net->lsb();
|
||||
obj->lsb_dist = net->msb() >= net->lsb() ? 1 : -1;
|
||||
obj->lsb_index = rng.lsb;
|
||||
obj->lsb_dist = rng.msb >= rng.lsb ? 1 : -1;
|
||||
obj->isint_ = false;
|
||||
obj->local_ = net->local_flag()? 1 : 0;
|
||||
obj->forced_net_ = (net->type() != NetNet::REG) &&
|
||||
|
|
|
|||
Loading…
Reference in New Issue