GithubHelp home page GithubHelp logo

churchroad's Introduction

Churchroad

:letsgo3:

Yosys Plugin

./yosys-plugin/

We provide a Yosys plugin, which can output Churchroad IR from Yosys. Please see the README in that directory for information on building and using the plugin.

churchroad's People

Contributors

bkushigian avatar dcao avatar gussmith23 avatar kscharan avatar ninehusky avatar sorawee avatar thiskappaisgrey avatar vcanumalla avatar yzh119 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

Forkers

ninehusky

churchroad's Issues

Add type checking as part of tests

Recently, a commit broke something (see: #51 ) broke something that could've been caught if the tests also ran typechecking.

Please also run typechecking as part of tests - to make sure that new commits don't break anything. Thanks.

Investigate possible impact of $shiftx vs. $shr

According to the Yosys documentation:

The $shift cell performs a right logical shift if the second operand is positive (or unsigned), and a left logical shift if it is negative. The $shiftx cell performs the same operation as the $shift cell, but the vacated bit positions are filled with undef (x) bits, and corresponds to the Verilog indexed part-select expression.

Because Churchroad doesn't support X bits, for now we'll encode both to a regular right shift, but this is something to potentially keep in mind.

Verilator testing is still broken on Mac

Verilator is becoming the bane of my existence

We are doing weird things on Mac though, using brew LLVM etc.

There's a chance Verilator should just work with default MacOS clang. I need to do more testing on this. With Lakeroad I could always get things to work, but it seems like I can't anymore.

Strange issue with LUT6

`timescale  1 ps / 1 ps
//
// LUT6 primitive for Xilinx FPGAs
// Compatible with Verilator tool (www.veripool.org)
// Copyright (c) 2019-2020 Frédéric REQUIN
// License : BSD
//

module LUT6
#(
    parameter [64:0] INIT = 64'h0000000000000000
)
(
    input  wire I0, I1, I2, I3, I4, I5,
    output wire O
);
    wire [5:0] _w_idx = { I5, I4, I3, I2, I1, I0 };
    
    assign O = INIT[_w_idx];

endmodule

produces

;;; generated with `yosys -p 'plugin -i churchroad; "read_verilog -sv <lut6.sv> prep -top LUT6; pmuxtree; write_lakeroad"`

; wire declarations
; $auto$splice.cc:140:get_spliced_signal$3
(let v0 (Wire "v0" 2))
; $auto$splice.cc:140:get_spliced_signal$5
(let v1 (Wire "v1" 3))
; $auto$splice.cc:140:get_spliced_signal$7
(let v2 (Wire "v2" 4))
; $auto$splice.cc:140:get_spliced_signal$9
(let v3 (Wire "v3" 5))
; I0
(let v4 (Wire "v4" 1))
; I1
(let v5 (Wire "v5" 1))
; I2
(let v6 (Wire "v6" 1))
; I3
(let v7 (Wire "v7" 1))
; I4
(let v8 (Wire "v8" 1))
; I5
(let v9 (Wire "v9" 1))
; O
(let v10 (Wire "v10" 1))
; _w_idx
(let v11 (Wire "v11" 6))

; cells
(union v11 (Op2 (Concat) v3 v9))
(union v0 (Op2 (Concat) v4 v5))
(union v1 (Op2 (Concat) v0 v6))
(union v2 (Op2 (Concat) v1 v7))
(union v3 (Op2 (Concat) v2 v8))
; 64'0000000000000000000000000000000000000000000000000000000000000000
(let v12 (Op0 (BV 0 64)))
(let v13 (Op1 (Extract 0 0) v12))
(union v10 (Op2 (Shr) v13 v11))

; inputs
(let I0 (Var "I0" 1))
(union v4 I0)
(let I1 (Var "I1" 1))
(union v5 I1)
(let I2 (Var "I2" 1))
(union v6 I2)
(let I3 (Var "I3" 1))
(union v7 I3)
(let I4 (Var "I4" 1))
(union v8 I4)
(let I5 (Var "I5" 1))
(union v9 I5)

; outputs
(let O v10)

; delete wire expressions
(delete (Wire "v0" 2))
(delete (Wire "v1" 3))
(delete (Wire "v2" 4))
(delete (Wire "v3" 5))
(delete (Wire "v4" 1))
(delete (Wire "v5" 1))
(delete (Wire "v6" 1))
(delete (Wire "v7" 1))
(delete (Wire "v8" 1))
(delete (Wire "v9" 1))
(delete (Wire "v10" 1))
(delete (Wire "v11" 6))

which seems wrong, because the shift/extract seem to be in the wrong order.

the RTLIL is

# Generated by Yosys 0.35+36 (git sha1 c95298225, aarch64-apple-darwin20.2-clang 10.0.0-4ubuntu1 -fPIC -Os)
autoidx 2
attribute \top 1
attribute \src "/Users/andrew/research/lakeroad/verilog/simulation/xilinx-ultrascale-plus/LUT6.v:9.1-21.10"
module \LUT6
  parameter \INIT 64'0000000000000000000000000000000000000000000000000000000000000000
  attribute \src "/Users/andrew/research/lakeroad/verilog/simulation/xilinx-ultrascale-plus/LUT6.v:14.17-14.19"
  wire input 1 \I0
  attribute \src "/Users/andrew/research/lakeroad/verilog/simulation/xilinx-ultrascale-plus/LUT6.v:14.21-14.23"
  wire input 2 \I1
  attribute \src "/Users/andrew/research/lakeroad/verilog/simulation/xilinx-ultrascale-plus/LUT6.v:14.25-14.27"
  wire input 3 \I2
  attribute \src "/Users/andrew/research/lakeroad/verilog/simulation/xilinx-ultrascale-plus/LUT6.v:14.29-14.31"
  wire input 4 \I3
  attribute \src "/Users/andrew/research/lakeroad/verilog/simulation/xilinx-ultrascale-plus/LUT6.v:14.33-14.35"
  wire input 5 \I4
  attribute \src "/Users/andrew/research/lakeroad/verilog/simulation/xilinx-ultrascale-plus/LUT6.v:14.37-14.39"
  wire input 6 \I5
  attribute \src "/Users/andrew/research/lakeroad/verilog/simulation/xilinx-ultrascale-plus/LUT6.v:15.17-15.18"
  wire output 7 \O
  attribute \src "/Users/andrew/research/lakeroad/verilog/simulation/xilinx-ultrascale-plus/LUT6.v:17.16-17.22"
  wire width 6 \_w_idx
  attribute \src "/Users/andrew/research/lakeroad/verilog/simulation/xilinx-ultrascale-plus/LUT6.v:0.0-0.0"
  cell $shiftx $shiftx$/Users/andrew/research/lakeroad/verilog/simulation/xilinx-ultrascale-plus/LUT6.v:0$1
    parameter \A_SIGNED 0
    parameter \A_WIDTH 64
    parameter \B_SIGNED 0
    parameter \B_WIDTH 6
    parameter \Y_WIDTH 1
    connect \A 64'0000000000000000000000000000000000000000000000000000000000000000
    connect \B { \I5 \I4 \I3 \I2 \I1 \I0 }
    connect \Y \O
  end
  connect \_w_idx { \I5 \I4 \I3 \I2 \I1 \I0 }
end

Smoketest: Churchroad multiply expression compiled and simulated via Lakeroad

A simple first smoketest would be to use Churchroad to compile a design which Lakeroad can already synthesize by itself: a multiply narrow enough to fit on a single DSP.

Essentially, the steps are this:

  • 1. Begin with a combinational multiply expression in Verilog.
  • 2. Import design into Churchroad; something like (Op2 (Mul) a b) of <18 bits.
  • 3. Rewrite the multiply to a DSP primitive (using the generic primitive interfaces from Lakeroad).
    Something like (rewrite (Op2 (Mul) a b [of a certain bitwidth]) (PrimitiveInterface (DSP <params>) a b)
  • #85
  • 5. If Lakeroad returns successfully, which it should, insert the compiled version back into the egraph.
  • 6. Extract a compiled design from the egraph.
  • 7. Compile extracted design to Verilog.
  • 8. Simulate against original design to validate correctness.

Yosys plugin generating incorrect `ZeroExtend`s

When using the Churchroad Yosys plugin, I'm seeing that there are multiple ZeroExtends that aren't correct. Consider the following module:

module my_module(
    input a,
    input b,
    output[1:0] o,
);
    assign o = {a, b};
endmodule

Running yosys -m $CHURCHROAD_DIR/yosys-plugin/churchroad.so -q -p "read_verilog -sv my-module.v; prep -top my_module; pmuxtree; write_lakeroad" yields:

; wire declarations
; a
(let v0 (Wire "v0" 1))
; b
(let v1 (Wire "v1" 1))
; o
(let v2 (Wire "v2" 2))

; cells
; TODO not handling signedness
(let v3 (Op1 (ZeroExtend 2) v1))
; TODO not handling signedness
(let v4 (Op1 (ZeroExtend 2) v0))
(union v2 (Op2 (Concat) v3 v4))

; inputs
(let a (Var "a" 1))
(IsPort "" "a" (Input) a)
(union v0 a)
(let b (Var "b" 1))
(IsPort "" "b" (Input) b)
(union v1 b)

; outputs
(let o v2)
(IsPort "" "o" (Output) o)

; delete wire expressions
(delete (Wire "v0" 1))
(delete (Wire "v1" 1))
(delete (Wire "v2" 2))

v2, which is the output of the module, is being assigned the concatenation of v3 and v4, each of which are respectively a and b zero-extended to be of bitwidth 2. This means that we're unioning two things of different bitwidth!

Unnecessary ZeroExtend and Concat

The following example is a 2-bit ripple-carry adder in Verilog.

module top
  (
	  i_a,
	  i_b,
	  o_s,
	  o_c
  );

  input [1:0] i_a;
  input [1:0] i_b;
  output [1:0] o_s;
  output o_c;

  wire [1:0] c;
  
  assign o_s[0] = i_a[0] ^ i_b[0] ^ 1'b0;
  assign c[0] = (i_a[0] & i_b[0]) | (i_b[0] & 1'b0) | (i_a[0] & 1'b0);
  
  assign o_s[1] = i_a[1] ^ i_b[1] ^ c[0];
  assign c[1] = (i_a[1] & i_b[1]) | (i_b[1] & c[0]) | (i_a[1] & c[0]);
  
  assign o_c = c[1];

endmodule

The generated Churchroad has lots of (seemingly?) unnecessary Concat and ZeroExtend expressions.
(Edit: Can recreate using the Churchroad web demo: https://sampl.cs.washington.edu/churchroad-web-demo/)
For example:

; TODO not handling signedness
(let v16 (Op1 (ZeroExtend 2) v3))
; TODO not handling signedness
(let v17 (Op1 (ZeroExtend 2) v4))
(union v15 (Op2 (Concat) v16 v17))

But I don't know that it makes sense to ZeroExtend wires like v3 and v4 as they are just from 1-bit Xor expressions:

(union v3 (Op2 (Xor) v5 v6))
(union v4 (Op2 (Xor) v10 v11))

And v15 is declared as a 2-bit wire, but the Concat expression makes it seem like the result is 4 bits (from the ZeroExtend).

These generated expressions seem to come from this commit: 3b48098

Stop assuming Yosys cells have inputs with matching bitwidths

For example, Yosys's $add cell has inputs A and B, and their bitwidths do not necessarily match. However, Churchroad currently assumes they do. This has already led to bugs (e.g. in Andrew's usecases).

There are a few things to consider at the same time:

  • What are the input bitwidths?
  • What do we do if they don't match? Extend the shorter one to the longer one?
  • How do we extend the shorter one, if that's what we do? Do we zero extend or sign extend?
  • What is the output bitwidth?
  • How do we extend the result, if that's what we do? Zero or sign extend?

Remove Lakeroad work from git history

This is definitely non-essential.

There's a lot of noise in the repo commit data because we forked this repo from Lakeroad. One simple way to fix this would be to start the git history at c24f10e4c9d3950ecab9fc7aa3c3d96eabcef1bc. There's still a bunch of intervening Lakeroad work between that commit and the real start of the Churchroad repo, though.

The other option is to start it at 01388887c9e97056d2e7a343c70d5afd396d5f62, where we convert the repo to Churchroad. In that case, though, I want to make sure Thanawat gets credit for his contributions still.

Make a new syntax node for modules

For the decompilation application, we need to turn the modules that we find back into verilog instantiations of the module (i.e. unflatten). Right now, I instantiate my module like:

(function ALU ( Expr  Expr Expr ) Expr :cost 0)

which is the "simplest" solution for now. However, I'd need to be able to turn this expression:

(ALU i_bit1 i_bit2 i_op) 

Into the verilog:

// may probably need to declare a wire for the output of the ALU or something
wire o_out;
alu alu(
           .i_a (o_a), 
          .i_b (o_b),
          .i_control (i_op),
          .o_res (o_out)
          );

when we do the decompilation and turn the Egglog expression back into the verilog again.

There are probably some other complications with this - but this is the idea for now.

"Missing symbol called" error with Yosys on Mac

(.venv) (.venv) fortyfort ➜  churchroad git:(ninehusky-even-more-operators) ✗ yosys -m yosys-plugin/churchroad.so -p 'read_verilog -sv tests/interpreter_tests/verilog/xilinx_ultrascale_plus/LUT6-modified.v; write_lakeroad'

 /----------------------------------------------------------------------------\
 |                                                                            |
 |  yosys -- Yosys Open SYnthesis Suite                                       |
 |                                                                            |
 |  Copyright (C) 2012 - 2020  Claire Xenia Wolf <[email protected]>         |
 |                                                                            |
 |  Permission to use, copy, modify, and/or distribute this software for any  |
 |  purpose with or without fee is hereby granted, provided that the above    |
 |  copyright notice and this permission notice appear in all copies.         |
 |                                                                            |
 |  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES  |
 |  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF          |
 |  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR   |
 |  ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES    |
 |  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN     |
 |  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF   |
 |  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.            |
 |                                                                            |
 \----------------------------------------------------------------------------/

 Yosys 0.36+42 (git sha1 70d35314d, clang 15.0.0 -fPIC -Os)


-- Running command `read_verilog -sv tests/interpreter_tests/verilog/xilinx_ultrascale_plus/LUT6-modified.v; write_lakeroad' --

1. Executing Verilog-2005 frontend: tests/interpreter_tests/verilog/xilinx_ultrascale_plus/LUT6-modified.v
Parsing SystemVerilog input from `tests/interpreter_tests/verilog/xilinx_ultrascale_plus/LUT6-modified.v' to AST representation.
Generating RTLIL representation for module `\LUT6'.
Successfully finished Verilog frontend.

2. Executing Lakeroad egglog backend.

3. Executing SPLICE pass (creating cells for signal splicing).
Splicing signals in module LUT6:
  Created spliced signal: { \I5 \I4 \I3 \I2 \I1 \I0 } -> $auto$splice.cc:140:get_spliced_signal$11

4. Executing SPLITNETS pass (splitting up multi-bit signals).
Removed 0 unused cells and 3 unused wires.
; wire declarations
dyld[83653]: missing symbol called
[1]    83653 abort      yosys -m yosys-plugin/churchroad.so -p 

Determine whether we're overusing `sigmap` in `churchroad.cc`

I suspect it might not be needed at all; currently, we're using it all over the place.

My understanding of sigmap has changed a lot. It seems like its main purpose is to generate a canonical representation of a wire, including tasks like inserting constant bits when one of the bits is known to be constant. That's not exactly what we need.

For example:
https://github.com/uwsampl/churchroad/blob/4a2a170d4a85cef4a35d2674336d6f154981e617/yosys-plugin/churchroad.cc#L1448

Wires that are not unioned to anything and then deleted will break the egraph

If the design has a wire that is never assigned to anything, then it will produce an eclass with just a Wire in it. Later, that Wire will be deleted, and anything that pointed to that eclass will now be syntactically incorrect.

Thanks to @thiskappaisgrey for finding this.

Subtasks:

  • Enforce the use of splice; splitnets -driver passes before Churchroad backend, either by running them explicitly, or via documentation. Also add checks to see whether they've been run.
    • The passes are run, but we still don't check that the design is in a sane state. Opening a new issue for this.

Create interpreter binary

There should be a way to run the Churchroad interpreter directly on Churchroad source code (i.e., src.egg).

Good test case: Mapping wider FMAs

This was mentioned by @dpetrisko.

Apparently Vivado is failing to map wide FMAs to DSPs efficiently.

Lakeroad alone probably can't do this -- once a solver query needs to figure out that some combination of bvmuls == one wide bvmul, they all seem to choke. There may be solver tricks to do this (reasoning about multiplies is a known hard problem; I would think solvers like cvc5 would have done research on this). However, there's an even more obvious way around this: use equality saturation (ie Churchroad) to block up the FMA via rewrites, and then run Lakeroad synthesis on the smaller FMAs that result. Assuming the smaller FMAs are sized to fit on a single DSP, then this should work great.

Subtasks:

  • Get an example of a realistic wide FMA.
  • See how Vivado fails to map it.
  • Ingest wide FMA into Churchroad.
  • Develop rewrites to block wide FMA into DSP-sized FMAs.
  • Call out to Lakeroad to map the DSP-sized FMAs.

List of benchmarks from Dan

cc @dpetrisko

I'll use this issue to collect benchmarks from Dan. These should be examples where Vivado produces mappings that Dan suspects we can improve upon.

Create a Churchroad interpreter

We need a way to interpret Churchroad programs so that we can ensure the Verilog -> Churchroad translation is correct (and probably for other reasons too).

Pull requests from public forks will not be able to run CI

This needs to be fixed in the long term. It seems like this will also be an issue with Lakeroad.

The primary issue is that our CI pushes an image, and public forks can't get write permissions to packages. It can be enabled in settings I think, but I'm unsure whether that's actually a sane idea.

Call out to Lakeroad to attempt to synthesize the `PrimitiveInterface`

Given an egraph with a primitive interface present inside of it, call out to Lakeroad to attempt to synthesize the primtive interface(s).

Probably easier to just start with the following functions:

  1. A function to find instances of primitive interfaces
  2. A function to, for a given instance of a primitive interface, call Lakeroad.

Prefix input variables with `i_` and output variables with `o_`

Hi,
I believe that the Var node is the only node that is used for inputs anyways(but having a naming convention is still good so that we can search for which variables are inputs in the code?), so it doesn't matter too much, but I need output egglog variables to be prefixed with o_ so I can automatically find which ones to extract when creating the rewrite rule. I've been prefixing them manually but adding them to the plugin would be nicer. I just realize that some projects don't follow the convention of prefixing input variables with i_ and output variables with o_ and there's no way to search for them in code the output egglog otherwise.

Thanks.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.