Merge pull request #1369 from larsclausen/unpacked-array-assign-strength-delay
Preserve delay and strength in unpacked array continuous assignments
This commit is contained in:
commit
129a5c980f
44
PDelays.cc
44
PDelays.cc
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 1999-2025 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 1999-2026 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
|
||||
|
|
@ -130,10 +130,11 @@ static NetExpr* make_delay_nets(Design*des, NetScope*scope, NetExpr*expr)
|
|||
return expr;
|
||||
}
|
||||
|
||||
static NetExpr* calc_decay_time(NetExpr *rise, NetExpr *fall)
|
||||
static const NetExpr *calc_decay_time(const NetExpr *rise,
|
||||
const NetExpr *fall)
|
||||
{
|
||||
const NetEConst *c_rise = dynamic_cast<NetEConst*>(rise);
|
||||
const NetEConst *c_fall = dynamic_cast<NetEConst*>(fall);
|
||||
const NetEConst *c_rise = dynamic_cast<const NetEConst*>(rise);
|
||||
const NetEConst *c_fall = dynamic_cast<const NetEConst*>(fall);
|
||||
if (c_rise && c_fall) {
|
||||
if (c_rise->value() < c_fall->value()) return rise;
|
||||
else return fall;
|
||||
|
|
@ -142,44 +143,43 @@ static NetExpr* calc_decay_time(NetExpr *rise, NetExpr *fall)
|
|||
return 0;
|
||||
}
|
||||
|
||||
void PDelays::eval_delays(Design*des, NetScope*scope,
|
||||
NetExpr*&rise_time,
|
||||
NetExpr*&fall_time,
|
||||
NetExpr*&decay_time,
|
||||
void PDelays::eval_delays(Design*des, NetScope*scope, delay_exprs_t &delays,
|
||||
bool as_nets_flag) const
|
||||
{
|
||||
assert(scope);
|
||||
|
||||
|
||||
if (delay_[0]) {
|
||||
rise_time = calculate_val(des, scope, delay_[0]);
|
||||
NetExpr *rise = calculate_val(des, scope, delay_[0]);
|
||||
if (as_nets_flag)
|
||||
rise_time = make_delay_nets(des, scope, rise_time);
|
||||
rise = make_delay_nets(des, scope, rise);
|
||||
delays.rise = rise;
|
||||
|
||||
if (delay_[1]) {
|
||||
fall_time = calculate_val(des, scope, delay_[1]);
|
||||
NetExpr *fall = calculate_val(des, scope, delay_[1]);
|
||||
if (as_nets_flag)
|
||||
fall_time = make_delay_nets(des, scope, fall_time);
|
||||
fall = make_delay_nets(des, scope, fall);
|
||||
delays.fall = fall;
|
||||
|
||||
if (delay_[2]) {
|
||||
decay_time = calculate_val(des, scope, delay_[2]);
|
||||
NetExpr *decay = calculate_val(des, scope, delay_[2]);
|
||||
if (as_nets_flag)
|
||||
decay_time = make_delay_nets(des, scope,
|
||||
decay_time);
|
||||
decay = make_delay_nets(des, scope, decay);
|
||||
delays.decay = decay;
|
||||
|
||||
} else {
|
||||
// If this is zero then we need to do the min()
|
||||
// at run time.
|
||||
decay_time = calc_decay_time(rise_time, fall_time);
|
||||
delays.decay = calc_decay_time(delays.rise,
|
||||
delays.fall);
|
||||
}
|
||||
} else {
|
||||
assert(delay_[2] == 0);
|
||||
fall_time = rise_time;
|
||||
decay_time = rise_time;
|
||||
delays.fall = delays.rise;
|
||||
delays.decay = delays.rise;
|
||||
}
|
||||
} else {
|
||||
rise_time = 0;
|
||||
fall_time = 0;
|
||||
decay_time = 0;
|
||||
delays.rise = nullptr;
|
||||
delays.fall = nullptr;
|
||||
delays.decay = nullptr;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
#ifndef IVL_PDelays_H
|
||||
#define IVL_PDelays_H
|
||||
/*
|
||||
* Copyright (c) 1999-2021 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 1999-2026 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
|
||||
|
|
@ -27,6 +27,7 @@ class Design;
|
|||
class NetScope;
|
||||
class NetExpr;
|
||||
class PExpr;
|
||||
struct delay_exprs_t;
|
||||
|
||||
/*
|
||||
* Various PForm objects can carry delays. These delays include rise,
|
||||
|
|
@ -46,10 +47,7 @@ class PDelays {
|
|||
|
||||
unsigned delay_count() const;
|
||||
|
||||
void eval_delays(Design*des, NetScope*scope,
|
||||
NetExpr*&rise_time,
|
||||
NetExpr*&fall_time,
|
||||
NetExpr*&decay_time,
|
||||
void eval_delays(Design*des, NetScope*scope, delay_exprs_t &delays,
|
||||
bool as_nets_flag =false) const;
|
||||
|
||||
void dump_delays(std::ostream&out) const;
|
||||
|
|
|
|||
41
PGate.cc
41
PGate.cc
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 1999-2025 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 1999-2026 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
|
||||
|
|
@ -41,29 +41,23 @@ void PGate::set_pins_(list<PExpr*>*pins)
|
|||
}
|
||||
|
||||
PGate::PGate(perm_string name, list<PExpr*>*pins, const list<PExpr*>*del)
|
||||
: name_(name), pins_(pins? pins->size() : 0), ranges_(0)
|
||||
: name_(name), pins_(pins? pins->size() : 0), ranges_(nullptr)
|
||||
{
|
||||
if (pins) set_pins_(pins);
|
||||
if (del) delay_.set_delays(del);
|
||||
str0_ = IVL_DR_STRONG;
|
||||
str1_ = IVL_DR_STRONG;
|
||||
}
|
||||
|
||||
PGate::PGate(perm_string name, list<PExpr*>*pins, PExpr*del)
|
||||
: name_(name), pins_(pins? pins->size() : 0), ranges_(0)
|
||||
: name_(name), pins_(pins? pins->size() : 0), ranges_(nullptr)
|
||||
{
|
||||
if (pins) set_pins_(pins);
|
||||
if (del) delay_.set_delay(del);
|
||||
str0_ = IVL_DR_STRONG;
|
||||
str1_ = IVL_DR_STRONG;
|
||||
}
|
||||
|
||||
PGate::PGate(perm_string name, list<PExpr*>*pins)
|
||||
: name_(name), pins_(pins? pins->size() : 0), ranges_(0)
|
||||
: name_(name), pins_(pins? pins->size() : 0), ranges_(nullptr)
|
||||
{
|
||||
if (pins) set_pins_(pins);
|
||||
str0_ = IVL_DR_STRONG;
|
||||
str1_ = IVL_DR_STRONG;
|
||||
}
|
||||
|
||||
PGate::~PGate()
|
||||
|
|
@ -76,24 +70,14 @@ void PGate::set_ranges(list<pform_range_t>*ranges)
|
|||
ranges_ = ranges;
|
||||
}
|
||||
|
||||
ivl_drive_t PGate::strength0() const
|
||||
drive_strength_t PGate::strength() const
|
||||
{
|
||||
return str0_;
|
||||
return strength_;
|
||||
}
|
||||
|
||||
void PGate::strength0(ivl_drive_t s)
|
||||
void PGate::strength(const drive_strength_t &str)
|
||||
{
|
||||
str0_ = s;
|
||||
}
|
||||
|
||||
ivl_drive_t PGate::strength1() const
|
||||
{
|
||||
return str1_;
|
||||
}
|
||||
|
||||
void PGate::strength1(ivl_drive_t s)
|
||||
{
|
||||
str1_ = s;
|
||||
strength_ = str;
|
||||
}
|
||||
|
||||
void PGate::elaborate_scope(Design*, NetScope*) const
|
||||
|
|
@ -109,15 +93,10 @@ void PGate::elaborate_scope(Design*, NetScope*) const
|
|||
* numbers of expressions.
|
||||
*/
|
||||
|
||||
void PGate::eval_delays(Design*des, NetScope*scope,
|
||||
NetExpr*&rise_expr,
|
||||
NetExpr*&fall_expr,
|
||||
NetExpr*&decay_expr,
|
||||
void PGate::eval_delays(Design*des, NetScope*scope, delay_exprs_t &delays,
|
||||
bool as_net_flag) const
|
||||
{
|
||||
delay_.eval_delays(des, scope,
|
||||
rise_expr, fall_expr, decay_expr,
|
||||
as_net_flag);
|
||||
delay_.eval_delays(des, scope, delays, as_net_flag);
|
||||
}
|
||||
|
||||
unsigned PGate::delay_count() const
|
||||
|
|
|
|||
19
PGate.h
19
PGate.h
|
|
@ -31,6 +31,8 @@
|
|||
class PExpr;
|
||||
class PUdp;
|
||||
class Module;
|
||||
struct delay_exprs_t;
|
||||
struct drive_strength_t;
|
||||
|
||||
/*
|
||||
* A PGate represents a Verilog gate. The gate has a name and other
|
||||
|
|
@ -66,10 +68,7 @@ class PGate : public PNamedItem {
|
|||
|
||||
// This evaluates the delays as far as possible, but returns
|
||||
// an expression, and do not signal errors.
|
||||
void eval_delays(Design*des, NetScope*scope,
|
||||
NetExpr*&rise_time,
|
||||
NetExpr*&fall_time,
|
||||
NetExpr*&decay_time,
|
||||
void eval_delays(Design*des, NetScope*scope, delay_exprs_t &delays,
|
||||
bool as_net_flag =false) const;
|
||||
|
||||
unsigned delay_count() const;
|
||||
|
|
@ -77,11 +76,9 @@ class PGate : public PNamedItem {
|
|||
unsigned pin_count() const { return pins_.size(); }
|
||||
PExpr*pin(unsigned idx) const { return pins_[idx]; }
|
||||
|
||||
ivl_drive_t strength0() const;
|
||||
ivl_drive_t strength1() const;
|
||||
drive_strength_t strength() const;
|
||||
|
||||
void strength0(ivl_drive_t);
|
||||
void strength1(ivl_drive_t);
|
||||
void strength(const drive_strength_t &str);
|
||||
|
||||
std::map<perm_string,PExpr*> attributes;
|
||||
|
||||
|
|
@ -109,7 +106,7 @@ class PGate : public PNamedItem {
|
|||
|
||||
std::list<pform_range_t>*ranges_;
|
||||
|
||||
ivl_drive_t str0_, str1_;
|
||||
drive_strength_t strength_;
|
||||
|
||||
void set_pins_(std::list<PExpr*>*pins);
|
||||
|
||||
|
|
@ -133,7 +130,9 @@ class PGAssign : public PGate {
|
|||
virtual void elaborate(Design*des, NetScope*scope) const override;
|
||||
|
||||
private:
|
||||
void elaborate_unpacked_array_(Design*des, NetScope*scope, NetNet*lval) const;
|
||||
void elaborate_unpacked_array_(Design*des, NetScope*scope, NetNet*lval,
|
||||
const drive_strength_t &drive,
|
||||
const delay_exprs_t &delays) const;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
4
cprop.cc
4
cprop.cc
|
|
@ -180,9 +180,7 @@ void cprop_functor::lpm_mux(Design*des, NetMux*obj)
|
|||
<< "Replace binary MUX with constant select=" << sel_val
|
||||
<< " with a BUFZ to the selected input." << endl;
|
||||
|
||||
tmp->rise_time(obj->rise_time());
|
||||
tmp->fall_time(obj->fall_time());
|
||||
tmp->decay_time(obj->decay_time());
|
||||
tmp->delay_times(obj->delay_times());
|
||||
|
||||
connect(tmp->pin(0), obj->pin_Result());
|
||||
if (sel_val == verinum::V1)
|
||||
|
|
|
|||
107
design_dump.cc
107
design_dump.cc
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 1998-2021 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 1998-2026 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
|
||||
|
|
@ -90,6 +90,30 @@ ostream& operator << (ostream&o, ivl_drive_t str)
|
|||
return o;
|
||||
}
|
||||
|
||||
ostream &operator << (ostream &o, const drive_strength_t &strength)
|
||||
{
|
||||
o << strength.drive0 << "0 " << strength.drive1 << "1";
|
||||
return o;
|
||||
}
|
||||
|
||||
static void dump_delay_expr(ostream &o, const NetExpr *expr)
|
||||
{
|
||||
if (expr)
|
||||
o << *expr;
|
||||
else
|
||||
o << "0";
|
||||
}
|
||||
|
||||
ostream &operator << (ostream &o, const delay_exprs_t &delays)
|
||||
{
|
||||
dump_delay_expr(o, delays.rise);
|
||||
o << ",";
|
||||
dump_delay_expr(o, delays.fall);
|
||||
o << ",";
|
||||
dump_delay_expr(o, delays.decay);
|
||||
return o;
|
||||
}
|
||||
|
||||
ostream& operator << (ostream&o, ivl_variable_type_t val)
|
||||
{
|
||||
switch (val) {
|
||||
|
|
@ -454,8 +478,7 @@ void NetNet::dump_net(ostream&o, unsigned ind) const
|
|||
o << " (eref=" << peek_eref() << ", lref=" << peek_lref() << ")";
|
||||
if (scope())
|
||||
o << " scope=" << scope_path(scope());
|
||||
o << " #(" << rise_time() << "," << fall_time() << ","
|
||||
<< decay_time() << ") vector_width=" << vector_width()
|
||||
o << " #(" << delay_times() << ") vector_width=" << vector_width()
|
||||
<< " pin_count=" << pin_count();
|
||||
if (pins_are_virtual()) {
|
||||
o << " pins_are_virtual" << endl;
|
||||
|
|
@ -486,8 +509,7 @@ void NetNet::dump_net(ostream&o, unsigned ind) const
|
|||
void NetNode::dump_node(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "" << "node: ";
|
||||
o << typeid(*this).name() << " #(" << rise_time()
|
||||
<< "," << fall_time() << "," << decay_time() << ") " << name()
|
||||
o << typeid(*this).name() << " #(" << delay_times() << ") " << name()
|
||||
<< endl;
|
||||
|
||||
dump_node_pins(o, ind+4);
|
||||
|
|
@ -518,8 +540,7 @@ void NetPins::dump_node_pins(ostream&o, unsigned ind, const char**pin_names) con
|
|||
break;
|
||||
}
|
||||
|
||||
o << " (" << pin(idx).drive0() << "0 "
|
||||
<< pin(idx).drive1() << "1): ";
|
||||
o << " (" << pin(idx).drive() << "): ";
|
||||
|
||||
if (pin(idx).is_linked()) {
|
||||
const Nexus*nex = pin(idx).nexus();
|
||||
|
|
@ -622,11 +643,7 @@ void NetConcat::dump_node(ostream&o, unsigned ind) const
|
|||
o << setw(ind) << "" << "NetConcat: ";
|
||||
o << name();
|
||||
|
||||
if (rise_time())
|
||||
o << " #(" << *rise_time()
|
||||
<< "," << *fall_time() << "," << *decay_time() << ")";
|
||||
else
|
||||
o << " #(0,0,0)";
|
||||
o << " #(" << delay_times() << ")";
|
||||
o << " scope=" << scope_path(scope())
|
||||
<< " width=" << width_ << endl;
|
||||
dump_node_pins(o, ind+4);
|
||||
|
|
@ -651,14 +668,7 @@ void NetPow::dump_node(ostream&o, unsigned ind) const
|
|||
{
|
||||
o << setw(ind) << "" << "LPM_POW (NetPow): " << name()
|
||||
<< " scope=" << scope_path(scope())
|
||||
<< " delay=(";
|
||||
if (rise_time())
|
||||
o << *rise_time() << "," << *fall_time() << ","
|
||||
<< *decay_time();
|
||||
else
|
||||
o << "0,0,0";
|
||||
|
||||
o << ")" << endl;
|
||||
<< " delay=(" << delay_times() << ")" << endl;
|
||||
dump_node_pins(o, ind+4);
|
||||
dump_obj_attr(o, ind+4);
|
||||
}
|
||||
|
|
@ -676,8 +686,7 @@ void NetBUFZ::dump_node(ostream&o, unsigned ind) const
|
|||
{
|
||||
o << setw(ind) << "" << "NetBUFZ: " << name()
|
||||
<< " scope=" << scope_path(scope())
|
||||
<< " delay=(" << rise_time() << "," << fall_time() << "," <<
|
||||
decay_time() << ") width=" << width()
|
||||
<< " delay=(" << delay_times() << ") width=" << width()
|
||||
<< (transparent()? " " : " non-") << "transparent" << endl;
|
||||
dump_node_pins(o, ind+4);
|
||||
}
|
||||
|
|
@ -693,10 +702,8 @@ void NetConst::dump_node(ostream&o, unsigned ind) const
|
|||
{
|
||||
o << setw(ind) << "" << "constant " << value_;
|
||||
o << ": " << name();
|
||||
if (rise_time())
|
||||
o << " #(" << *rise_time()
|
||||
<< "," << *fall_time()
|
||||
<< "," << *decay_time() << ")";
|
||||
if (delay_times().has_delay())
|
||||
o << " #(" << delay_times() << ")";
|
||||
else
|
||||
o << " #(.,.,.)";
|
||||
o << endl;
|
||||
|
|
@ -729,10 +736,8 @@ void NetLiteral::dump_node(ostream&o, unsigned ind) const
|
|||
{
|
||||
o << setw(ind) << "" << "constant real " << real_
|
||||
<< ": " << name();
|
||||
if (rise_time())
|
||||
o << " #(" << *rise_time()
|
||||
<< "," << *fall_time()
|
||||
<< "," << *decay_time() << ")";
|
||||
if (delay_times().has_delay())
|
||||
o << " #(" << delay_times() << ")";
|
||||
else
|
||||
o << " #(.,.,.)";
|
||||
o << endl;
|
||||
|
|
@ -810,8 +815,7 @@ void NetLogic::dump_node(ostream&o, unsigned ind) const
|
|||
o << "xor";
|
||||
break;
|
||||
}
|
||||
o << " #(" << rise_time()
|
||||
<< "," << fall_time() << "," << decay_time() << ") " << name()
|
||||
o << " #(" << delay_times() << ") " << name()
|
||||
<< " scope=" << scope_path(scope())
|
||||
<< endl;
|
||||
|
||||
|
|
@ -839,10 +843,8 @@ void NetPartSelect::dump_node(ostream&o, unsigned ind) const
|
|||
}
|
||||
o << setw(ind) << "" << "NetPartSelect(" << pt << "): "
|
||||
<< name();
|
||||
if (rise_time())
|
||||
o << " #(" << *rise_time()
|
||||
<< "," << *fall_time()
|
||||
<< "," << *decay_time() << ")";
|
||||
if (delay_times().has_delay())
|
||||
o << " #(" << delay_times() << ")";
|
||||
else
|
||||
o << " #(.,.,.)";
|
||||
o << " off=" << off_ << " wid=" << wid_ <<endl;
|
||||
|
|
@ -854,10 +856,8 @@ void NetSubstitute::dump_node(ostream&fd, unsigned ind) const
|
|||
{
|
||||
fd << setw(ind) << "" << "NetSubstitute: "
|
||||
<< name();
|
||||
if (rise_time())
|
||||
fd << " #(" << *rise_time()
|
||||
<< "," << *fall_time()
|
||||
<< "," << *decay_time() << ")";
|
||||
if (delay_times().has_delay())
|
||||
fd << " #(" << delay_times() << ")";
|
||||
else
|
||||
fd << " #(.,.,.)";
|
||||
fd << " width=" << wid_ << " base=" << off_ <<endl;
|
||||
|
|
@ -877,10 +877,8 @@ void NetReplicate::dump_node(ostream&o, unsigned ind) const
|
|||
void NetSignExtend::dump_node(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "" << "NetSignExtend: " << name();
|
||||
if (rise_time())
|
||||
o << " #(" << *rise_time()
|
||||
<< "," << *fall_time()
|
||||
<< "," << *decay_time() << ")";
|
||||
if (delay_times().has_delay())
|
||||
o << " #(" << delay_times() << ")";
|
||||
else
|
||||
o << " #(.,.,.)";
|
||||
o << " output width=" << width_ << endl;
|
||||
|
|
@ -914,8 +912,7 @@ void NetUReduce::dump_node(ostream&o, unsigned ind) const
|
|||
o << "xnor";
|
||||
break;
|
||||
}
|
||||
o << " #(" << rise_time()
|
||||
<< "," << fall_time() << "," << decay_time() << ") " << name()
|
||||
o << " #(" << delay_times() << ") " << name()
|
||||
<< " scope=" << scope_path(scope())
|
||||
<< endl;
|
||||
|
||||
|
|
@ -935,10 +932,8 @@ void NetUserFunc::dump_node(ostream&o, unsigned ind) const
|
|||
{
|
||||
o << setw(ind) << "" << "USER FUNC: "
|
||||
<< scope_path(def_);
|
||||
if (rise_time())
|
||||
o << " #(" <<*rise_time()
|
||||
<<","<<*fall_time()
|
||||
<< "," <<*decay_time() << ")";
|
||||
if (delay_times().has_delay())
|
||||
o << " #(" << delay_times() << ")";
|
||||
o << endl;
|
||||
dump_node_pins(o, ind+4);
|
||||
dump_obj_attr(o, ind+4);
|
||||
|
|
@ -986,14 +981,7 @@ void NetTran::dump_node(ostream&o, unsigned ind) const
|
|||
<< " part=" << part_width()
|
||||
<< " offset=" << part_offset();
|
||||
}
|
||||
o << " delay=(";
|
||||
if (rise_time())
|
||||
o << *rise_time() << "," << *fall_time() << ","
|
||||
<< *decay_time();
|
||||
else
|
||||
o << "0,0,0";
|
||||
|
||||
o << ")" << endl;
|
||||
o << " delay=(" << delay_times() << ")" << endl;
|
||||
dump_node_pins(o, ind+4);
|
||||
dump_obj_attr(o, ind+4);
|
||||
}
|
||||
|
|
@ -1001,8 +989,7 @@ void NetTran::dump_node(ostream&o, unsigned ind) const
|
|||
void NetUDP::dump_node(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "" << "UDP (" << udp_name() << "): ";
|
||||
o << " #(" << rise_time() << "," << fall_time() << "," << decay_time() <<
|
||||
") " << name() << endl;
|
||||
o << " #(" << delay_times() << ") " << name() << endl;
|
||||
|
||||
dump_node_pins(o, ind+4);
|
||||
dump_obj_attr(o, ind+4);
|
||||
|
|
|
|||
|
|
@ -1197,8 +1197,8 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope)
|
|||
pull = new NetLogic(scope, scope->local_symbol(),
|
||||
1, pull_type, wid);
|
||||
pull->set_line(*this);
|
||||
pull->pin(0).drive0(IVL_DR_SUPPLY);
|
||||
pull->pin(0).drive1(IVL_DR_SUPPLY);
|
||||
pull->pin(0).drive(drive_strength_t(IVL_DR_SUPPLY,
|
||||
IVL_DR_SUPPLY));
|
||||
des->add_node(pull);
|
||||
wtype = NetNet::WIRE;
|
||||
}
|
||||
|
|
|
|||
52
elaborate.cc
52
elaborate.cc
|
|
@ -115,19 +115,16 @@ void PGAssign::elaborate(Design*des, NetScope*scope) const
|
|||
{
|
||||
ivl_assert(*this, scope);
|
||||
|
||||
NetExpr* rise_time, *fall_time, *decay_time;
|
||||
eval_delays(des, scope, rise_time, fall_time, decay_time, true);
|
||||
|
||||
ivl_drive_t drive0 = strength0();
|
||||
ivl_drive_t drive1 = strength1();
|
||||
drive_strength_t drive = strength();
|
||||
delay_exprs_t delays;
|
||||
eval_delays(des, scope, delays, true);
|
||||
|
||||
ivl_assert(*this, pin(0));
|
||||
ivl_assert(*this, pin(1));
|
||||
|
||||
/* Elaborate the l-value. */
|
||||
// A continuous assignment can drive a variable if the default strength is used.
|
||||
bool var_allowed_in_sv = (drive0 == IVL_DR_STRONG &&
|
||||
drive1 == IVL_DR_STRONG) ? true : false;
|
||||
bool var_allowed_in_sv = !drive.has_drive();
|
||||
NetNet*lval = pin(0)->elaborate_lnet(des, scope, var_allowed_in_sv);
|
||||
if (lval == 0) {
|
||||
return;
|
||||
|
|
@ -136,7 +133,7 @@ void PGAssign::elaborate(Design*des, NetScope*scope) const
|
|||
// If this turns out to be an assignment to an unpacked array,
|
||||
// then handle that special case elsewhere.
|
||||
if (lval->unpacked_dimensions() > 0) {
|
||||
elaborate_unpacked_array_(des, scope, lval);
|
||||
elaborate_unpacked_array_(des, scope, lval, drive, delays);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -214,7 +211,7 @@ void PGAssign::elaborate(Design*des, NetScope*scope) const
|
|||
/* When we are given a non-default strength value and if the drive
|
||||
* source is a bit, part, indexed select or a concatenation we need
|
||||
* to add a driver (BUFZ) to convey the strength information. */
|
||||
if ((drive0 != IVL_DR_STRONG || drive1 != IVL_DR_STRONG) &&
|
||||
if (drive.has_drive() &&
|
||||
((dynamic_cast<NetESelect*>(rval_expr)) ||
|
||||
(dynamic_cast<NetEConcat*>(rval_expr)))) {
|
||||
need_driver_flag = true;
|
||||
|
|
@ -242,11 +239,11 @@ void PGAssign::elaborate(Design*des, NetScope*scope) const
|
|||
|
||||
/* Set the drive and delays for the r-val. */
|
||||
|
||||
if (drive0 != IVL_DR_STRONG || drive1 != IVL_DR_STRONG)
|
||||
rval->pin(0).drivers_drive(drive0, drive1);
|
||||
if (drive.has_drive())
|
||||
rval->pin(0).drivers_drive(drive);
|
||||
|
||||
if (rise_time || fall_time || decay_time)
|
||||
rval->pin(0).drivers_delays(rise_time, fall_time, decay_time);
|
||||
if (delays.has_delay())
|
||||
rval->pin(0).drivers_delays(delays);
|
||||
|
||||
connect(lval->pin(0), rval->pin(0));
|
||||
|
||||
|
|
@ -314,11 +311,14 @@ NetNet *elaborate_unpacked_array(Design *des, NetScope *scope, const LineInfo &l
|
|||
return expr_net;
|
||||
}
|
||||
|
||||
void PGAssign::elaborate_unpacked_array_(Design*des, NetScope*scope, NetNet*lval) const
|
||||
void PGAssign::elaborate_unpacked_array_(Design*des, NetScope*scope, NetNet*lval,
|
||||
const drive_strength_t &drive,
|
||||
const delay_exprs_t &delays) const
|
||||
{
|
||||
NetNet *rval_net = elaborate_unpacked_array(des, scope, *this, lval, pin(1));
|
||||
if (rval_net)
|
||||
assign_unpacked_with_bufz(des, scope, lval, lval, rval_net);
|
||||
assign_unpacked_with_bufz(des, scope, lval, lval, rval_net, drive,
|
||||
delays);
|
||||
}
|
||||
|
||||
void PGBuiltin::calculate_gate_and_lval_count_(unsigned&gate_count,
|
||||
|
|
@ -826,8 +826,9 @@ void PGBuiltin::elaborate(Design*des, NetScope*scope) const
|
|||
values are given, they are taken as specified. */
|
||||
|
||||
if (check_delay_count(des)) return;
|
||||
NetExpr* rise_time, *fall_time, *decay_time;
|
||||
eval_delays(des, scope, rise_time, fall_time, decay_time, true);
|
||||
delay_exprs_t delays;
|
||||
eval_delays(des, scope, delays, true);
|
||||
drive_strength_t drive = strength();
|
||||
|
||||
struct attrib_list_t*attrib_list;
|
||||
unsigned attrib_list_n = 0;
|
||||
|
|
@ -859,12 +860,8 @@ void PGBuiltin::elaborate(Design*des, NetScope*scope) const
|
|||
attrib_list[adx].val);
|
||||
|
||||
/* Set the delays and drive strength for all built in gates. */
|
||||
cur[idx]->rise_time(rise_time);
|
||||
cur[idx]->fall_time(fall_time);
|
||||
cur[idx]->decay_time(decay_time);
|
||||
|
||||
cur[idx]->pin(0).drive0(strength0());
|
||||
cur[idx]->pin(0).drive1(strength1());
|
||||
cur[idx]->delay_times(delays);
|
||||
cur[idx]->pin(0).drive(drive);
|
||||
|
||||
cur[idx]->set_line(*this);
|
||||
des->add_node(cur[idx]);
|
||||
|
|
@ -2457,7 +2454,7 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const
|
|||
|
||||
void PGModule::elaborate_udp_(Design*des, PUdp*udp, NetScope*scope) const
|
||||
{
|
||||
NetExpr*rise_expr =0, *fall_expr =0, *decay_expr =0;
|
||||
delay_exprs_t delays;
|
||||
|
||||
perm_string my_name = get_name();
|
||||
if (my_name == 0)
|
||||
|
|
@ -2474,8 +2471,7 @@ void PGModule::elaborate_udp_(Design*des, PUdp*udp, NetScope*scope) const
|
|||
} else {
|
||||
PDelays tmp_del;
|
||||
tmp_del.set_delays(overrides_, false);
|
||||
tmp_del.eval_delays(des, scope, rise_expr, fall_expr,
|
||||
decay_expr, true);
|
||||
tmp_del.eval_delays(des, scope, delays, true);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2494,9 +2490,7 @@ void PGModule::elaborate_udp_(Design*des, PUdp*udp, NetScope*scope) const
|
|||
ivl_assert(*this, udp);
|
||||
NetUDP*net = new NetUDP(scope, my_name, udp->ports.size(), udp);
|
||||
net->set_line(*this);
|
||||
net->rise_time(rise_expr);
|
||||
net->fall_time(fall_expr);
|
||||
net->decay_time(decay_expr);
|
||||
net->delay_times(delays);
|
||||
|
||||
struct attrib_list_t*attrib_list;
|
||||
unsigned attrib_list_n = 0;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,39 @@
|
|||
// Check that continuous assignments to unpacked arrays preserve drive strength.
|
||||
|
||||
module test;
|
||||
|
||||
reg failed;
|
||||
reg [8*3-1:0] s;
|
||||
|
||||
wire driven[0:1];
|
||||
wire resolved[0:1];
|
||||
|
||||
assign (weak1, weak0) driven = '{1'b1, 1'b0};
|
||||
assign resolved[0] = 1'b0;
|
||||
assign resolved[1] = 1'b1;
|
||||
assign (weak1, weak0) resolved = '{1'b1, 1'b0};
|
||||
|
||||
`define check_str(val, exp) begin \
|
||||
$swrite(s, "%v", val); \
|
||||
if (s != exp) begin \
|
||||
$display("FAILED(%0d). '%s' expected %s, got %s", `__LINE__, \
|
||||
`"val`", exp, s); \
|
||||
failed = 1'b1; \
|
||||
end \
|
||||
end
|
||||
|
||||
initial begin
|
||||
failed = 1'b0;
|
||||
|
||||
#0;
|
||||
`check_str(driven[0], "We1");
|
||||
`check_str(driven[1], "We0");
|
||||
`check_str(resolved[0], "St0");
|
||||
`check_str(resolved[1], "St1");
|
||||
|
||||
if (!failed) begin
|
||||
$display("PASSED");
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
// Check that continuous assignments to unpacked arrays preserve delay.
|
||||
|
||||
module test;
|
||||
|
||||
reg failed;
|
||||
|
||||
wire delayed[0:1];
|
||||
reg value[0:1];
|
||||
|
||||
assign #5 delayed = value;
|
||||
|
||||
`define check(val, exp) \
|
||||
if (val !== exp) begin \
|
||||
$display("FAILED(%0d). '%s' expected %b, got %b", `__LINE__, \
|
||||
`"val`", exp, val); \
|
||||
failed = 1'b1; \
|
||||
end
|
||||
|
||||
initial begin
|
||||
failed = 1'b0;
|
||||
value[0] = 1'b1;
|
||||
value[1] = 1'b0;
|
||||
|
||||
#5;
|
||||
`check(delayed[0], 1'b1)
|
||||
`check(delayed[1], 1'b0)
|
||||
|
||||
value[0] = 1'b0;
|
||||
value[1] = 1'b1;
|
||||
|
||||
#4;
|
||||
`check(delayed[0], 1'b1)
|
||||
`check(delayed[1], 1'b0)
|
||||
|
||||
#1;
|
||||
`check(delayed[0], 1'b0)
|
||||
`check(delayed[1], 1'b1)
|
||||
|
||||
if (!failed) begin
|
||||
$display("PASSED");
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
|
@ -242,6 +242,8 @@ sv_array_assign_single_fail1 vvp_tests/sv_array_assign_single_fail1.json
|
|||
sv_array_cassign6 vvp_tests/sv_array_cassign6.json
|
||||
sv_array_cassign7 vvp_tests/sv_array_cassign7.json
|
||||
sv_array_cassign8 vvp_tests/sv_array_cassign8.json
|
||||
sv_array_cassign9 vvp_tests/sv_array_cassign9.json
|
||||
sv_array_cassign10 vvp_tests/sv_array_cassign10.json
|
||||
sv_array_cassign_single vvp_tests/sv_array_cassign_single.json
|
||||
sv_array_cassign_single_fail1 vvp_tests/sv_array_cassign_single_fail1.json
|
||||
sv_automatic_2state vvp_tests/sv_automatic_2state.json
|
||||
|
|
|
|||
|
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
"type" : "normal",
|
||||
"source" : "sv_array_cassign10.v",
|
||||
"iverilog-args" : [ "-g2005-sv" ],
|
||||
"vlog95" : {
|
||||
"__comment" : "Array nets are not supported",
|
||||
"type" : "CE"
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
"type" : "normal",
|
||||
"source" : "sv_array_cassign9.v",
|
||||
"iverilog-args" : [ "-g2005-sv" ],
|
||||
"vlog95" : {
|
||||
"__comment" : "Array nets are not supported",
|
||||
"type" : "CE"
|
||||
}
|
||||
}
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2002-2025 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2002-2026 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
|
||||
|
|
@ -41,8 +41,7 @@ NetUserFunc::NetUserFunc(NetScope*s, perm_string n, NetScope*d,
|
|||
for (unsigned idx = 1 ; idx < pin_count() ; idx += 1) {
|
||||
|
||||
pin(idx).set_dir(Link::INPUT);
|
||||
pin(idx).drive0(IVL_DR_HiZ);
|
||||
pin(idx).drive1(IVL_DR_HiZ);
|
||||
pin(idx).drive(drive_strength_t::hiz);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -103,8 +102,7 @@ NetSysFunc::NetSysFunc(NetScope*s, perm_string n,
|
|||
for (unsigned idx = 1 ; idx < pin_count() ; idx += 1) {
|
||||
|
||||
pin(idx).set_dir(Link::INPUT);
|
||||
pin(idx).drive0(IVL_DR_HiZ);
|
||||
pin(idx).drive1(IVL_DR_HiZ);
|
||||
pin(idx).drive(drive_strength_t::hiz);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
28
net_link.cc
28
net_link.cc
|
|
@ -164,25 +164,26 @@ Link::DIR Link::get_dir() const
|
|||
return dir_;
|
||||
}
|
||||
|
||||
void Link::drivers_delays(const NetExpr*rise, const NetExpr*fall, const NetExpr*decay)
|
||||
void Link::drivers_delays(const delay_exprs_t &delays)
|
||||
{
|
||||
find_nexus_()->drivers_delays(rise, fall, decay);
|
||||
find_nexus_()->drivers_delays(delays);
|
||||
}
|
||||
|
||||
void Link::drivers_drive(ivl_drive_t drive0__, ivl_drive_t drive1__)
|
||||
void Link::drivers_drive(const drive_strength_t &drive)
|
||||
{
|
||||
find_nexus_()->drivers_drive(drive0__, drive1__);
|
||||
find_nexus_()->drivers_drive(drive);
|
||||
}
|
||||
|
||||
|
||||
void Link::drive0(ivl_drive_t str)
|
||||
void Link::drive(const drive_strength_t &drive)
|
||||
{
|
||||
drive0_ = str;
|
||||
drive0_ = drive.drive0;
|
||||
drive1_ = drive.drive1;
|
||||
}
|
||||
|
||||
void Link::drive1(ivl_drive_t str)
|
||||
drive_strength_t Link::drive() const
|
||||
{
|
||||
drive1_ = str;
|
||||
return drive_strength_t(drive0_, drive1_);
|
||||
}
|
||||
|
||||
ivl_drive_t Link::drive0() const
|
||||
|
|
@ -358,7 +359,7 @@ bool Nexus::drivers_present() const
|
|||
return false;
|
||||
}
|
||||
|
||||
void Nexus::drivers_delays(const NetExpr*rise, const NetExpr*fall, const NetExpr*decay)
|
||||
void Nexus::drivers_delays(const delay_exprs_t &delays)
|
||||
{
|
||||
for (Link*cur = first_nlink() ; cur ; cur = cur->next_nlink()) {
|
||||
if (cur->get_dir() != Link::OUTPUT)
|
||||
|
|
@ -368,20 +369,17 @@ void Nexus::drivers_delays(const NetExpr*rise, const NetExpr*fall, const NetExpr
|
|||
if (obj == 0)
|
||||
continue;
|
||||
|
||||
obj->rise_time(rise);
|
||||
obj->fall_time(fall);
|
||||
obj->decay_time(decay);
|
||||
obj->delay_times(delays);
|
||||
}
|
||||
}
|
||||
|
||||
void Nexus::drivers_drive(ivl_drive_t drive0, ivl_drive_t drive1)
|
||||
void Nexus::drivers_drive(const drive_strength_t &drive)
|
||||
{
|
||||
for (Link*cur = first_nlink() ; cur ; cur = cur->next_nlink()) {
|
||||
if (cur->get_dir() != Link::OUTPUT)
|
||||
continue;
|
||||
|
||||
cur->drive0(drive0);
|
||||
cur->drive1(drive1);
|
||||
cur->drive(drive);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -40,6 +40,8 @@
|
|||
|
||||
using namespace std;
|
||||
|
||||
const drive_strength_t drive_strength_t::hiz(IVL_DR_HiZ, IVL_DR_HiZ);
|
||||
|
||||
ostream& operator<< (ostream&o, NetNet::Type t)
|
||||
{
|
||||
switch (t) {
|
||||
|
|
@ -237,7 +239,7 @@ bool NetPins::is_linked(void) const
|
|||
}
|
||||
|
||||
NetObj::NetObj(NetScope*s, perm_string n, unsigned np)
|
||||
: NetPins(np), scope_(s), name_(n), delay1_(0), delay2_(0), delay3_(0)
|
||||
: NetPins(np), scope_(s), name_(n), delays_()
|
||||
{
|
||||
/* Don't
|
||||
ivl_assert(*this, np > 0);
|
||||
|
|
@ -260,6 +262,11 @@ const NetScope* NetObj::scope() const
|
|||
return scope_;
|
||||
}
|
||||
|
||||
void NetObj::delay_times(const delay_exprs_t &delays)
|
||||
{
|
||||
delays_ = delays;
|
||||
}
|
||||
|
||||
NetNode::NetNode(NetScope*s, perm_string n, unsigned npins)
|
||||
: NetObj(s, n, npins), node_next_(0), node_prev_(0), design_(0)
|
||||
{
|
||||
|
|
|
|||
66
netlist.h
66
netlist.h
|
|
@ -103,6 +103,42 @@ struct functor_t;
|
|||
# define ENUM_UNSIGNED_INT
|
||||
#endif
|
||||
|
||||
struct drive_strength_t {
|
||||
static const drive_strength_t hiz;
|
||||
|
||||
explicit drive_strength_t(ivl_drive_t d0 = IVL_DR_STRONG,
|
||||
ivl_drive_t d1 = IVL_DR_STRONG)
|
||||
: drive0(d0), drive1(d1)
|
||||
{ }
|
||||
|
||||
bool has_drive() const
|
||||
{
|
||||
return drive0 != IVL_DR_STRONG || drive1 != IVL_DR_STRONG;
|
||||
}
|
||||
|
||||
ivl_drive_t drive0;
|
||||
ivl_drive_t drive1;
|
||||
};
|
||||
|
||||
struct delay_exprs_t {
|
||||
explicit delay_exprs_t(const NetExpr *r = nullptr,
|
||||
const NetExpr *f = nullptr,
|
||||
const NetExpr *d = nullptr)
|
||||
: rise(r), fall(f), decay(d)
|
||||
{ }
|
||||
|
||||
bool has_delay() const
|
||||
{
|
||||
return rise || fall || decay;
|
||||
}
|
||||
|
||||
const NetExpr *rise;
|
||||
const NetExpr *fall;
|
||||
const NetExpr *decay;
|
||||
};
|
||||
|
||||
std::ostream &operator << (std::ostream &o, const drive_strength_t &strength);
|
||||
std::ostream &operator << (std::ostream &o, const delay_exprs_t &delays);
|
||||
std::ostream& operator << (std::ostream&o, ivl_variable_type_t val);
|
||||
|
||||
extern void join_island(NetPins*obj);
|
||||
|
|
@ -126,17 +162,17 @@ class Link {
|
|||
DIR get_dir() const;
|
||||
|
||||
// Set the delay for all the drivers to this nexus.
|
||||
void drivers_delays(const NetExpr*rise, const NetExpr*fall, const NetExpr*decay);
|
||||
void drivers_delays(const delay_exprs_t &delays);
|
||||
|
||||
// A link has a drive strength for 0 and 1 values. The drive0
|
||||
// strength is for when the link has the value 0, and drive1
|
||||
// strength is for when the link has a value 1.
|
||||
void drive0(ivl_drive_t);
|
||||
void drive1(ivl_drive_t);
|
||||
void drive(const drive_strength_t &drive);
|
||||
drive_strength_t drive() const;
|
||||
|
||||
// This sets the drives for all drivers of this link, and not
|
||||
// just the current link.
|
||||
void drivers_drive(ivl_drive_t d0, ivl_drive_t d1);
|
||||
void drivers_drive(const drive_strength_t &drive);
|
||||
|
||||
ivl_drive_t drive0() const;
|
||||
ivl_drive_t drive1() const;
|
||||
|
|
@ -269,13 +305,15 @@ class NetObj : public NetPins, public Attrib {
|
|||
perm_string name() const { return name_; }
|
||||
void rename(perm_string n) { name_ = n; }
|
||||
|
||||
const NetExpr* rise_time() const { return delay1_; }
|
||||
const NetExpr* fall_time() const { return delay2_; }
|
||||
const NetExpr* decay_time() const { return delay3_; }
|
||||
const NetExpr *rise_time() const { return delays_.rise; }
|
||||
const NetExpr *fall_time() const { return delays_.fall; }
|
||||
const NetExpr *decay_time() const { return delays_.decay; }
|
||||
delay_exprs_t delay_times() const
|
||||
{
|
||||
return delays_;
|
||||
}
|
||||
|
||||
void rise_time(const NetExpr* d) { delay1_ = d; }
|
||||
void fall_time(const NetExpr* d) { delay2_ = d; }
|
||||
void decay_time(const NetExpr* d) { delay3_ = d; }
|
||||
void delay_times(const delay_exprs_t &delays);
|
||||
|
||||
void dump_obj_attr(std::ostream&, unsigned) const;
|
||||
|
||||
|
|
@ -284,9 +322,7 @@ class NetObj : public NetPins, public Attrib {
|
|||
private:
|
||||
NetScope*scope_;
|
||||
perm_string name_;
|
||||
const NetExpr* delay1_;
|
||||
const NetExpr* delay2_;
|
||||
const NetExpr* delay3_;
|
||||
delay_exprs_t delays_;
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
@ -374,8 +410,8 @@ class Nexus {
|
|||
|
||||
const char* name() const;
|
||||
|
||||
void drivers_delays(const NetExpr*rise, const NetExpr*fall, const NetExpr*decay);
|
||||
void drivers_drive(ivl_drive_t d0, ivl_drive_t d1);
|
||||
void drivers_delays(const delay_exprs_t &delays);
|
||||
void drivers_drive(const drive_strength_t &drive);
|
||||
|
||||
Link*first_nlink();
|
||||
const Link* first_nlink()const;
|
||||
|
|
|
|||
21
netmisc.cc
21
netmisc.cc
|
|
@ -1619,6 +1619,8 @@ NetExpr*collapse_array_indices(Design*des, NetScope*scope, const NetNet*net,
|
|||
static void assign_unpacked_with_bufz_dim(Design *des, NetScope *scope,
|
||||
const LineInfo *loc,
|
||||
NetNet *lval, NetNet *rval,
|
||||
const drive_strength_t &drive,
|
||||
const delay_exprs_t &delays,
|
||||
const std::vector<long> &stride,
|
||||
unsigned int dim = 0,
|
||||
unsigned int idx_l = 0,
|
||||
|
|
@ -1661,11 +1663,19 @@ static void assign_unpacked_with_bufz_dim(Design *des, NetScope *scope,
|
|||
driver->set_line(*loc);
|
||||
des->add_node(driver);
|
||||
|
||||
connect(lval->pin(idx_l), driver->pin(0));
|
||||
connect(driver->pin(1), rval->pin(idx_r));
|
||||
|
||||
if (drive.has_drive())
|
||||
driver->pin(0).drive(drive);
|
||||
|
||||
if (delays.has_delay())
|
||||
driver->delay_times(delays);
|
||||
|
||||
connect(lval->pin(idx_l), driver->pin(0));
|
||||
} else {
|
||||
assign_unpacked_with_bufz_dim(des, scope, loc, lval, rval,
|
||||
stride, dim + 1, idx_l, idx_r);
|
||||
drive, delays, stride,
|
||||
dim + 1, idx_l, idx_r);
|
||||
}
|
||||
|
||||
idx_l += inc_l;
|
||||
|
|
@ -1675,7 +1685,9 @@ static void assign_unpacked_with_bufz_dim(Design *des, NetScope *scope,
|
|||
|
||||
void assign_unpacked_with_bufz(Design*des, NetScope*scope,
|
||||
const LineInfo*loc,
|
||||
NetNet*lval, NetNet*rval)
|
||||
NetNet*lval, NetNet*rval,
|
||||
const drive_strength_t &drive,
|
||||
const delay_exprs_t &delays)
|
||||
{
|
||||
ivl_assert(*loc, lval->pin_count()==rval->pin_count());
|
||||
|
||||
|
|
@ -1683,7 +1695,8 @@ void assign_unpacked_with_bufz(Design*des, NetScope*scope,
|
|||
vector<long> stride(dims.size());
|
||||
|
||||
make_strides(dims, stride);
|
||||
assign_unpacked_with_bufz_dim(des, scope, loc, lval, rval, stride);
|
||||
assign_unpacked_with_bufz_dim(des, scope, loc, lval, rval, drive,
|
||||
delays, stride);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -492,7 +492,11 @@ extern NetExpr*collapse_array_exprs(Design*des, NetScope*scope,
|
|||
|
||||
extern void assign_unpacked_with_bufz(Design*des, NetScope*scope,
|
||||
const LineInfo*loc,
|
||||
NetNet*lval, NetNet*rval);
|
||||
NetNet*lval, NetNet*rval,
|
||||
const drive_strength_t &drive =
|
||||
drive_strength_t(),
|
||||
const delay_exprs_t &delays =
|
||||
delay_exprs_t());
|
||||
|
||||
extern NetPartSelect* detect_partselect_lval(Link&pin);
|
||||
|
||||
|
|
|
|||
6
pform.cc
6
pform.cc
|
|
@ -2260,8 +2260,7 @@ static void pform_makegate(PGBuiltin::Type type,
|
|||
// pform_bind_attributes function to keep the attr object.
|
||||
pform_bind_attributes(cur->attributes, attr, true);
|
||||
|
||||
cur->strength0(str.str0);
|
||||
cur->strength1(str.str1);
|
||||
cur->strength(drive_strength_t(str.str0, str.str1));
|
||||
cur->set_line(info);
|
||||
|
||||
if (pform_cur_generate) {
|
||||
|
|
@ -2483,8 +2482,7 @@ static PGAssign* pform_make_pgassign(PExpr*lval, PExpr*rval,
|
|||
else
|
||||
cur = new PGAssign(wires, del);
|
||||
|
||||
cur->strength0(str.str0);
|
||||
cur->strength1(str.str1);
|
||||
cur->strength(drive_strength_t(str.str0, str.str1));
|
||||
|
||||
if (pform_cur_generate)
|
||||
pform_cur_generate->add_gate(cur);
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 1998-2025 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 1998-2026 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
|
||||
|
|
@ -741,7 +741,7 @@ void PGate::dump(ostream&out, unsigned ind) const
|
|||
void PGAssign::dump(ostream&out, unsigned ind) const
|
||||
{
|
||||
out << setw(ind) << "";
|
||||
out << "assign (" << strength0() << "0 " << strength1() << "1) ";
|
||||
out << "assign (" << strength() << ") ";
|
||||
dump_delays(out);
|
||||
out << " " << *pin(0) << " = " << *pin(1) << ";" << endl;
|
||||
}
|
||||
|
|
@ -787,7 +787,7 @@ void PGBuiltin::dump(ostream&out, unsigned ind) const
|
|||
out << "builtin gate ";
|
||||
}
|
||||
|
||||
out << "(" << strength0() << "0 " << strength1() << "1) ";
|
||||
out << "(" << strength() << ") ";
|
||||
dump_delays(out);
|
||||
out << " " << get_name();
|
||||
dump_ranges(out);
|
||||
|
|
|
|||
Loading…
Reference in New Issue