Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

dfflibmap: enable inference #4698

Merged
merged 2 commits into from
Nov 13, 2024
Merged

dfflibmap: enable inference #4698

merged 2 commits into from
Nov 13, 2024

Conversation

Ravenslofty
Copy link
Collaborator

@Ravenslofty Ravenslofty commented Nov 3, 2024

What are the reasons/motivation for this change?
dfflibmap can't map flops with enables, so yosys has to use muxes. By using flops that have enables, we can save area and possibly delay.

Explain how this is achieved.
The next_state attribute of the ff block needs to be evaluated to see if it's an enable expression. This means a bunch of infrastructure related to parsing liberty expressions.

If applicable, please suggest to reviewers how they can test the change.
Run dfflibmap -liberty foo.lib on various liberty files you can find, and see if they a) parse without crashing and b) successfully detect the enable flops in the file.

Still to do:

  • a bunch of log_warnings are commented out because they are extremely noisy.
    • sky130 has some scan chain flops with the expression (D&DE&!SCE)|(IQ&!DE&!SCE)|(SCD&SCE), which the parser chokes on because of three ands instead of two - to investigate and fix. (to be clear, this won't infer, but it shouldn't issue the nonsense warning of "Inference failed on expression '(D&DE&!SCE)|(IQ&!DE&!SCE)|(SCD&SCE)' in next_state attribute of cell 'sky130_fd_sc_hd__sedfxtp_4' because it does not contain ff output 'IQ' - skipping." when it does. continue in a do/while loop did not do what I thought it did.
    • more generally, because the code loops through all cells to find each cell type, this results in a lot of duplicate warnings. there's now a lookup to avoid duplicate warnings.
  • flops with enable and reset - the infrastructure is there, I just don't know of any test cases to check they work, since sky130 just has edfxtp/edfxbp.

@QuantamHD
Copy link
Contributor

It would also be okay to skip scan flops. DFT is implemented in OpenROAD, and will replace flops with their scan equivalents.

Copy link
Member

@povik povik left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some drive-by comments from a first read

passes/techmap/dfflibmap.cc Outdated Show resolved Hide resolved
passes/techmap/dfflibmap.cc Outdated Show resolved Hide resolved
passes/techmap/dfflibmap.cc Outdated Show resolved Hide resolved
passes/techmap/dfflibmap.cc Outdated Show resolved Hide resolved
@Ravenslofty Ravenslofty force-pushed the lofty/dfflibmap-enable branch from 1a5face to 430e626 Compare November 4, 2024 13:19
@Ravenslofty Ravenslofty marked this pull request as ready for review November 7, 2024 00:52
@widlarizer
Copy link
Collaborator

widlarizer commented Nov 8, 2024

Should we also extend techlibs/common/cells.lib with DFFE.* to make default synth represent realistic flows better now that we have this capability?

@povik
Copy link
Member

povik commented Nov 8, 2024

Should we also extend techlibs/common/cells.lib with DFFE.* to make default synth represent realistic flows better now that we have this capability?

I don't think cells.lib has anything to do with synth

@widlarizer
Copy link
Collaborator

Well, seeing that cells.lib isn't referenced anywhere in the codebase, that certainly raises the question: what does cells.lib have to do with anything? But that's not relevant for this PR specifically.

@KrystalDelusion
Copy link
Member

KrystalDelusion commented Nov 8, 2024

cells.lib provides synthesis models used for simulation (and possibly formal verification?) I'm thinking of simcells.v and simlib.v, though I suspect cells.lib is similar for liberty (albeit with far fewer cells)


if (!parse_pin(cell, ff->find("clocked_on"), cell_clk_pin, cell_clk_pol) || cell_clk_pol != clkpol)
continue;
if (!parse_pin(cell, ff->find("next_state"), cell_next_pin, cell_next_pol))
if (!parse_next_state(cell, ff->find("next_state"), cell_next_pin, cell_next_pol, cell_enable_pin, cell_enable_pol))
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm guessing the enapol check is missing here

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

well, yes, but also: none of the cells passed to find_cell_sr are DFFSREs, so the enable polarity doesn't actually matter. I couldn't find a PDK which has a DFFSRE, but I wanted to leave the infrastructure in to make it easy to add.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In that case I think we should log_assert(!has_enable && "Unimplemented"); even if we are guaranteed not to hit it due to the user code

@widlarizer
Copy link
Collaborator

The build failure should be possible to resolve with a rebase BTW

Copy link
Collaborator

@widlarizer widlarizer left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • fix the enapol parameter
  • fix CI

Functionally seems like a valid approach

@Ravenslofty Ravenslofty force-pushed the lofty/dfflibmap-enable branch from 6ce0c5f to 4f40187 Compare November 13, 2024 16:07
@Ravenslofty
Copy link
Collaborator Author

rebased, with log_assert in find_cell_sr when enapol is true.

@Ravenslofty Ravenslofty merged commit d9ef388 into main Nov 13, 2024
44 checks passed
@Ravenslofty Ravenslofty deleted the lofty/dfflibmap-enable branch November 13, 2024 17:50
@widlarizer
Copy link
Collaborator

widlarizer commented Nov 20, 2024

Unfortunately, when used in ORFS, turns out this feature regresses area usage on ibex on sky130. When dfflibmap matches a $dffe of the opposite enable polarity, it emits an $_NOT_ and the PDK flop with enable. In ORFS, dfflibmap is ran before abc. When the mux is hidden in the PDK dffe cell, abc can't (in effect) make use of ITE(!a, x, y) = ITE(a, y, x) to eliminate the inverter by swapping the mux inputs, unlike when it emitted a regular flop and multiplexer.

Repro:

module foo(
    input se,
    input clk,
    input xi,
    input [8:0] a,
    input [8:0] b,
    output xo,
);
  // To test with more logic around,
  // uncomment and replace se with mod:

  // wire mod;
  // assign mod = ((a + b) % 7) == 3;

  initial begin
    xo = 0;
  end

  always @(posedge clk)
  begin
    if (se)
        xo <= xi;
  end
endmodule
read_verilog dff_regr.v
proc
opt
techmap
opt
stat
dfflibmap -liberty sky130_fd_sc_hd__tt_025C_1v80.lib
stat
abc -liberty sky130_fd_sc_hd__tt_025C_1v80.lib
stat -liberty sky130_fd_sc_hd__tt_025C_1v80.lib

I think we have work to do in dfflegalize to prevent this (maybe configurably)

@Ravenslofty
Copy link
Collaborator Author

I'm...not sure that's a valid transformation when the enable mux is baked into the flop?

But I can see that it can be an issue if the polarity doesn't exactly match. Hmm.

@widlarizer
Copy link
Collaborator

Yeah the idea is we probably should prevent baking the muxes into dffe PDK cells if it creates an inverter outside the PDK cell

@widlarizer
Copy link
Collaborator

I'm not so sure about this anymore. The regression doesn't reproduce on commits of this PR branch, because it's based on an older main commit. Hilariously, when qwp was removed, a constid was removed too, which made the ibex synthesize better, but not when DFFEs are inferred. Apparently, the 1% regression we saw is indistinguishable from hash perturbations. Can't wait to have --hash-seed available on main so we can chase fewer ghosts

@povik
Copy link
Member

povik commented Nov 23, 2024

On nangate45:

12. Executing DFFLIBMAP pass (mapping DFF cells to sequential cells from liberty file).
Warning: Inference failed on expression '((SE*SI)+(D*!SE))' in next_state attribute of cell 'SDFFRS_X1' because it does not contain ff output 'IQ' - skipping.
Warning: Inference failed on expression '((SE*SI)+(D*!SE))' in next_state attribute of cell 'SDFFRS_X2' because it does not contain ff output 'IQ' - skipping.
Warning: Inference failed on expression '((SE*SI)+(D*!SE))' in next_state attribute of cell 'SDFFR_X1' because it does not contain ff output 'IQ' - skipping.
Warning: Inference failed on expression '((SE*SI)+(D*!SE))' in next_state attribute of cell 'SDFFR_X2' because it does not contain ff output 'IQ' - skipping.
Warning: Inference failed on expression '((SE*SI)+(D*!SE))' in next_state attribute of cell 'SDFFS_X1' because it does not contain ff output 'IQ' - skipping.
Warning: Inference failed on expression '((SE*SI)+(D*!SE))' in next_state attribute of cell 'SDFFS_X2' because it does not contain ff output 'IQ' - skipping.
Warning: Inference failed on expression '((SE*SI)+(D*!SE))' in next_state attribute of cell 'SDFF_X1' because it does not contain ff output 'IQ' - skipping.
Warning: Inference failed on expression '((SE*SI)+(D*!SE))' in next_state attribute of cell 'SDFF_X2' because it does not contain ff output 'IQ' - skipping.

I think we need to demote those to log_debug

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants