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:
parent
96deee1360
commit
f42923d896
1 changed files with 45 additions and 0 deletions
|
|
@ -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;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue