diff --git a/PDelays.cc b/PDelays.cc index 20645434a..97e1d577b 100644 --- a/PDelays.cc +++ b/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(rise); - const NetEConst *c_fall = dynamic_cast(fall); + const NetEConst *c_rise = dynamic_cast(rise); + const NetEConst *c_fall = dynamic_cast(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; } } diff --git a/PDelays.h b/PDelays.h index 30709070d..87a727e57 100644 --- a/PDelays.h +++ b/PDelays.h @@ -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; diff --git a/PGate.cc b/PGate.cc index 6da02060e..944d4e2dd 100644 --- a/PGate.cc +++ b/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*pins) } PGate::PGate(perm_string name, list*pins, const list*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*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*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*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 diff --git a/PGate.h b/PGate.h index 88e0d8c57..0c832ddd1 100644 --- a/PGate.h +++ b/PGate.h @@ -31,6 +31,7 @@ class PExpr; class PUdp; class Module; +struct delay_exprs_t; /* * A PGate represents a Verilog gate. The gate has a name and other @@ -66,10 +67,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 +75,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 attributes; @@ -109,7 +105,7 @@ class PGate : public PNamedItem { std::list*ranges_; - ivl_drive_t str0_, str1_; + drive_strength_t strength_; void set_pins_(std::list*pins); diff --git a/cprop.cc b/cprop.cc index 9e7864b09..804fa4e91 100644 --- a/cprop.cc +++ b/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) diff --git a/design_dump.cc b/design_dump.cc index c1e74325d..fe5d9edf3 100644 --- a/design_dump.cc +++ b/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_ <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; } diff --git a/elaborate.cc b/elaborate.cc index c78723000..ff448cc95 100644 --- a/elaborate.cc +++ b/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; @@ -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(rval_expr)) || (dynamic_cast(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)); @@ -826,8 +823,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 +857,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 +2451,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 +2468,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 +2487,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; diff --git a/net_func.cc b/net_func.cc index 1bd714aa4..755be3ec8 100644 --- a/net_func.cc +++ b/net_func.cc @@ -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); } } diff --git a/net_link.cc b/net_link.cc index 039428ae9..4ef426e48 100644 --- a/net_link.cc +++ b/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); } } diff --git a/netlist.cc b/netlist.cc index b26c508ec..79b5f6cfb 100644 --- a/netlist.cc +++ b/netlist.cc @@ -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) { diff --git a/netlist.h b/netlist.h index a3880604b..812372ff5 100644 --- a/netlist.h +++ b/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; diff --git a/pform.cc b/pform.cc index d7c476532..e66d5dce8 100644 --- a/pform.cc +++ b/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); diff --git a/pform_dump.cc b/pform_dump.cc index 6dc130687..94913eca6 100644 --- a/pform_dump.cc +++ b/pform_dump.cc @@ -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);