Preserve delay and strength in unpacked array continuous assignments

Continuous assignments to unpacked arrays are expanded into per-element
BUFZ drivers. Currently this path drops the delay and drive strength from
the original continuous assignment, so `assign #5 a = b` updates the array
immediately and `assign (weak1, weak0) a = b` drives with the default
strength.

Pass the evaluated delay and strength values through the unpacked array
assignment helper and apply them to each generated element driver.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
This commit is contained in:
Lars-Peter Clausen 2026-05-17 12:56:09 -07:00
parent 85c58d0a7a
commit ab6a0e0799
4 changed files with 32 additions and 9 deletions

View File

@ -32,6 +32,7 @@ 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
@ -129,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;
};

View File

@ -133,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;
}
@ -311,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,

View File

@ -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);
}
/*

View File

@ -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);