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

[FIRRTL] Return multiple results from memories, Lower Memories in LowerTypes #488

Merged
merged 8 commits into from
Jan 29, 2021

Conversation

seldridge
Copy link
Member

@seldridge seldridge commented Jan 19, 2021

Fixes #479, #478.

Return one result per port for a FIRRTL memory instead of a single
bundle.

Lowers memories during FIRRTL type lowering.

Status

This is still work-in-progress and there's a lot of cargo culting from ded5bd2 and 938ad62. This also has some very ugly code in LowerTypes that I'll cleanup before promoting to non-draft.

Copy link
Collaborator

@lattner lattner left a comment

Choose a reason for hiding this comment

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

Nice. I'm really happy you tackled this, thank you. I just did a quick scan and this is going in the right direction, lemme know when you want a detailed review thx!

lib/Conversion/HandshakeToFIRRTL/HandshakeToFIRRTL.cpp Outdated Show resolved Hide resolved
lib/Dialect/FIRRTL/FIRRTLDialect.cpp Outdated Show resolved Hide resolved
lib/Dialect/FIRRTL/FIRRTLOps.cpp Outdated Show resolved Hide resolved
@seldridge seldridge force-pushed the dev/seldridge/issue-479 branch from 315d006 to a033113 Compare January 24, 2021 20:04
@seldridge seldridge changed the title [FIRRTL] Return multiple results from memories [FIRRTL] Return multiple results from memories, Lower Memories in LowerTypes Jan 24, 2021
@seldridge seldridge force-pushed the dev/seldridge/issue-479 branch from b684847 to 37ad6bf Compare January 24, 2021 23:04
@seldridge
Copy link
Member Author

Note that this is not ready for review yet. The memory type lowering is very ugly right now and should be cleaned up before anybody looks at it.

That said, the output here is looking pretty good through the FIRRTL type lowering path.

Compiling with:

firtool -lower-to-rtl -enable-lower-types -verilog Bar.fir 
Input FIRRTL IR
circuit Bar :
  module Bar :
    input clock: Clock
    input rAddr: UInt<4>
    input rEn: UInt<1>
    output rData: {a: UInt<8>, b: UInt<8>}
    input wAddr: UInt<4>
    input wEn: UInt<1>
    input wMask: {a: UInt<1>, b: UInt<1>}
    input wData: {a: UInt<8>, b: UInt<8>}

    mem memory:
      data-type => {a: UInt<8>, b: UInt<8>}
      depth => 16
      reader => r
      writer => w
      read-latency => 0
      write-latency => 1
      read-under-write => undefined

    memory.r.clk <= clock
    memory.r.en <= rEn
    memory.r.addr <= rAddr
    rData <= memory.r.data

    memory.w.clk <= clock
    memory.w.en <= wEn
    memory.w.addr <= wAddr
    memory.w.mask <= wMask
    memory.w.data <= wData
