3
0
Fork 0
mirror of https://github.com/YosysHQ/yosys synced 2026-08-08 23:21:20 +00:00

mul2dsp: declare $__mul and $__soft_mul so their ports have directions

Neither is a cell anything implements. They exist so a mapping rule can
re-emit a multiplier without matching itself, and a later techmap or
`chtype` consumes them. Nothing ever declared them, so
`Cell::port_dir()` fell through to PD_UNKNOWN for every port, and
anything that has to tell a cell's inputs from its outputs had to guess.

signorm guesses "output": setup_driven_wires() skips only PD_INPUT, so
\A and \B of a $__mul are read as drivers. \B is the enclosing module's
own input, already driven by its $input_port cell, and \A is a slice, so
both take the fallback -- interpose a helper wire and connect it -- and
both sides then look driven, which is what a $connect means. _80_mul's
wide branch has two $__mul instances, and it runs `proc; clean` through
_TECHMAP_DO_, whose closing opt_expr normalizes the map design. Result:
four helper wires and four $connect cells manufactured out of a design
that has no multi-driver net in it anywhere.

Declaring them as blackboxes gives the interface a definition without
making them mappable: techmap skips blackbox templates outright
(`tpl->get_blackbox_attribute(ignore_wb)`), and every rule that emits
these types carries an explicit techmap_celltype, so nothing was relying
on matching them by module name.

96deee136 stopped the $connect cells escaping the index, which is right
regardless; this stops them being created. `make -C tests` is unchanged
at 7 failures.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MQU5XCqDYY8MbivGkNRrDo
This commit is contained in:
Emil J. Tywoniak 2026-07-21 17:45:02 +02:00
parent 96deee1360
commit f42923d896

View file

@ -49,6 +49,51 @@ $fatal(1, "Macro DSP_NAME must be defined");
`define MAX(a,b) (a > b ? a : b)
`define MIN(a,b) (a < b ? a : b)
// $__mul and $__soft_mul are not cells anything implements: the rules below
// re-emit a multiplier as one of them so that the match does not recurse into
// itself, and a later techmap or `chtype` consumes them. Nothing declared them,
// so port_dir() answered PD_UNKNOWN for their ports, and anything that has to
// tell a cell's inputs from its outputs then has to guess -- the signorm index
// guesses "output", reads A and B as drivers, and manufactures a multi-driver
// conflict on every net feeding one. Give the interface a definition instead.
//
// The blackbox attribute is what keeps techmap from taking these as mapping
// templates: it skips blackbox templates outright, so they stay pure
// declarations. Every rule that produces them carries an explicit
// techmap_celltype, so nothing depends on matching by module name here.
(* blackbox *)
module \$__mul (A, B, Y);
parameter A_SIGNED = 0;
parameter B_SIGNED = 0;
parameter A_WIDTH = 1;
parameter B_WIDTH = 1;
parameter Y_WIDTH = 1;
(* force_downto *)
input [A_WIDTH-1:0] A;
(* force_downto *)
input [B_WIDTH-1:0] B;
(* force_downto *)
output [Y_WIDTH-1:0] Y;
endmodule
(* blackbox *)
module \$__soft_mul (A, B, Y);
parameter A_SIGNED = 0;
parameter B_SIGNED = 0;
parameter A_WIDTH = 1;
parameter B_WIDTH = 1;
parameter Y_WIDTH = 1;
(* force_downto *)
input [A_WIDTH-1:0] A;
(* force_downto *)
input [B_WIDTH-1:0] B;
(* force_downto *)
output [Y_WIDTH-1:0] Y;
endmodule
(* techmap_celltype = "$mul $__mul" *)
module _80_mul (A, B, Y);
parameter A_SIGNED = 0;