Continuous assign no longer uses elaborate_net.
convert the continuous assign elaboration to use elaborate_expr and synthesize methods instead of the elaborate_net methods of PExpr. This exposes problems with the synthesize methods, but it is a better way to do it.
This commit is contained in:
parent
1d884cb0e9
commit
6051150c14
196
elaborate.cc
196
elaborate.cc
|
|
@ -99,187 +99,29 @@ void PGAssign::elaborate(Design*des, NetScope*scope) const
|
|||
<< ", type=" << lval->data_type() << endl;
|
||||
}
|
||||
|
||||
/* Handle the special case that the rval is simply an
|
||||
identifier. Get the rval as a NetNet, then use NetBUFZ
|
||||
objects to connect it to the l-value. This is necessary to
|
||||
direct drivers. This is how I attach strengths to the
|
||||
assignment operation. */
|
||||
if (const PEIdent*id = dynamic_cast<const PEIdent*>(pin(1))) {
|
||||
NetNet*rid = id->elaborate_net(des, scope, lval->vector_width(),
|
||||
0, 0, 0, Link::STRONG,
|
||||
Link::STRONG);
|
||||
if (rid == 0) {
|
||||
des->errors += 1;
|
||||
return;
|
||||
}
|
||||
NetExpr*rval_expr = elab_and_eval(des, scope, pin(1),
|
||||
lval->vector_width(),
|
||||
lval->vector_width());
|
||||
|
||||
/* Cast the right side when needed. */
|
||||
if ((lval->data_type() == IVL_VT_REAL &&
|
||||
rid->data_type() != IVL_VT_REAL)) {
|
||||
rid = cast_to_real(des, scope, rid);
|
||||
} else if ((lval->data_type() != IVL_VT_REAL &&
|
||||
rid->data_type() == IVL_VT_REAL)) {
|
||||
rid = cast_to_int(des, scope, rid, lval->vector_width());
|
||||
}
|
||||
|
||||
ivl_assert(*this, rid);
|
||||
if (rid->pin_count() != 1) {
|
||||
cerr << get_fileline() << ": internal error: "
|
||||
<< "Invalid elaborate_net results here:" << endl;
|
||||
rid->dump_net(cerr, 4);
|
||||
des->errors += 1;
|
||||
return;
|
||||
}
|
||||
ivl_assert(*this, rid->pin_count() == 1);
|
||||
|
||||
/* If the right hand net is the same type as the left
|
||||
side net (i.e., WIRE/WIRE) then it is enough to just
|
||||
connect them together. Otherwise, put a bufz between
|
||||
them to carry strengths from the rval.
|
||||
|
||||
While we are at it, handle the case where the r-value
|
||||
is not as wide as the l-value by padding with a
|
||||
constant-0. */
|
||||
|
||||
unsigned cnt = lval->vector_width();
|
||||
if (rid->vector_width() < cnt)
|
||||
cnt = rid->vector_width();
|
||||
|
||||
bool need_driver_flag = false;
|
||||
|
||||
/* If the device is linked to itself, a driver is
|
||||
needed. Should I print a warning here? */
|
||||
if (lval->pin(0) .is_linked (rid->pin(0)))
|
||||
need_driver_flag = true;
|
||||
|
||||
/* If the nets are different type (i.e., reg vs. tri) then
|
||||
a driver is needed. */
|
||||
if (rid->type() != lval->type())
|
||||
need_driver_flag = true;
|
||||
|
||||
/* If there is a delay, then I need a driver to carry
|
||||
it. */
|
||||
if (rise_time || fall_time || decay_time)
|
||||
need_driver_flag = true;
|
||||
|
||||
/* If there is a strength to be carried, then I need a
|
||||
driver to carry that strength. */
|
||||
if (rid->pin(0).drive0() != drive0)
|
||||
need_driver_flag = true;
|
||||
|
||||
if (rid->pin(0).drive1() != drive1)
|
||||
need_driver_flag = true;
|
||||
|
||||
/* If the r-value is more narrow then the l-value, pad
|
||||
it to the desired width. */
|
||||
if (cnt < lval->vector_width()) {
|
||||
if (lval->get_signed() && rid->get_signed()) {
|
||||
|
||||
unsigned use_width = lval->vector_width();
|
||||
|
||||
if (debug_elaborate)
|
||||
cerr << get_fileline() << ": debug: PGassign "
|
||||
<< "Generate sign-extend node." << endl;
|
||||
|
||||
rid = pad_to_width_signed(des, rid, use_width);
|
||||
|
||||
} else {
|
||||
|
||||
if (debug_elaborate)
|
||||
cerr << get_fileline() << ": debug: PGAssign "
|
||||
<< "Unsigned pad r-value from "
|
||||
<< cnt << " bits to "
|
||||
<< lval->vector_width() << " bits." << endl;
|
||||
|
||||
NetNet*tmp = pad_to_width(des, rid,
|
||||
lval->vector_width());
|
||||
rid = tmp;
|
||||
}
|
||||
|
||||
} else if (cnt < rid->vector_width()) {
|
||||
|
||||
if (debug_elaborate)
|
||||
cerr << get_fileline() << ": debug: PGAssign "
|
||||
<< "Truncate r-value from "
|
||||
<< cnt << " bits to "
|
||||
<< lval->vector_width() << " bits." << endl;
|
||||
|
||||
NetNet*tmp = crop_to_width(des, rid, lval->vector_width());
|
||||
rid = tmp;
|
||||
}
|
||||
|
||||
if (! need_driver_flag) {
|
||||
|
||||
/* Don't need a driver, presumably because the
|
||||
r-value already has the needed drivers. Just
|
||||
hook things up. If the r-value is too narrow
|
||||
for the l-value, then sign extend it or zero
|
||||
extend it, whichever makes sense. */
|
||||
|
||||
if (debug_elaborate) {
|
||||
cerr << get_fileline() << ": debug: PGAssign: "
|
||||
<< "Connect lval directly to "
|
||||
<< id->path() << endl;
|
||||
}
|
||||
|
||||
connect(lval->pin(0), rid->pin(0));
|
||||
|
||||
} else {
|
||||
/* Do need a driver. Use BUFZ objects to carry the
|
||||
strength and delays. */
|
||||
|
||||
if (debug_elaborate) {
|
||||
cerr << get_fileline() << ": debug: PGAssign: "
|
||||
<< "Connect lval to " << id->path()
|
||||
<< " through bufz. delay=(";
|
||||
if (rise_time)
|
||||
cerr << *rise_time << ":";
|
||||
else
|
||||
cerr << "<none>:";
|
||||
if (fall_time)
|
||||
cerr << *fall_time << ":";
|
||||
else
|
||||
cerr << "<none>:";
|
||||
if (decay_time)
|
||||
cerr << *decay_time;
|
||||
else
|
||||
cerr << "<none>";
|
||||
cerr << ")" << endl;
|
||||
}
|
||||
|
||||
NetBUFZ*dev = new NetBUFZ(scope, scope->local_symbol(),
|
||||
rid->vector_width());
|
||||
connect(lval->pin(0), dev->pin(0));
|
||||
connect(rid->pin(0), dev->pin(1));
|
||||
dev->rise_time(rise_time);
|
||||
dev->fall_time(fall_time);
|
||||
dev->decay_time(decay_time);
|
||||
dev->pin(0).drive0(drive0);
|
||||
dev->pin(0).drive1(drive1);
|
||||
des->add_node(dev);
|
||||
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* Elaborate the r-value. Account for the initial decays,
|
||||
which are going to be attached to the last gate before the
|
||||
generated NetNet. */
|
||||
NetNet*rval = pin(1)->elaborate_net(des, scope,
|
||||
lval->vector_width(),
|
||||
0, 0, 0,
|
||||
drive0, drive1);
|
||||
if (rval == 0) {
|
||||
if (rval_expr == 0) {
|
||||
cerr << get_fileline() << ": error: Unable to elaborate r-value: "
|
||||
<< *pin(1) << endl;
|
||||
des->errors += 1;
|
||||
return;
|
||||
}
|
||||
|
||||
NetNet*rval = rval_expr->synthesize(des, scope);
|
||||
|
||||
if (rval == 0) {
|
||||
cerr << get_fileline() << ": internal error: "
|
||||
<< "Failed to synthesize expression: " << *rval_expr << endl;
|
||||
des->errors += 1;
|
||||
return;
|
||||
}
|
||||
|
||||
if (debug_elaborate) {
|
||||
cerr << get_fileline() << ": debug: PGAssign: elaborated r-value"
|
||||
<< " width="<<rval->vector_width()
|
||||
<< " width="<< rval->vector_width()
|
||||
<< ", type="<< rval->data_type() << endl;
|
||||
}
|
||||
|
||||
|
|
@ -318,11 +160,13 @@ void PGAssign::elaborate(Design*des, NetScope*scope) const
|
|||
rval = osig;
|
||||
}
|
||||
|
||||
/* If there is a rise/fall/decay time, then attach that delay
|
||||
to the drivers for this net. */
|
||||
if (rise_time || fall_time || decay_time) {
|
||||
/* Set the drive and delays for the r-val. */
|
||||
|
||||
if (drive0 != Link::STRONG || drive1 != Link::STRONG)
|
||||
rval->pin(0).drivers_drive(drive0, drive1);
|
||||
|
||||
if (rise_time || fall_time || decay_time)
|
||||
rval->pin(0).drivers_delays(rise_time, fall_time, decay_time);
|
||||
}
|
||||
|
||||
connect(lval->pin(0), rval->pin(0));
|
||||
|
||||
|
|
|
|||
214
expr_synth.cc
214
expr_synth.cc
|
|
@ -78,12 +78,7 @@ static bool process_binary_args(Design*des, NetScope*scope,
|
|||
else return false;
|
||||
}
|
||||
|
||||
NetNet* NetExpr::synthesize(Design*des, NetScope*scope,
|
||||
const NetExpr* rise,
|
||||
const NetExpr* fall,
|
||||
const NetExpr* decay,
|
||||
Link::strength_t drive0,
|
||||
Link::strength_t drive1)
|
||||
NetNet* NetExpr::synthesize(Design*des, NetScope*scope)
|
||||
{
|
||||
cerr << get_fileline() << ": internal error: cannot synthesize expression: "
|
||||
<< *this << endl;
|
||||
|
|
@ -94,12 +89,7 @@ NetNet* NetExpr::synthesize(Design*des, NetScope*scope,
|
|||
/*
|
||||
* Make an LPM_ADD_SUB device from addition operators.
|
||||
*/
|
||||
NetNet* NetEBAdd::synthesize(Design*des, NetScope*scope,
|
||||
const NetExpr* rise,
|
||||
const NetExpr* fall,
|
||||
const NetExpr* decay,
|
||||
Link::strength_t drive0,
|
||||
Link::strength_t drive1)
|
||||
NetNet* NetEBAdd::synthesize(Design*des, NetScope*scope)
|
||||
{
|
||||
assert((op()=='+') || (op()=='-'));
|
||||
|
||||
|
|
@ -149,12 +139,7 @@ NetNet* NetEBAdd::synthesize(Design*des, NetScope*scope,
|
|||
* signals, then just connect a single gate to each bit of the vector
|
||||
* of the expression.
|
||||
*/
|
||||
NetNet* NetEBBits::synthesize(Design*des, NetScope*scope,
|
||||
const NetExpr* rise,
|
||||
const NetExpr* fall,
|
||||
const NetExpr* decay,
|
||||
Link::strength_t drive0,
|
||||
Link::strength_t drive1)
|
||||
NetNet* NetEBBits::synthesize(Design*des, NetScope*scope)
|
||||
{
|
||||
NetNet*lsig = left_->synthesize(des, scope);
|
||||
NetNet*rsig = right_->synthesize(des, scope);
|
||||
|
|
@ -218,12 +203,7 @@ NetNet* NetEBBits::synthesize(Design*des, NetScope*scope,
|
|||
return osig;
|
||||
}
|
||||
|
||||
NetNet* NetEBComp::synthesize(Design*des, NetScope*scope,
|
||||
const NetExpr* rise,
|
||||
const NetExpr* fall,
|
||||
const NetExpr* decay,
|
||||
Link::strength_t drive0,
|
||||
Link::strength_t drive1)
|
||||
NetNet* NetEBComp::synthesize(Design*des, NetScope*scope)
|
||||
{
|
||||
|
||||
NetNet *lsig=0, *rsig=0;
|
||||
|
|
@ -336,12 +316,7 @@ NetNet* NetEBComp::synthesize(Design*des, NetScope*scope,
|
|||
return osig;
|
||||
}
|
||||
|
||||
NetNet* NetEBPow::synthesize(Design*des, NetScope*scope,
|
||||
const NetExpr* rise,
|
||||
const NetExpr* fall,
|
||||
const NetExpr* decay,
|
||||
Link::strength_t drive0,
|
||||
Link::strength_t drive1)
|
||||
NetNet* NetEBPow::synthesize(Design*des, NetScope*scope)
|
||||
{
|
||||
NetNet *lsig=0, *rsig=0;
|
||||
unsigned width;
|
||||
|
|
@ -376,12 +351,7 @@ NetNet* NetEBPow::synthesize(Design*des, NetScope*scope,
|
|||
return osig;
|
||||
}
|
||||
|
||||
NetNet* NetEBMult::synthesize(Design*des, NetScope*scope,
|
||||
const NetExpr* rise,
|
||||
const NetExpr* fall,
|
||||
const NetExpr* decay,
|
||||
Link::strength_t drive0,
|
||||
Link::strength_t drive1)
|
||||
NetNet* NetEBMult::synthesize(Design*des, NetScope*scope)
|
||||
{
|
||||
NetNet *lsig=0, *rsig=0;
|
||||
unsigned width;
|
||||
|
|
@ -417,12 +387,7 @@ NetNet* NetEBMult::synthesize(Design*des, NetScope*scope,
|
|||
return osig;
|
||||
}
|
||||
|
||||
NetNet* NetEBDiv::synthesize(Design*des, NetScope*scope,
|
||||
const NetExpr* rise,
|
||||
const NetExpr* fall,
|
||||
const NetExpr* decay,
|
||||
Link::strength_t drive0,
|
||||
Link::strength_t drive1)
|
||||
NetNet* NetEBDiv::synthesize(Design*des, NetScope*scope)
|
||||
{
|
||||
NetNet *lsig=0, *rsig=0;
|
||||
unsigned width;
|
||||
|
|
@ -493,12 +458,7 @@ NetNet* NetEBDiv::synthesize(Design*des, NetScope*scope,
|
|||
return osig;
|
||||
}
|
||||
|
||||
NetNet* NetEBLogic::synthesize(Design*des, NetScope*scope,
|
||||
const NetExpr* rise,
|
||||
const NetExpr* fall,
|
||||
const NetExpr* decay,
|
||||
Link::strength_t drive0,
|
||||
Link::strength_t drive1)
|
||||
NetNet* NetEBLogic::synthesize(Design*des, NetScope*scope)
|
||||
{
|
||||
NetNet*lsig = left_->synthesize(des, scope);
|
||||
NetNet*rsig = right_->synthesize(des, scope);
|
||||
|
|
@ -575,12 +535,7 @@ NetNet* NetEBLogic::synthesize(Design*des, NetScope*scope,
|
|||
return osig;
|
||||
}
|
||||
|
||||
NetNet* NetEBShift::synthesize(Design*des, NetScope*scope,
|
||||
const NetExpr* rise,
|
||||
const NetExpr* fall,
|
||||
const NetExpr* decay,
|
||||
Link::strength_t drive0,
|
||||
Link::strength_t drive1)
|
||||
NetNet* NetEBShift::synthesize(Design*des, NetScope*scope)
|
||||
{
|
||||
eval_expr(right_);
|
||||
|
||||
|
|
@ -705,12 +660,7 @@ NetNet* NetEBShift::synthesize(Design*des, NetScope*scope,
|
|||
return osig;
|
||||
}
|
||||
|
||||
NetNet* NetEConcat::synthesize(Design*des, NetScope*scope,
|
||||
const NetExpr* rise,
|
||||
const NetExpr* fall,
|
||||
const NetExpr* decay,
|
||||
Link::strength_t drive0,
|
||||
Link::strength_t drive1)
|
||||
NetNet* NetEConcat::synthesize(Design*des, NetScope*scope)
|
||||
{
|
||||
/* First, synthesize the operands. */
|
||||
NetNet**tmp = new NetNet*[parms_.count()];
|
||||
|
|
@ -751,12 +701,7 @@ NetNet* NetEConcat::synthesize(Design*des, NetScope*scope,
|
|||
return osig;
|
||||
}
|
||||
|
||||
NetNet* NetEConst::synthesize(Design*des, NetScope*scope,
|
||||
const NetExpr* rise,
|
||||
const NetExpr* fall,
|
||||
const NetExpr* decay,
|
||||
Link::strength_t drive0,
|
||||
Link::strength_t drive1)
|
||||
NetNet* NetEConst::synthesize(Design*des, NetScope*scope)
|
||||
{
|
||||
perm_string path = scope->local_symbol();
|
||||
unsigned width=expr_width();
|
||||
|
|
@ -775,12 +720,7 @@ NetNet* NetEConst::synthesize(Design*des, NetScope*scope,
|
|||
/*
|
||||
* Create a NetLiteral object to represent real valued constants.
|
||||
*/
|
||||
NetNet* NetECReal::synthesize(Design*des, NetScope*scope,
|
||||
const NetExpr* rise,
|
||||
const NetExpr* fall,
|
||||
const NetExpr* decay,
|
||||
Link::strength_t drive0,
|
||||
Link::strength_t drive1)
|
||||
NetNet* NetECReal::synthesize(Design*des, NetScope*scope)
|
||||
{
|
||||
perm_string path = scope->local_symbol();
|
||||
|
||||
|
|
@ -802,12 +742,7 @@ NetNet* NetECReal::synthesize(Design*des, NetScope*scope,
|
|||
* The bitwise unary logic operator (there is only one) is turned
|
||||
* into discrete gates just as easily as the binary ones above.
|
||||
*/
|
||||
NetNet* NetEUBits::synthesize(Design*des, NetScope*scope,
|
||||
const NetExpr* rise,
|
||||
const NetExpr* fall,
|
||||
const NetExpr* decay,
|
||||
Link::strength_t drive0,
|
||||
Link::strength_t drive1)
|
||||
NetNet* NetEUBits::synthesize(Design*des, NetScope*scope)
|
||||
{
|
||||
NetNet*isig = expr_->synthesize(des, scope);
|
||||
|
||||
|
|
@ -846,12 +781,25 @@ NetNet* NetEUBits::synthesize(Design*des, NetScope*scope,
|
|||
return osig;
|
||||
}
|
||||
|
||||
NetNet* NetEUReduce::synthesize(Design*des, NetScope*scope,
|
||||
const NetExpr* rise,
|
||||
const NetExpr* fall,
|
||||
const NetExpr* decay,
|
||||
Link::strength_t drive0,
|
||||
Link::strength_t drive1)
|
||||
NetNet* NetEUnary::synthesize(Design*des, NetScope*scope)
|
||||
{
|
||||
if (op_ == '+')
|
||||
return expr_->synthesize(des, scope);
|
||||
|
||||
if (op_ == '-') {
|
||||
NetExpr*tmp = make_sub_expr(0, expr_);
|
||||
NetNet*sig = tmp->synthesize(des, scope);
|
||||
delete tmp;
|
||||
return sig;
|
||||
}
|
||||
|
||||
cerr << get_fileline() << ": iternal error: "
|
||||
<< "NetEUnary::synthesize cannot handle op_=" << op_ << endl;
|
||||
des->errors += 1;
|
||||
return expr_->synthesize(des, scope);
|
||||
}
|
||||
|
||||
NetNet* NetEUReduce::synthesize(Design*des, NetScope*scope)
|
||||
{
|
||||
NetNet*isig = expr_->synthesize(des, scope);
|
||||
|
||||
|
|
@ -909,12 +857,7 @@ NetNet* NetEUReduce::synthesize(Design*des, NetScope*scope,
|
|||
return osig;
|
||||
}
|
||||
|
||||
NetNet* NetESelect::synthesize(Design *des, NetScope*scope,
|
||||
const NetExpr* rise,
|
||||
const NetExpr* fall,
|
||||
const NetExpr* decay,
|
||||
Link::strength_t drive0,
|
||||
Link::strength_t drive1)
|
||||
NetNet* NetESelect::synthesize(Design *des, NetScope*scope)
|
||||
{
|
||||
|
||||
NetNet*sub = expr_->synthesize(des, scope);
|
||||
|
|
@ -1008,12 +951,7 @@ NetNet* NetESelect::synthesize(Design *des, NetScope*scope,
|
|||
* expressions to the B and A inputs. This way, when the select input
|
||||
* is one, the B input, which is the true expression, is selected.
|
||||
*/
|
||||
NetNet* NetETernary::synthesize(Design *des, NetScope*scope,
|
||||
const NetExpr* rise,
|
||||
const NetExpr* fall,
|
||||
const NetExpr* decay,
|
||||
Link::strength_t drive0,
|
||||
Link::strength_t drive1)
|
||||
NetNet* NetETernary::synthesize(Design *des, NetScope*scope)
|
||||
{
|
||||
NetNet*csig = cond_->synthesize(des, scope),
|
||||
*tsig = true_val_->synthesize(des, scope),
|
||||
|
|
@ -1071,12 +1009,7 @@ NetNet* NetETernary::synthesize(Design *des, NetScope*scope,
|
|||
* a bit more work needs to be done. Return a temporary that represents
|
||||
* the selected word.
|
||||
*/
|
||||
NetNet* NetESignal::synthesize(Design*des, NetScope*scope,
|
||||
const NetExpr* rise,
|
||||
const NetExpr* fall,
|
||||
const NetExpr* decay,
|
||||
Link::strength_t drive0,
|
||||
Link::strength_t drive1)
|
||||
NetNet* NetESignal::synthesize(Design*des, NetScope*scope)
|
||||
{
|
||||
if (word_ == 0)
|
||||
return net_;
|
||||
|
|
@ -1087,13 +1020,14 @@ NetNet* NetESignal::synthesize(Design*des, NetScope*scope,
|
|||
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.
|
||||
|
||||
if (NetEConst*index_co = dynamic_cast<NetEConst*> (word_)) {
|
||||
|
||||
long index = index_co->value().as_long();
|
||||
|
||||
assert(net_->array_index_is_valid(index));
|
||||
index = net_->array_index_to_address(index);
|
||||
|
||||
connect(tmp->pin(0), net_->pin(index));
|
||||
|
||||
} else {
|
||||
unsigned selwid = word_->expr_width();
|
||||
|
||||
|
|
@ -1110,25 +1044,61 @@ NetNet* NetESignal::synthesize(Design*des, NetScope*scope,
|
|||
return tmp;
|
||||
}
|
||||
|
||||
NetNet* NetESFunc::synthesize(Design*des, NetScope*scope,
|
||||
const NetExpr* rise,
|
||||
const NetExpr* fall,
|
||||
const NetExpr* decay,
|
||||
Link::strength_t drive0,
|
||||
Link::strength_t drive1)
|
||||
NetNet* NetESFunc::synthesize(Design*des, NetScope*scope)
|
||||
{
|
||||
cerr << get_fileline() << ": sorry: cannot synthesize system function: "
|
||||
<< *this << " in this context" << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
|
||||
const struct sfunc_return_type*def = lookup_sys_func(name_);
|
||||
|
||||
/* We cannot use the default value for system functions in a
|
||||
* continuous assignment since the function name is NULL. */
|
||||
if (def == 0 || def->name == 0) {
|
||||
cerr << get_fileline() << ": error: System function "
|
||||
<< name_ << " not defined in system "
|
||||
"table or SFT file(s)." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (debug_elaborate) {
|
||||
cerr << get_fileline() << ": debug: Net system function "
|
||||
<< name_ << " returns " << def->type << endl;
|
||||
}
|
||||
|
||||
NetSysFunc*net = new NetSysFunc(scope, scope->local_symbol(),
|
||||
def, 1+nparms_);
|
||||
net->set_line(*this);
|
||||
des->add_node(net);
|
||||
|
||||
NetNet*osig = new NetNet(scope, scope->local_symbol(),
|
||||
NetNet::WIRE, def->wid);
|
||||
osig->local_flag(true);
|
||||
osig->set_signed(def->type==IVL_VT_REAL? true : false);
|
||||
osig->data_type(def->type);
|
||||
osig->set_line(*this);
|
||||
|
||||
connect(net->pin(0), osig->pin(0));
|
||||
|
||||
unsigned errors = 0;
|
||||
for (unsigned idx = 0 ; idx < nparms_ ; idx += 1) {
|
||||
NetNet*tmp = parms_[idx]->synthesize(des, scope);
|
||||
if (tmp == 0) {
|
||||
cerr << get_fileline() << ": error: Unable to elaborate "
|
||||
<< "argument " << idx << " of call to " << name_ <<
|
||||
"." << endl;
|
||||
errors += 1;
|
||||
des->errors += 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
connect(net->pin(1+idx), tmp->pin(0));
|
||||
}
|
||||
|
||||
if (errors > 0) return 0;
|
||||
|
||||
return osig;
|
||||
}
|
||||
|
||||
NetNet* NetEUFunc::synthesize(Design*des, NetScope*scope,
|
||||
const NetExpr* rise,
|
||||
const NetExpr* fall,
|
||||
const NetExpr* decay,
|
||||
Link::strength_t drive0,
|
||||
Link::strength_t drive1)
|
||||
NetNet* NetEUFunc::synthesize(Design*des, NetScope*scope)
|
||||
{
|
||||
svector<NetNet*> eparms (parms_.count());
|
||||
|
||||
|
|
|
|||
16
net_link.cc
16
net_link.cc
|
|
@ -103,6 +103,11 @@ void Link::drivers_delays(NetExpr*rise, NetExpr*fall, NetExpr*decay)
|
|||
nexus_->drivers_delays(rise, fall, decay);
|
||||
}
|
||||
|
||||
void Link::drivers_drive(strength_t drive0, strength_t drive1)
|
||||
{
|
||||
nexus_->drivers_drive(drive0, drive1);
|
||||
}
|
||||
|
||||
void Link::drive0(Link::strength_t str)
|
||||
{
|
||||
drive0_ = str;
|
||||
|
|
@ -295,6 +300,17 @@ void Nexus::drivers_delays(NetExpr*rise, NetExpr*fall, NetExpr*decay)
|
|||
}
|
||||
}
|
||||
|
||||
void Nexus::drivers_drive(Link::strength_t drive0, Link::strength_t drive1)
|
||||
{
|
||||
for (Link*cur = list_ ; cur ; cur = cur->next_) {
|
||||
if (cur->get_dir() != Link::OUTPUT)
|
||||
continue;
|
||||
|
||||
cur->drive0(drive0);
|
||||
cur->drive1(drive1);
|
||||
}
|
||||
}
|
||||
|
||||
void Nexus::unlink(Link*that)
|
||||
{
|
||||
if (name_) {
|
||||
|
|
|
|||
139
netlist.h
139
netlist.h
|
|
@ -178,6 +178,10 @@ class Link {
|
|||
void drive0(strength_t);
|
||||
void drive1(strength_t);
|
||||
|
||||
// This sets the drives for all drivers of this link, and not
|
||||
// just the current link.
|
||||
void drivers_drive(strength_t d0, strength_t d1);
|
||||
|
||||
strength_t drive0() const;
|
||||
strength_t drive1() const;
|
||||
|
||||
|
|
@ -280,6 +284,7 @@ class Nexus {
|
|||
verinum::V get_init() const;
|
||||
|
||||
void drivers_delays(NetExpr*rise, NetExpr*fall, NetExpr*decay);
|
||||
void drivers_drive(Link::strength_t d0, Link::strength_t d1);
|
||||
|
||||
Link*first_nlink();
|
||||
const Link* first_nlink()const;
|
||||
|
|
@ -1544,12 +1549,7 @@ class NetExpr : public LineInfo {
|
|||
//
|
||||
// drive0/drive1: Attach these strengths tp the driver for
|
||||
// the expression output.
|
||||
virtual NetNet*synthesize(Design*des, NetScope*scope,
|
||||
const NetExpr* rise =0,
|
||||
const NetExpr* fall =0,
|
||||
const NetExpr* decay =0,
|
||||
Link::strength_t drive0 =Link::STRONG,
|
||||
Link::strength_t drive1 =Link::STRONG);
|
||||
virtual NetNet*synthesize(Design*des, NetScope*scope);
|
||||
|
||||
|
||||
protected:
|
||||
|
|
@ -1587,12 +1587,7 @@ class NetEConst : public NetExpr {
|
|||
virtual void dump(ostream&) const;
|
||||
|
||||
virtual NetEConst* dup_expr() const;
|
||||
virtual NetNet*synthesize(Design*, NetScope*scope,
|
||||
const NetExpr* rise =0,
|
||||
const NetExpr* fall =0,
|
||||
const NetExpr* decay =0,
|
||||
Link::strength_t drive0 =Link::STRONG,
|
||||
Link::strength_t drive1 =Link::STRONG);
|
||||
virtual NetNet*synthesize(Design*, NetScope*scope);
|
||||
virtual NexusSet* nex_input(bool rem_out = true);
|
||||
|
||||
private:
|
||||
|
|
@ -1645,12 +1640,7 @@ class NetECReal : public NetExpr {
|
|||
virtual void dump(ostream&) const;
|
||||
|
||||
virtual NetECReal* dup_expr() const;
|
||||
virtual NetNet*synthesize(Design*, NetScope*scope,
|
||||
const NetExpr* rise =0,
|
||||
const NetExpr* fall =0,
|
||||
const NetExpr* decay =0,
|
||||
Link::strength_t drive0 =Link::STRONG,
|
||||
Link::strength_t drive1 =Link::STRONG);
|
||||
virtual NetNet*synthesize(Design*, NetScope*scope);
|
||||
virtual NexusSet* nex_input(bool rem_out = true);
|
||||
|
||||
private:
|
||||
|
|
@ -2887,12 +2877,7 @@ class NetEUFunc : public NetExpr {
|
|||
virtual void expr_scan(struct expr_scan_t*) const;
|
||||
virtual NetEUFunc*dup_expr() const;
|
||||
virtual NexusSet* nex_input(bool rem_out = true);
|
||||
virtual NetNet* synthesize(Design*des, NetScope*scope,
|
||||
const NetExpr* rise =0,
|
||||
const NetExpr* fall =0,
|
||||
const NetExpr* decay =0,
|
||||
Link::strength_t drive0 =Link::STRONG,
|
||||
Link::strength_t drive1 =Link::STRONG);
|
||||
virtual NetNet* synthesize(Design*des, NetScope*scope);
|
||||
|
||||
private:
|
||||
NetScope*scope_;
|
||||
|
|
@ -3086,12 +3071,7 @@ class NetEBAdd : public NetEBinary {
|
|||
virtual bool set_width(unsigned w, bool last_chance);
|
||||
virtual NetEBAdd* dup_expr() const;
|
||||
virtual NetExpr* eval_tree(int prune_to_width = -1);
|
||||
virtual NetNet* synthesize(Design*, NetScope*scope,
|
||||
const NetExpr* rise =0,
|
||||
const NetExpr* fall =0,
|
||||
const NetExpr* decay =0,
|
||||
Link::strength_t drive0 =Link::STRONG,
|
||||
Link::strength_t drive1 =Link::STRONG);
|
||||
virtual NetNet* synthesize(Design*, NetScope*scope);
|
||||
|
||||
private:
|
||||
NetECReal* eval_tree_real_();
|
||||
|
|
@ -3113,12 +3093,7 @@ class NetEBDiv : public NetEBinary {
|
|||
virtual bool set_width(unsigned w, bool last_chance);
|
||||
virtual NetEBDiv* dup_expr() const;
|
||||
virtual NetExpr* eval_tree(int prune_to_width = -1);
|
||||
virtual NetNet* synthesize(Design*, NetScope*scope,
|
||||
const NetExpr* rise =0,
|
||||
const NetExpr* fall =0,
|
||||
const NetExpr* decay =0,
|
||||
Link::strength_t drive0 =Link::STRONG,
|
||||
Link::strength_t drive1 =Link::STRONG);
|
||||
virtual NetNet* synthesize(Design*, NetScope*scope);
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
@ -3145,12 +3120,7 @@ class NetEBBits : public NetEBinary {
|
|||
virtual NetEBBits* dup_expr() const;
|
||||
virtual NetEConst* eval_tree(int prune_to_width = -1);
|
||||
|
||||
virtual NetNet* synthesize(Design*, NetScope*scope,
|
||||
const NetExpr* rise =0,
|
||||
const NetExpr* fall =0,
|
||||
const NetExpr* decay =0,
|
||||
Link::strength_t drive0 =Link::STRONG,
|
||||
Link::strength_t drive1 =Link::STRONG);
|
||||
virtual NetNet* synthesize(Design*, NetScope*scope);
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
@ -3181,12 +3151,7 @@ class NetEBComp : public NetEBinary {
|
|||
virtual NetEBComp* dup_expr() const;
|
||||
virtual NetEConst* eval_tree(int prune_to_width = -1);
|
||||
|
||||
virtual NetNet* synthesize(Design*, NetScope*scope,
|
||||
const NetExpr* rise =0,
|
||||
const NetExpr* fall =0,
|
||||
const NetExpr* decay =0,
|
||||
Link::strength_t drive0 =Link::STRONG,
|
||||
Link::strength_t drive1 =Link::STRONG);
|
||||
virtual NetNet* synthesize(Design*, NetScope*scope);
|
||||
|
||||
private:
|
||||
NetEConst* must_be_leeq_(NetExpr*le, const verinum&rv, bool eq_flag);
|
||||
|
|
@ -3217,12 +3182,7 @@ class NetEBLogic : public NetEBinary {
|
|||
virtual bool set_width(unsigned w, bool last_chance);
|
||||
virtual NetEBLogic* dup_expr() const;
|
||||
virtual NetEConst* eval_tree(int prune_to_width = -1);
|
||||
virtual NetNet* synthesize(Design*, NetScope*scope,
|
||||
const NetExpr* rise =0,
|
||||
const NetExpr* fall =0,
|
||||
const NetExpr* decay =0,
|
||||
Link::strength_t drive0 =Link::STRONG,
|
||||
Link::strength_t drive1 =Link::STRONG);
|
||||
virtual NetNet* synthesize(Design*, NetScope*scope);
|
||||
|
||||
private:
|
||||
};
|
||||
|
|
@ -3260,12 +3220,7 @@ class NetEBMult : public NetEBinary {
|
|||
virtual bool set_width(unsigned w, bool last_chance);
|
||||
virtual NetEBMult* dup_expr() const;
|
||||
virtual NetExpr* eval_tree(int prune_to_width = -1);
|
||||
virtual NetNet* synthesize(Design*, NetScope*scope,
|
||||
const NetExpr* rise =0,
|
||||
const NetExpr* fall =0,
|
||||
const NetExpr* decay =0,
|
||||
Link::strength_t drive0 =Link::STRONG,
|
||||
Link::strength_t drive1 =Link::STRONG);
|
||||
virtual NetNet* synthesize(Design*, NetScope*scope);
|
||||
|
||||
private:
|
||||
|
||||
|
|
@ -3287,12 +3242,7 @@ class NetEBPow : public NetEBinary {
|
|||
virtual bool set_width(unsigned w, bool last_chance);
|
||||
virtual NetEBPow* dup_expr() const;
|
||||
virtual NetExpr* eval_tree(int prune_to_width = -1);
|
||||
virtual NetNet* synthesize(Design*, NetScope*scope,
|
||||
const NetExpr* rise =0,
|
||||
const NetExpr* fall =0,
|
||||
const NetExpr* decay =0,
|
||||
Link::strength_t drive0 =Link::STRONG,
|
||||
Link::strength_t drive1 =Link::STRONG);
|
||||
virtual NetNet* synthesize(Design*, NetScope*scope);
|
||||
|
||||
private:
|
||||
|
||||
|
|
@ -3324,12 +3274,7 @@ class NetEBShift : public NetEBinary {
|
|||
virtual NetEBShift* dup_expr() const;
|
||||
virtual NetEConst* eval_tree(int prune_to_width = -1);
|
||||
|
||||
virtual NetNet* synthesize(Design*, NetScope*scope,
|
||||
const NetExpr* rise =0,
|
||||
const NetExpr* fall =0,
|
||||
const NetExpr* decay =0,
|
||||
Link::strength_t drive0 =Link::STRONG,
|
||||
Link::strength_t drive1 =Link::STRONG);
|
||||
virtual NetNet* synthesize(Design*, NetScope*scope);
|
||||
|
||||
private:
|
||||
};
|
||||
|
|
@ -3363,12 +3308,7 @@ class NetEConcat : public NetExpr {
|
|||
virtual bool set_width(unsigned w, bool last_chance =false);
|
||||
virtual NetEConcat* dup_expr() const;
|
||||
virtual NetEConst* eval_tree(int prune_to_width = -1);
|
||||
virtual NetNet*synthesize(Design*, NetScope*scope,
|
||||
const NetExpr* rise =0,
|
||||
const NetExpr* fall =0,
|
||||
const NetExpr* decay =0,
|
||||
Link::strength_t drive0 =Link::STRONG,
|
||||
Link::strength_t drive1 =Link::STRONG);
|
||||
virtual NetNet*synthesize(Design*, NetScope*scope);
|
||||
virtual void expr_scan(struct expr_scan_t*) const;
|
||||
virtual void dump(ostream&) const;
|
||||
|
||||
|
|
@ -3444,12 +3384,7 @@ class NetESelect : public NetExpr {
|
|||
virtual void expr_scan(struct expr_scan_t*) const;
|
||||
virtual NetEConst* eval_tree(int prune_to_width = -1);
|
||||
virtual NetESelect* dup_expr() const;
|
||||
virtual NetNet*synthesize(Design*des, NetScope*scope,
|
||||
const NetExpr* rise =0,
|
||||
const NetExpr* fall =0,
|
||||
const NetExpr* decay =0,
|
||||
Link::strength_t drive0 =Link::STRONG,
|
||||
Link::strength_t drive1 =Link::STRONG);
|
||||
virtual NetNet*synthesize(Design*des, NetScope*scope);
|
||||
virtual void dump(ostream&) const;
|
||||
|
||||
private:
|
||||
|
|
@ -3527,12 +3462,7 @@ class NetESFunc : public NetExpr {
|
|||
|
||||
virtual void expr_scan(struct expr_scan_t*) const;
|
||||
virtual NetESFunc*dup_expr() const;
|
||||
virtual NetNet*synthesize(Design*, NetScope*scope,
|
||||
const NetExpr* rise =0,
|
||||
const NetExpr* fall =0,
|
||||
const NetExpr* decay =0,
|
||||
Link::strength_t drive0 =Link::STRONG,
|
||||
Link::strength_t drive1 =Link::STRONG);
|
||||
virtual NetNet*synthesize(Design*, NetScope*scope);
|
||||
|
||||
private:
|
||||
const char* name_;
|
||||
|
|
@ -3569,12 +3499,7 @@ class NetETernary : public NetExpr {
|
|||
virtual NexusSet* nex_input(bool rem_out = true);
|
||||
virtual void expr_scan(struct expr_scan_t*) const;
|
||||
virtual void dump(ostream&) const;
|
||||
virtual NetNet*synthesize(Design*, NetScope*scope,
|
||||
const NetExpr* rise =0,
|
||||
const NetExpr* fall =0,
|
||||
const NetExpr* decay =0,
|
||||
Link::strength_t drive0 =Link::STRONG,
|
||||
Link::strength_t drive1 =Link::STRONG);
|
||||
virtual NetNet*synthesize(Design*, NetScope*scope);
|
||||
|
||||
private:
|
||||
NetExpr*cond_;
|
||||
|
|
@ -3611,6 +3536,7 @@ class NetEUnary : public NetExpr {
|
|||
|
||||
virtual NetEUnary* dup_expr() const;
|
||||
virtual NetExpr* eval_tree(int prune_to_width = -1);
|
||||
virtual NetNet* synthesize(Design*, NetScope*scope);
|
||||
|
||||
virtual ivl_variable_type_t expr_type() const;
|
||||
virtual NexusSet* nex_input(bool rem_out = true);
|
||||
|
|
@ -3631,12 +3557,7 @@ class NetEUBits : public NetEUnary {
|
|||
NetEUBits(char op, NetExpr*ex);
|
||||
~NetEUBits();
|
||||
|
||||
virtual NetNet* synthesize(Design*, NetScope*scope,
|
||||
const NetExpr* rise =0,
|
||||
const NetExpr* fall =0,
|
||||
const NetExpr* decay =0,
|
||||
Link::strength_t drive0 =Link::STRONG,
|
||||
Link::strength_t drive1 =Link::STRONG);
|
||||
virtual NetNet* synthesize(Design*, NetScope*scope);
|
||||
|
||||
virtual NetExpr* eval_tree(int prune_to_width = -1);
|
||||
virtual ivl_variable_type_t expr_type() const;
|
||||
|
|
@ -3649,12 +3570,7 @@ class NetEUReduce : public NetEUnary {
|
|||
~NetEUReduce();
|
||||
|
||||
virtual bool set_width(unsigned w, bool last_chance);
|
||||
virtual NetNet* synthesize(Design*, NetScope*scope,
|
||||
const NetExpr* rise =0,
|
||||
const NetExpr* fall =0,
|
||||
const NetExpr* decay =0,
|
||||
Link::strength_t drive0 =Link::STRONG,
|
||||
Link::strength_t drive1 =Link::STRONG);
|
||||
virtual NetNet* synthesize(Design*, NetScope*scope);
|
||||
virtual NetEUReduce* dup_expr() const;
|
||||
virtual NetEConst* eval_tree(int prune_to_width = -1);
|
||||
virtual ivl_variable_type_t expr_type() const;
|
||||
|
|
@ -3681,12 +3597,7 @@ class NetESignal : public NetExpr {
|
|||
virtual bool set_width(unsigned, bool last_chance);
|
||||
|
||||
virtual NetESignal* dup_expr() const;
|
||||
NetNet* synthesize(Design*des, NetScope*scope,
|
||||
const NetExpr* rise =0,
|
||||
const NetExpr* fall =0,
|
||||
const NetExpr* decay =0,
|
||||
Link::strength_t drive0 =Link::STRONG,
|
||||
Link::strength_t drive1 =Link::STRONG);
|
||||
NetNet* synthesize(Design*des, NetScope*scope);
|
||||
NexusSet* nex_input(bool rem_out = true);
|
||||
|
||||
// This is the expression for selecting an array word, if this
|
||||
|
|
|
|||
Loading…
Reference in New Issue