-
Notifications
You must be signed in to change notification settings - Fork 347
[circt-lec] Introduce the circt-lec
tool
#3991
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its 8000 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
Changes from all commits
f52dd6e
d3ca95a
ca36d01
74ae51b
ae04de2
743b41d
b295bac
d926e54
63f2e12
7697030
79d5d1d
75a3ae0
16fd18d
3087f81
6e36bb1
3626a41
c762ee1
8f4ac68
2b5d3db
dbcfb50
7fdcec5
d80f9d7
8515594
d6cc972
0bb2973
993c834
e52f227
4ce5155
7e3d7be
351eaed
4391f24
97a8c2f
3852499
4921d85
6d4869c
c0d1f34
41dd724
96f5fee
20866dc
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
// These tests will be only enabled if circt-lec is built. | ||
// REQUIRES: circt-lec | ||
|
||
// builtin.module implementation | ||
// RUN: circt-lec %s -v=false | FileCheck %s --check-prefix=BUILTIN_MODULE | ||
// BUILTIN_MODULE: c1 == c2 | ||
|
||
hw.module @basic(%in: i1) -> (out: i1) { | ||
hw.output %in : i1 | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,254 @@ | ||
// These tests will be only enabled if circt-lec is built. | ||
// REQUIRES: circt-lec | ||
|
||
hw.module @basic(%in: i1) -> (out: i1) { | ||
hw.output %in : i1 | ||
} | ||
|
||
hw.module @not(%in: i1) -> (out: i1) { | ||
%true = hw.constant true | ||
%out = comb.xor bin %in, %true : i1 | ||
hw.output %out : i1 | ||
} | ||
|
||
// comb.add | ||
// RUN: circt-lec %s -c1=adder -c2=completeAdder -v=false | FileCheck %s --check-prefix=COMB_ADD | ||
// COMB_ADD: c1 == c2 | ||
|
||
hw.module @adder(%in1: i2, %in2: i2) -> (out: i2) { | ||
%sum = comb.add bin %in1, %in2 : i2 | ||
hw.output %sum : i2 | ||
} | ||
|
||
hw.module @halfAdder(%in1: i1, %in2: i1) -> (carry: i1, sum: i1) { | ||
%sum = comb.xor bin %in1, %in2 : i1 | ||
%carry = comb.and bin %in1, %in2 : i1 | ||
hw.output %carry, %sum: i1, i1 | ||
} | ||
|
||
hw.module @completeAdder(%in1: i2, %in2 : i2) -> (out: i2) { | ||
%in1_0 = comb.extract %in1 from 0 : (i2) -> i1 | ||
%in1_1 = comb.extract %in1 from 1 : (i2) -> i1 | ||
%in2_0 = comb.extract %in2 from 0 : (i2) -> i1 | ||
%in2_1 = comb.extract %in2 from 1 : (i2) -> i1 | ||
%c1, %s1 = hw.instance "h1" @halfAdder(in1: %in1_0: i1, in2: %in2_0: i1) -> (carry: i1, sum: i1) | ||
%c2, %s2 = hw.instance "h2" @halfAdder(in1: %in1_1: i1, in2: %in2_1: i1) -> (carry: i1, sum: i1) | ||
%c3, %s3 = hw.instance "h3" @halfAdder(in1: %s2: i1, in2: %c1: i1) -> (carry: i1, sum: i1) | ||
%fullsum = comb.concat %s3, %s1 : i1, i1 | ||
hw.output %fullsum : i2 | ||
} | ||
|
||
// comb.and | ||
// RUN: circt-lec %s -c1=and -c2=decomposedAnd -v=false | FileCheck %s --check-prefix=COMB_AND | ||
// COMB_AND: c1 == c2 | ||
|
||
hw.module @and(%in1: i1, %in2: i1) -> (out: i1) { | ||
%out = comb.and bin %in1, %in2 : i1 | ||
hw.output %out : i1 | ||
} | ||
|
||
hw.module @decomposedAnd(%in1: i1, %in2: i1) -> (out: i1) { | ||
%not_in1 = hw.instance "n_in1" @not(in: %in1: i1) -> (out: i1) | ||
%not_in2 = hw.instance "n_in2" @not(in: %in2: i1) -> (out: i1) | ||
%not_and = comb.or bin %not_in1, %not_in2 : i1 | ||
%and = hw.instance "and" @not(in: %not_and: i1) -> (out: i1) | ||
hw.output %and : i1 | ||
} | ||
|
||
// comb.concat | ||
// TODO | ||
|
||
// comb.divs | ||
// TODO | ||
|
||
// comb.divu | ||
// TODO | ||
|
||
// comb.extract | ||
// TODO | ||
|
||
// comb.icmp | ||
// TODO | ||
|
||
// comb.mods | ||
// TODO | ||
|
||
// comb.modu | ||
// TODO | ||
|
||
// comb.mul | ||
// RUN: circt-lec %s -c1=mulBy2 -c2=addTwice -v=false | FileCheck %s --check-prefix=COMB_MUL | ||
// COMB_MUL: c1 == c2 | ||
|
||
hw.module @mulBy2(%in: i2) -> (out: i2) { | ||
%two = hw.constant 2 : i2 | ||
%res = comb.mul bin %in, %two : i2 | ||
hw.output %res : i2 | ||
} | ||
|
||
hw.module @addTwice(%in: i2) -> (out: i2) { | ||
%res = comb.add bin %in, %in : i2 | ||
hw.output %res : i2 | ||
} | ||
Comment on lines
+79
to
+92
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's very cool that we can have these kinds of self-contained tests where we just logically compare two things to each other. Very exciting. I could totally see us use this pattern to verify canonicalizations and folders which aren't supposed to functionally change the circuit 🤩 |
||
|
||
// comb.mux | ||
// RUN: circt-lec %s -c1=mux -c2=decomposedMux -v=false | FileCheck %s --check-prefix=COMB_MUX | ||
// COMB_MUX: c1 == c2 | ||
|
||
hw.module @mux(%cond: i1, %tvalue: i8, %fvalue: i8) -> (out: i8) { | ||
%res = comb.mux bin %cond, %tvalue, %fvalue : i8 | ||
hw.output %res : i8 | ||
} | ||
|
||
hw.module @decomposedMux(%cond: i1, %tvalue: i8, %fvalue: i8) -> (out: i8) { | ||
%cond_bar = hw.instance "n" @not(in: %cond: i1) -> (out: i1) | ||
%lead_0 = hw.constant 0 : i7 | ||
%c_t = comb.concat %lead_0, %cond : i7, i1 | ||
%c_f = comb.concat %lead_0, %cond_bar : i7, i1 | ||
%t = comb.mul bin %tvalue, %c_t : i8 | ||
%f = comb.mul bin %fvalue, %c_f : i8 | ||
%res = comb.add bin %t, %f : i8 | ||
hw.output %res : i8 | ||
} | ||
|
||
// comb.or | ||
// RUN: circt-lec %s -c1=or -c2=decomposedOr -v=false | FileCheck %s --check-prefix=COMB_OR | ||
// COMB_OR: c1 == c2 | ||
|
||
hw.module @or(%in1: i1, %in2: i1) -> (out: i1) { | ||
%out = comb.or bin %in1, %in2 : i1 | ||
hw.output %out : i1 | ||
} | ||
|
||
hw.module @decomposedOr(%in1: i1, %in2: i1) -> (out: i1) { | ||
%not_in1 = hw.instance "n_in1" @not(in: %in1: i1) -> (out: i1) | ||
%not_in2 = hw.instance "n_in2" @not(in: %in2: i1) -> (out: i1) | ||
%not_or = comb.and bin %not_in1, %not_in2 : i1 | ||
%or = hw.instance "or" @not(in: %not_or: i1) -> (out: i1) | ||
hw.output %or : i1 | ||
} | ||
|
||
// comb.parity | ||
// RUN: circt-lec %s -c1=parity -c2=decomposedParity -v=false | FileCheck %s --check-prefix=COMB_PARITY | ||
// COMB_PARITY: c1 == c2 | ||
|
||
hw.module @parity(%in: i8) -> (out: i1) { | ||
%res = comb.parity bin %in : i8 | ||
hw.output %res : i1 | ||
} | ||
|
||
hw.module @decomposedParity(%in: i8) -> (out: i1) { | ||
%b0 = comb.extract %in from 0 : (i8) -> i1 | ||
%b1 = comb.extract %in from 1 : (i8) -> i1 | ||
%b2 = comb.extract %in from 2 : (i8) -> i1 | ||
%b3 = comb.extract %in from 3 : (i8) -> i1 | ||
%b4 = comb.extract %in from 4 : (i8) -> i1 | ||
%b5 = comb.extract %in from 5 : (i8) -> i1 | ||
%b6 = comb.extract %in from 6 : (i8) -> i1 | ||
%b7 = comb.extract %in from 7 : (i8) -> i1 | ||
%res = comb.xor bin %b0, %b1, %b2, %b3, %b4, %b5, %b6, %b7 : i1 | ||
hw.output %res : i1 | ||
} | ||
|
||
// comb.replicate | ||
// RUN: circt-lec %s -c1=replicate -c2=decomposedReplicate -v=false | FileCheck %s --check-prefix=COMB_REPLICATE | ||
// COMB_REPLICATE: c1 == c2 | ||
|
||
hw.module @replicate(%in: i2) -> (out: i8) { | ||
%res = comb.replicate %in : (i2) -> i8 | ||
hw.output %res : i8 | ||
} | ||
|
||
hw.module @decomposedReplicate(%in: i2) -> (out: i8) { | ||
%res = comb.concat %in, %in, %in, %in : i2, i2, i2, i2 | ||
hw.output %res : i8 | ||
} | ||
|
||
// comb.shl | ||
// RUN: circt-lec %s -c1=shl -c2=decomposedShl -v=false | FileCheck %s --check-prefix=COMB_SHL | ||
// COMB_SHL: c1 == c2 | ||
|
||
hw.module @shl(%in1: i2, %in2: i2) -> (out: i2) { | ||
%res = comb.shl bin %in1, %in2 : i2 | ||
hw.output %res : i2 | ||
} | ||
|
||
hw.module @decomposedShl(%in1: i2, %in2: i2) -> (out: i2) { | ||
%zero = hw.constant 0 : i2 | ||
% 1 : i2 | ||
%two = hw.constant 2 : i2 | ||
// first possible shift | ||
%cond1 = comb.icmp bin ugt %in2, %zero : i2 | ||
%mul1 = comb.mux bin %cond1, %two, %one : i2 | ||
%shl1 = comb.mul bin %in1, %mul1 : i2 | ||
// avoid subtraction underflow | ||
%cond1_1 = comb.icmp bin eq %in2, %zero : i2 | ||
%sub1 = comb.mux bin %cond1_1, %zero, %one : i2 | ||
%in2_2 = comb.sub bin %in2, %sub1 : i2 | ||
// second possible shift | ||
%cond2 = comb.icmp bin ugt %in2_2, %zero : i2 | ||
%mul2 = comb.mux bin %cond2, %two, %one : i2 | ||
%shl2 = comb.mul bin %shl1, %mul2 : i2 | ||
hw.output %shl2 : i2 | ||
} | ||
|
||
// comb.shrs | ||
// TODO | ||
|
||
// comb.shru | ||
// TODO | ||
|
||
// comb.sub | ||
// RUN: circt-lec %s -c1=subtractor -c2=completeSubtractor -v=false | FileCheck %s --check-prefix=COMB_SUB | ||
// COMB_SUB: c1 == c2 | ||
|
||
hw.module @subtractor(%in1: i8, %in2: i8) -> (out: i8) { | ||
%diff = comb.sub bin %in1, %in2 : i8 | ||
hw.output %diff : i8 | ||
} | ||
|
||
hw.module @halfSubtractor(%in1: i1, %in2: i1) -> (borrow: i1, diff: i1) { | ||
%diff = comb.xor bin %in1, %in2 : i1 | ||
%not_in1 = hw.instance "n_in1" @not(in: %in1: i1) -> (out: i1) | ||
%borrow = comb.and bin %not_in1, %in2 : i1 | ||
hw.output %borrow, %diff: i1, i1 | ||
} | ||
|
||
hw.module @fullSubtractor(%in1: i1, %in2: i1, %b_in: i1) -> (borrow: i1, diff: i1) { | ||
%b1, %d1 = hw.instance "s1" @halfSubtractor(in1: %in1: i1, in2: %in2: i1) -> (borrow: i1, diff: i1) | ||
%b2, %d_out = hw.instance "s2" @halfSubtractor(in1: %d1: i1, in2: %b_in: i1) -> (borrow: i1, diff: i1) | ||
%b_out = comb.or bin %b1, %b2 : i1 | ||
hw.output %b_out, %d_out: i1, i1 | ||
} | ||
|
||
hw.module @completeSubtractor(%in1: i8, %in2 : i8) -> (out: i8) { | ||
%in1_0 = comb.extract %in1 from 0 : (i8) -> i1 | ||
%in1_1 = comb.extract %in1 from 1 : (i8) -> i1 | ||
%in1_2 = comb.extract %in1 from 2 : (i8) -> i1 | ||
%in1_3 = comb.extract %in1 from 3 : (i8) -> i1 | ||
%in1_4 = comb.extract %in1 from 4 : (i8) -> i1 | ||
%in1_5 = comb.extract %in1 from 5 : (i8) -> i1 | ||
%in1_6 = comb.extract %in1 from 6 : (i8) -> i1 | ||
%in1_7 = comb.extract %in1 from 7 : (i8) -> i1 | ||
%in2_0 = comb.extract %in2 from 0 : (i8) -> i1 | ||
%in2_1 = comb.extract %in2 from 1 : (i8) -> i1 | ||
%in2_2 = comb.extract %in2 from 2 : (i8) -> i1 | ||
%in2_3 = comb.extract %in2 from 3 : (i8) -> i1 | ||
%in2_4 = comb.extract %in2 from 4 : (i8) -> i1 | ||
%in2_5 = comb.extract %in2 from 5 : (i8) -> i1 | ||
%in2_6 = comb.extract %in2 from 6 : (i8) -> i1 | ||
%in2_7 = comb.extract %in2 from 7 : (i8) -> i1 | ||
%b0, %d0 = hw.instance "s0" @halfSubtractor(in1: %in1_0: i1, in2: %in2_0: i1) -> (borrow: i1, diff: i1) | ||
%b1, %d1 = hw.instance "s1" @fullSubtractor(in1: %in1_1: i1, in2: %in2_1: i1, b_in: %b0: i1) -> (borrow: i1, diff: i1) | ||
%b2, %d2 = hw.instance "s2" @fullSubtractor(in1: %in1_2: i1, in2: %in2_2: i1, b_in: %b1: i1) -> (borrow: i1, diff: i1) | ||
%b3, %d3 = hw.instance "s3" @fullSubtractor(in1: %in1_3: i1, in2: %in2_3: i1, b_in: %b2: i1) -> (borrow: i1, diff: i1) | ||
%b4, %d4 = hw.instance "s4" @fullSubtractor(in1: %in1_4: i1, in2: %in2_4: i1, b_in: %b3: i1) -> (borrow: i1, diff: i1) | ||
%b5, %d5 = hw.instance "s5" @fullSubtractor(in1: %in1_5: i1, in2: %in2_5: i1, b_in: %b4: i1) -> (borrow: i1, diff: i1) | ||
%b6, %d6 = hw.instance "s6" @fullSubtractor(in1: %in1_6: i1, in2: %in2_6: i1, b_in: %b5: i1) -> (borrow: i1, diff: i1) | ||
%b7, %d7 = hw.instance "s7" @fullSubtractor(in1: %in1_7: i1, in2: %in2_7: i1, b_in: %b6: i1) -> (borrow: i1, diff: i1) | ||
%diff = comb.concat %d7, %d6, %d5, %d4, %d3, %d2, %d1, %d0 : i1, i1, i1, i1, i1, i1, i1, i1 | ||
hw.output %diff : i8 | ||
} | ||
|
||
// comb.xor | ||
// TODO |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
// These tests will be only enabled if circt-lec is built. | ||
// REQUIRES: circt-lec | ||
|
||
// RUN: split-file %s %t | ||
|
||
// Passing two input files | ||
// RUN: circt-lec %t/first.mlir %t/second.mlir -v=false | FileCheck %s | ||
// CHECK: c1 == c2 | ||
|
||
//--- first.mlir | ||
hw.module @basic(%in: i1) -> (out: i1) { | ||
hw.output %in : i1 | ||
} | ||
|
||
//--- second.mlir | ||
hw.module @basic(%in: i1) -> (out: i1) { | ||
hw.output %in : i1 | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
// These tests will be only enabled if circt-lec is built. | ||
// REQUIRES: circt-lec | ||
|
||
hw.module @basic(%in: i1) -> (out: i1) { | ||
hw.output %in : i1 | ||
} | ||
|
||
// hw.constant | ||
// RUN: circt-lec %s -c1=basic -c2=notnot -v=false | FileCheck %s --check-prefix=HW_CONSTANT | ||
// HW_CONSTANT: c1 == c2 | ||
|
||
hw.module @onePlusTwo() -> (out: i2) { | ||
% 1 : i2 | ||
%two = hw.constant 2 : i2 | ||
%three = comb.add bin %one, %two : i2 | ||
hw.output %three : i2 | ||
} | ||
|
||
hw.module @three() -> (out: i2) { | ||
%three = hw.constant 3 : i2 | ||
hw.output %three : i2 | ||
} | ||
|
||
// hw.instance | ||
// RUN: circt-lec %s -c1=basic -c2=notnot -v=false | FileCheck %s --check-prefix=HW_INSTANCE | ||
// HW_INSTANCE: c1 == c2 | ||
|
||
hw.module @not(%in: i1) -> (out: i1) { | ||
%true = hw.constant true | ||
%out = comb.xor bin %in, %true : i1 | ||
hw.output %out : i1 | ||
} | ||
|
||
hw.module @notnot(%in: i1) -> (out: i1) { | ||
%n = hw.instance "n" @not(in: %in: i1) -> (out: i1) | ||
%nn = hw.instance "nn" @not(in: %n: i1) -> (out: i1) | ||
hw.output %nn : i1 | ||
} | ||
|
||
// hw.output | ||
// RUN: circt-lec %s -c1=basic -c2=basic -v=false | FileCheck %s --check-prefix=HW_OUTPUT | ||
// HW_OUTPUT: c1 == c2 |
Uh oh!
There was an error while loading. Please reload this page.