Output Veriog
module Bar(
  input        clock,
  input  [3:0] rAddr,
  input        rEn,
  input  [3:0] wAddr,
  input        wEn, wMask_a, wMask_b,
  input  [7:0] wData_a, wData_b,
  output [7:0] rData_a, rData_b);

  reg  [7:0] memory_a[15:0];	// Bar.fir:12:5
  wire [3:0] memory_a_r_addr;	// Bar.fir:12:5
  wire [7:0] memory_a_r_data;	// Bar.fir:12:5
  wire [3:0] memory_a_w_addr;	// Bar.fir:12:5
  wire       memory_a_w_en;	// Bar.fir:12:5
  wire       memory_a_w_clk;	// Bar.fir:12:5
  wire [7:0] memory_a_w_data;	// Bar.fir:12:5
  wire       memory_a_w_mask;	// Bar.fir:12:5
  wire [3:0] memory_r_addr;	// Bar.fir:12:5
  wire [3:0] memory_w_addr;	// Bar.fir:12:5
  wire       memory_w_en;	// Bar.fir:12:5
  wire       memory_w_clk;	// Bar.fir:12:5
  reg  [7:0] memory_b[15:0];	// Bar.fir:12:5
  wire [3:0] memory_b_r_addr;	// Bar.fir:12:5
  wire [7:0] memory_b_r_data;	// Bar.fir:12:5
  wire [3:0] memory_b_w_addr;	// Bar.fir:12:5
  wire       memory_b_w_en;	// Bar.fir:12:5
  wire       memory_b_w_clk;	// Bar.fir:12:5
  wire [7:0] memory_b_w_data;	// Bar.fir:12:5
  wire       memory_b_w_mask;	// Bar.fir:12:5

  `ifndef SYNTHESIS	// Bar.fir:12:5
    initial begin	// Bar.fir:12:5
      `INIT_RANDOM_PROLOG_	// Bar.fir:12:5
      `ifdef RANDOMIZE_MEM_INIT	// Bar.fir:12:5
        integer memory_a_initvar;
        for (memory_a_initvar = 0; memory_a_initvar < 16; memory_a_initvar = memory_a_initvar+1)
          memory_a[memory_a_initvar] = `RANDOM;	// Bar.fir:12:5
      `endif
    end // initial
  `endif
  assign memory_a_r_data = memory_a[memory_a_r_addr];	// Bar.fir:12:5
  always @(posedge memory_a_w_clk) begin	// Bar.fir:12:5
    if (memory_a_w_en & memory_a_w_mask) begin	// Bar.fir:12:5
      memory_a[memory_a_w_addr] = memory_a_w_data;	// Bar.fir:12:5
    end
  end // always @(posedge)
  wire [3:0] _T = memory_r_addr;	// Bar.fir:12:5
  assign memory_a_r_addr = _T;	// Bar.fir:12:5
  wire [3:0] _T_0 = memory_w_addr;	// Bar.fir:12:5
  assign memory_a_w_addr = _T_0;	// Bar.fir:12:5
  wire _T_1 = memory_w_en;	// Bar.fir:12:5
  assign memory_a_w_en = _T_1;	// Bar.fir:12:5
  wire _T_2 = memory_w_clk;	// Bar.fir:12:5
  assign memory_a_w_clk = _T_2;	// Bar.fir:12:5
  `ifndef SYNTHESIS	// Bar.fir:12:5
    initial begin	// Bar.fir:12:5
      `ifdef RANDOMIZE_MEM_INIT	// Bar.fir:12:5
        integer memory_b_initvar;
        for (memory_b_initvar = 0; memory_b_initvar < 16; memory_b_initvar = memory_b_initvar+1)
          memory_b[memory_b_initvar] = `RANDOM;	// Bar.fir:12:5
      `endif
    end // initial
  `endif
  assign memory_b_r_data = memory_b[memory_b_r_addr];	// Bar.fir:12:5
  always @(posedge memory_b_w_clk) begin	// Bar.fir:12:5
    if (memory_b_w_en & memory_b_w_mask) begin	// Bar.fir:12:5
      memory_b[memory_b_w_addr] = memory_b_w_data;	// Bar.fir:12:5
    end
  end // always @(posedge)
  assign memory_b_r_addr = _T;	// Bar.fir:12:5
  assign memory_b_w_addr = _T_0;	// Bar.fir:12:5
  assign memory_b_w_en = _T_1;	// Bar.fir:12:5
  assign memory_b_w_clk = _T_2;	// Bar.fir:12:5
  assign memory_r_addr = rAddr;	// Bar.fir:23:19
  assign memory_w_clk = clock;	// Bar.fir:26:18
  assign memory_w_en = wEn;	// Bar.fir:27:17
  assign memory_w_addr = wAddr;	// Bar.fir:28:19
  assign memory_a_w_mask = wMask_a;	// Bar.fir:29:19
  assign memory_b_w_mask = wMask_b;	// Bar.fir:29:19
  assign memory_a_w_data = wData_a;	// Bar.fir:30:19
  assign memory_b_w_data = wData_b;	// Bar.fir:30:19
  assign rData_a = memory_a_r_data;	// Bar.fir:2:3
  assign rData_b = memory_b_r_data;	// Bar.fir:2:3
endmodule

lib/Conversion/FIRRTLToRTL/LowerToRTL.cpp Outdated Show resolved Hide resolved
lib/Conversion/FIRRTLToRTL/LowerToRTL.cpp Outdated Show resolved Hide resolved
lib/Conversion/FIRRTLToRTL/LowerToRTL.cpp Show resolved Hide resolved
lib/Conversion/HandshakeToFIRRTL/HandshakeToFIRRTL.cpp Outdated Show resolved Hide resolved
lib/Dialect/FIRRTL/Import/FIRParser.cpp Outdated Show resolved Hide resolved
lib/Dialect/FIRRTL/Transforms/LowerTypes.cpp Outdated Show resolved Hide resolved
lib/Dialect/FIRRTL/Transforms/LowerTypes.cpp Outdated Show resolved Hide resolved
@seldridge seldridge force-pushed the dev/seldridge/issue-479 branch 4 times, most recently from e988b86 to 64696b5 Compare January 26, 2021 03:41
@seldridge seldridge marked this pull request as ready for review January 26, 2021 03:52
@seldridge
Copy link
Member Author

This is good for a review.

@seldridge seldridge force-pushed the dev/seldridge/issue-479 branch from 64696b5 to 621e2f6 Compare January 26, 2021 05:03
Copy link
Contributor

@mikeurbach mikeurbach left a comment

Choose a reason for hiding this comment

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

I reviewed each commit here separately. In general, I think the logic and test cases are correct.

I think the first commit is ready to land as-is.

I had some concerns about the style in the second commit, but I'm not an authority on LLVM/C++ style.

lib/Conversion/HandshakeToFIRRTL/HandshakeToFIRRTL.cpp Outdated Show resolved Hide resolved
lib/Conversion/HandshakeToFIRRTL/HandshakeToFIRRTL.cpp Outdated Show resolved Hide resolved
lib/Dialect/FIRRTL/FIRRTLOps.cpp Outdated Show resolved Hide resolved
lib/Translation/ExportVerilog/ExportVerilogFIRRTL.cpp Outdated Show resolved Hide resolved
lib/Translation/ExportVerilog/ExportVerilogFIRRTL.cpp Outdated Show resolved Hide resolved
test/Dialect/FIRRTL/lower-types.mlir Outdated Show resolved Hide resolved
lib/Dialect/FIRRTL/Transforms/LowerTypes.cpp Show resolved Hide resolved
lib/Dialect/FIRRTL/Transforms/LowerTypes.cpp Outdated Show resolved Hide resolved
lib/Dialect/FIRRTL/Transforms/LowerTypes.cpp Outdated Show resolved Hide resolved
lib/Dialect/FIRRTL/Transforms/LowerTypes.cpp Outdated Show resolved Hide resolved
@seldridge
Copy link
Member Author

Annoyingly, the first commit, applied by itself, will cause LowerTypes to start crashing. If the second commit is problematic, I can patch the first so that it can land (and unblock #493).

My only big concern with the second commit is the duplicate walking of the both the old memory and the new memory. I can think of a way to simplify that or can modify that in a follow-up commit.

@seldridge seldridge force-pushed the dev/seldridge/issue-479 branch from 8f79b93 to efb66db Compare January 27, 2021 20:35
@seldridge seldridge force-pushed the dev/seldridge/issue-479 branch from efb66db to 1fb4086 Compare January 27, 2021 21:36
Comment on lines 329 to 331
Type theType = elt.type;
if (flipped)
theType = FlipType::get(elt.type);
Copy link
Member

@youngar youngar Jan 27, 2021

Choose a reason for hiding this comment

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

I was using (the slower) SubfieldOp::getResultType(op.getResult(i), field.name, op.getLoc()) to get this done. I'm not totally sure what I'm doing. Maybe we should factor this out into a helper that can get the field type by index (it could work for vectors?)?

@seldridge
Copy link
Member Author

@lattner: Can you take a look at this when you get a chance?

Copy link
Collaborator

@lattner lattner left a comment

Choose a reason for hiding this comment

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

Looks great!

lib/Conversion/FIRRTLToRTL/LowerToRTL.cpp Show resolved Hide resolved
lib/Conversion/HandshakeToFIRRTL/HandshakeToFIRRTL.cpp Outdated Show resolved Hide resolved
@seldridge seldridge force-pushed the dev/seldridge/issue-479 branch 2 times, most recently from ff70949 to 796402c Compare January 28, 2021 22:35
seldridge referenced this pull request Jan 28, 2021
BundleType::get doesn't always return a bundle type (due to nested
flips) but we know that getTypeForPortList does.  Put the cast in its
implementation to avoid casts in the clients.
@seldridge seldridge force-pushed the dev/seldridge/issue-479 branch 4 times, most recently from 947d32a to 6e7ac6a Compare January 29, 2021 04:25
Signed-off-by: Schuyler Eldridge <[email protected]>
Change FIRRTL Dialect's MemOp to return one result per port as opposed
to a single result bundle containing each port as a subelement.

Fix bug where a memory with a read/write port would erroneously return
null from getDataTypeOrNull. This will now use either "data" or
"rdata" to look up the field that has the data type of the memory
based on the kind of the first memory port.

Signed-off-by: Schuyler Eldridge <[email protected]>
@seldridge seldridge force-pushed the dev/seldridge/issue-479 branch from 6e7ac6a to f071665 Compare January 29, 2021 05:16
@mikeurbach
Copy link
Contributor

@seldridge Just an FYI, I checked out this branch and tried lowering a pretty complex piece of FIRRTL from Handshake using the changes in LowerTypes. It works great! I am not promising it is logically correct, but it unblocks the lowering all the way to (System) Verilog, as expected from the discussion here: #337 (comment).

This example program was complex enough to reveal another issue in LowerTypes, which I'm logging, reducing a test case for, and will have a PR for today: #534. I am only touching the visitor for connects, so I don't forsee any conflicts with what you're doing here.

@seldridge seldridge merged commit 527bc99 into main Jan 29, 2021
seldridge added a commit that referenced this pull request Jan 29, 2021
@seldridge
Copy link
Member Author

Slight issue with this and f736bc5. I'm looking into it now...

@lattner
Copy link
Collaborator

lattner commented Jan 30, 2021

Ok thanks. when this lands again, plz update the FIRRTL rationale to mention this as well, thanks!

seldridge added a commit that referenced this pull request Jan 30, 2021
…erTypes (#488)

Re-application of the #488 PR.

Signed-off-by: Schuyler Eldridge <[email protected]>
seldridge added a commit that referenced this pull request Jan 30, 2021
Re-application of the #488 PR.

Revert to old behavior in LowerToRTL where unused memory ports would
not be lowered. This allowed for some janky test cases that had
aggregate ports (which LowerToRTL has no idea what to do with) to be
"lowered" since their ports were never connected to.

Signed-off-by: Schuyler Eldridge <[email protected]>
@seldridge seldridge deleted the dev/seldridge/issue-479 branch January 30, 2021 21:20
@drom drom added this to the SiFive-1 milestone Mar 23, 2021
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.

[FIRRTL] Memories Should Return Multiple Results
6 participants