diff options
| author | Adam Izraelevitz | 2015-07-29 11:22:02 -0700 |
|---|---|---|
| committer | Adam Izraelevitz | 2015-07-29 11:22:02 -0700 |
| commit | 6ce20db7e2f81cd3ef8f859614f423bea897484b (patch) | |
| tree | f1a60ab050d9dda6aca63bc4b6be9df138adb4f2 | |
| parent | 0c7aca561aef907314b0d9c9737fcea04ae6ce82 (diff) | |
Add bigint support.
| -rw-r--r-- | src/main/stanza/bigint.stanza | 173 | ||||
| -rw-r--r-- | src/main/stanza/firrtl-lexer.stanza | 6 | ||||
| -rw-r--r-- | src/main/stanza/firrtl-test-main.stanza | 2 | ||||
| -rw-r--r-- | src/main/stanza/ir-parser.stanza | 29 | ||||
| -rw-r--r-- | src/main/stanza/verilog.stanza | 10 | ||||
| -rw-r--r-- | test/chisel3/Test.fir | 9 |
6 files changed, 103 insertions, 126 deletions
diff --git a/src/main/stanza/bigint.stanza b/src/main/stanza/bigint.stanza index f5122323..7d8e6426 100644 --- a/src/main/stanza/bigint.stanza +++ b/src/main/stanza/bigint.stanza @@ -2,45 +2,45 @@ defpackage bigint : import core import verse - -public defn to-hex (num: Int) -> String : - val buf = StringBuffer() - print(buf, "0x") - var rems = List<Int>() - var x : Int = num - defn* loop () : - rems = List(x % 16, rems) - x = x / 16 - if x > 0: loop() - loop() - for r in rems do : - print(buf, to-char((to-int('0') + r) when r < 10 else (to-int('a') + r - 10))) - to-string(buf) - - val val-n-bytes = 4 val val-n-bits = val-n-bytes * 8 val val-all-ones = -1 ;; TODO val val-n-half-bits = 32 / 2 -defn val-n-words (nbits: Int) -> Int : 1 + (nbits - 1) / 32 ;val-n-bits +defn val-n-words (nbits: Int) -> Int : 1 + (nbits - 1) / 32 defn val-n-half-words (nbits: Int) -> Int : (1 + (nbits - 1)) / val-n-half-bits defn val-top-bit (v: Int) -> Int : v >> (32 - 1) defn val-n-full-words (nbits: Int) -> Int : nbits / 32 defn val-n-word-bits (nbits: Int) -> Int : nbits % 32 -defn mask-val (n: Int) : val-all-ones >> (32 - n) +defn mask-val (n: Int) : -1 >> (32 - n) public defclass BigInt <: Gettable & Settable & Lengthable public defmulti to-bin (b: BigInt) -> String +public defmulti to-hex (b: BigInt) -> String public defmulti num-words (b: BigInt) -> Int public defmulti dat (b: BigInt) -> Array<Int> public defn BigInt (len: Int) : val d = Array<Int>(val-n-words(len)) new BigInt : defmethod get (this, i: Int) -> Int : d[i] - defmethod set (this, i: Int, x: Int) : d[i] = x; & (-1) ;val-all-ones + defmethod set (this, i: Int, x: Int) : d[i] = x & -1 defmethod dat (this) -> Array<Int> : d defmethod length (this) -> Int : len defmethod num-words (this) -> Int : length(d) + defmethod to-hex (this) -> String : + defn as-hex (i: Int) -> String : + val str = "0123456789abcdef" + substring(str,i,i + 1) + var str = "h" + ;println(to-bin(this)) + for i in 0 to len by 4 do : + val pos = len - 4 - i + ;println(pos) + val digit = (d[pos / 32] >> (pos % 32)) & 15 + ;println(digit) + val hex = as-hex(digit) + ;println(hex) + str = string-join([str hex]) + string-join([ "\"" str "\""]) defmethod to-bin (this) -> String : string-join $ generate<Char> : @@ -49,11 +49,8 @@ public defn BigInt (len: Int) : yield(if (d[pos / 32] >> (pos % 32))&1 == 1: '1' else: '0') loop(pos - 1) loop(len - 1) - defmethod to-string (this) : - var s = "" - for x in d do : s = string-join([x s]) - s ;defmethod to-string (this) : string-join(["BigInt<" len ">(" to-bin(this) ")"]) + defmethod to-string (this) : to-hex(this) defmethod print (o:OutputStream, b:BigInt) : print(o, to-string(b)) @@ -78,7 +75,7 @@ defn mask! (d: BigInt) -> BigInt : val n-full-words = val-n-full-words(length(d)) val n-word-bits = val-n-word-bits(length(d)) for i in 0 to n-full-words do : - d[i] = val-all-ones + d[i] = -1 for i in n-full-words to num-words(d) do : d[i] = 0 if n-word-bits > 0 : @@ -97,8 +94,8 @@ defn extract! (d:BigInt, s0:BigInt, e:Int, s:Int) -> BigInt : trim!(rsh!(d, s0, public defn bits (s0:BigInt, e:Int, s:Int) -> BigInt : extract!(BigInt(e - s + 1), s0, e, s) public defn bit (s0:BigInt, s:Int) -> Int : - val wi = s / 32 ;val-n-bits - val bi = s % 32 ;val-n-bits + val wi = s / 32 + val bi = s % 32 s0[wi] >> bi defn inject! (d:BigInt, s0:BigInt, f:BigInt, start:Int) -> BigInt : @@ -151,71 +148,41 @@ public defn greater-eq?! (diff:BigInt, x:BigInt, y:BigInt) -> True|False : not l public defn greater-eq? (x:BigInt, y:BigInt) -> True|False : op(greater-eq?!, x, y) +defn as-digit (c: Char) -> Int : + index-of("0123456789abcdef", c) as Int + public defn BigIntLit (f: (Int) -> Int, len: Int) : fill!(f, BigInt(len)) -;val hex-nibbles = "0123456789abcdef" +public defn BigIntLit (x: Int, w: Int) : + fill!({_ + x}, BigInt(w)) -defn as-digit (c: Char) -> Int : - var index = 0 - for (x in "0123456789abcdef", i in 0 to false) do : - if x == c: index = i - index - ;val x = index-of(hex-nibbles, c) - ;x as Int +public defn BigIntLit (x: Int) : BigIntLit(x, sizeof(x)) public defn BigIntLit (s: String) : BigIntLit(s, -1) -;public defn BigIntLit (i: Int) : BigIntLit(string-join(["x" to-hex(to-string(i))])) - public defn BigIntLit (s: String, w:Int) : - val hd = s[0] - val base = if hd == 'b': 1 else if hd == 'x': 4 else: 'd' - val shamt = if base == 'b': 1 else if base == 'x': 4 else: 4 - val digits = if base == 'b': substring(s, 1) else if base == 'x': substring(s, 1) else: s + val base = s[0] + val shamt = if base == 'b': 1 else if base == 'h': 4 else: 2 + val digits = substring(s, 1) val len = if w == -1: length(digits) * shamt else: w - println-all(["STRING " s]) - println-all(["BASE " base " SHAMT " shamt " DIGITS " digits " LEN " len]) - var lit = BigInt(len) + val lit = BigInt(len) + ;; println-all(["BASE " base " SHAMT " shamt " DIGITS " digits]) for i in 0 to num-words(lit) do : lit[i] = 0 - - - switch {base == _} : - 'd' : - for i in 0 to length(digits) do : - val y = shift-left(lit,3) + shift-left(lit,1) - val x = to-int(substring(digits,i,i + 1)) - val z = BigInt(length(y)) - z[0] = x - lit = y + z - println-all(["DIGIT = " x]) - println-all(["Before LIT = " lit]) - - ;println-all(["After LIT = " lit]) - ;println-all(["RES = " to-bin(lit)]) - ;println-all(["RES = " lit]) - lit - else : - for i in 0 to length(digits) do : - val off = (length(digits) - 1 - i) * shamt - val wi = off / 32;val-n-bits - val bi = off % 32;val-n-bits - ;println-all(["OFF " off " wi " wi " bi " bi " digits " digits]) - lit[wi] = lit[wi] | ((as-digit(digits[i]) & 1) << bi) - ;println-all([" lit[wi] " lit[wi] " => " lit]) - ;println-all(["RES = " to-bin(lit)]) - ;println-all(["RES = " lit]) - lit + for i in 0 to length(digits) do : + val off = (length(digits) - 1 - i) * shamt + val wi = off / 32 + val bi = off % 32 + lit[wi] = lit[wi] | (as-digit(digits[i]) << bi) + ;; println-all(["OFF " off " wi " wi " bi " bi " lit[wi] " lit[wi] " => " lit]) + ;; println-all(["RES = " lit]) + lit public defn sizeof (in: Int) -> Int : + println(in) max(1, ceil-log2(in + 1)) -public defn BigIntLit (x: Int, w: Int) : - fill!({_ + x}, BigInt(w)) - -public defn BigIntLit (x: Int) : BigIntLit(x, sizeof(x)) - defn op (f:(BigInt, BigInt, BigInt) -> True|False, x:BigInt, y:BigInt) -> True|False : f(BigInt(max(length(x), length(y))), x, y) @@ -273,11 +240,11 @@ public defn neg (x:BigInt) -> BigInt : op(neg!, x) public defn rsha! (d:BigInt, s0:BigInt, amount:Int) -> BigInt : val w = length(s0) val nw = num-words(d) - val n-shift-bits = amount % 32;val-n-bits - val n-shift-words = amount / 32;val-n-bits - val n-rev-shift-bits = 32 - n-shift-bits;val-n-bits + val n-shift-bits = amount % 32 + val n-shift-words = amount / 32 + val n-rev-shift-bits = 32 - n-shift-bits val is-zero-carry = n-shift-bits == 0 - val msb = s0[nw - 1] >> (w - nw * 32 - 1);val-n-bits + val msb = s0[nw - 1] >> (w - nw * 32 - 1) var carry = 0; if msb == 0 : @@ -297,13 +264,13 @@ public defn rsha! (d:BigInt, s0:BigInt, amount:Int) -> BigInt : defn* loop (i:Int) : if i >= 0 : - val idx = i * val-n-bits + val idx = i * 32 if idx > boundary : - d[i] = val-all-ones + d[i] = -1 loop(i - 1) else : - d[i] = d[i] | (val-all-ones << (boundary - idx)) - d[nw - 1] = d[nw - 1] & (val-all-ones >> ((nw - 1) * val-n-bits - w)) + d[i] = d[i] | (-1 << (boundary - idx)) + d[nw - 1] = d[nw - 1] & (-1 >> ((nw - 1) * 32 - w)) loop(nw - 1) d @@ -312,9 +279,9 @@ public defn signed-shift-right (b:BigInt, n:Int) -> BigInt : rsha!(BigInt(length public defn rsh! (d:BigInt, s0:BigInt, amount:Int) -> BigInt : val nw = num-words(d) var carry = 0 - val n-shift-bits = amount % val-n-bits - val n-shift-words = amount / val-n-bits - val n-rev-shift-bits = val-n-bits - n-shift-bits + val n-shift-bits = amount % 32 + val n-shift-words = amount / 32 + val n-rev-shift-bits = 32 - n-shift-bits val is-zero-carry = n-shift-bits == 0 for i in 0 to n-shift-words do : d[nw - i - 1] = 0 @@ -331,14 +298,14 @@ public defn shift-right (b:BigInt, n:Int) -> BigInt : rsh!(BigInt(length(b)), b, public defn lsh! (d:BigInt, s0:BigInt, amount:Int) : ;; println-all(["LSH " s0 " AMOUNT " amount " INTO BIGINT<" length(d) ">"]) - val n-shift-bits = amount % val-n-bits - val n-shift-words = amount / val-n-bits - val n-rev-shift-bits = val-n-bits - n-shift-bits + val n-shift-bits = amount % 32 + val n-shift-words = amount / 32 + val n-rev-shift-bits = 32 - n-shift-bits val is-zero-carry = n-shift-bits == 0 for i in 0 to num-words(d) do : d[i] = 0 var carry = 0; - ;; println-all(["LSH AMOUNT " amount " VNB " val-n-bits " NSB " n-shift-bits " NSW " n-shift-words " NRSB " n-rev-shift-bits]) + ;; println-all(["LSH AMOUNT " amount " VNB " 32 " NSB " n-shift-bits " NSW " n-shift-words " NRSB " n-rev-shift-bits]) for i in 0 to (num-words(d) - n-shift-words) do : val x = if i >= num-words(s0) : 0 else: s0[i] ;; println-all([" SHIFTING " (i + n-shift-words) " VAL " (x << n-shift-bits)]) @@ -410,15 +377,15 @@ defn check (msg:String, x:BigInt) : ;; check("B< ", BigIntLit(5, 3) << 10, BigIntLit(5 << 1, 13)) ;; check("B< ", BigIntLit(5, 3) << 32, BigIntLit(5 << 1, 38)) ;; check("B< ", BigIntLit("b1010") << 1, BigIntLit(10 << 1, 5)) -;check("S1 ", BigIntLit("xfafa") << 16, BigIntLit("xfafa0000", 32)) -;;; check("B< ", BigIntLit(5, 3) << 64, BigIntLit(5 << 1, 67)) -;;; check("BN ", neg(BigIntLit(2, 8)), BigIntLit(-2, 8)) -;check("S2 ", BigIntLit("b11111010") << 8, BigIntLit("b1111101000000000", 16)) -;check("C1 ", cat(BigIntLit("b11111010", 8), BigIntLit("b10111100", 8)), BigIntLit("b1111101010111100", 16)) -;check("C3 ", cat(cat(BigIntLit("b1111"), BigIntLit("b1010")), cat(BigIntLit("b1011"), BigIntLit("b1100"))), BigIntLit("b1111101010111100", 16)) -;check("C4 ", cat([BigIntLit("b1111"), BigIntLit("b1010"), BigIntLit("b1011"), BigIntLit("b1100")]), BigIntLit("b1111101010111100", 16)) -;check("C5 ", BigIntLit("b101111001"), BigIntLit("b101111001")) -;check("C6 ", cat(BigIntLit("b1"), BigIntLit("b01111001")), BigIntLit("b101111001")) -;check("C7 ", cat(BigIntLit("b11101"), BigIntLit("b101111001")), BigIntLit("b11101101111001")) -;check("C8 ", cat([BigIntLit("b11"), BigIntLit("b101"), BigIntLit("b1011"), BigIntLit("b11001")]), BigIntLit("b11101101111001")) -;check("C0 ", bits(BigIntLit("b11101101111001"), 10, 1), BigIntLit("b0110111100")) +check("S1 ", BigIntLit("xfafa") << 16, BigIntLit("xfafa0000", 32)) +;; check("B< ", BigIntLit(5, 3) << 64, BigIntLit(5 << 1, 67)) +;; check("BN ", neg(BigIntLit(2, 8)), BigIntLit(-2, 8)) +check("S2 ", BigIntLit("b11111010") << 8, BigIntLit("b1111101000000000", 16)) +check("C1 ", cat(BigIntLit("b11111010", 8), BigIntLit("b10111100", 8)), BigIntLit("b1111101010111100", 16)) +check("C3 ", cat(cat(BigIntLit("b1111"), BigIntLit("b1010")), cat(BigIntLit("b1011"), BigIntLit("b1100"))), BigIntLit("b1111101010111100", 16)) +check("C4 ", cat([BigIntLit("b1111"), BigIntLit("b1010"), BigIntLit("b1011"), BigIntLit("b1100")]), BigIntLit("b1111101010111100", 16)) +check("C5 ", BigIntLit("b101111001"), BigIntLit("b101111001")) +check("C6 ", cat(BigIntLit("b1"), BigIntLit("b01111001")), BigIntLit("b101111001")) +check("C7 ", cat(BigIntLit("b11101"), BigIntLit("b101111001")), BigIntLit("b11101101111001")) +check("C8 ", cat([BigIntLit("b11"), BigIntLit("b101"), BigIntLit("b1011"), BigIntLit("b11001")]), BigIntLit("b11101101111001")) +check("C0 ", bits(BigIntLit("b11101101111001"), 10, 1), BigIntLit("b0110111100")) diff --git a/src/main/stanza/firrtl-lexer.stanza b/src/main/stanza/firrtl-lexer.stanza index 8ee90f68..7581b26c 100644 --- a/src/main/stanza/firrtl-lexer.stanza +++ b/src/main/stanza/firrtl-lexer.stanza @@ -287,14 +287,14 @@ defn eat-number () : match(to-float(str)) : (f:Float) : token-eaten(Token(f, info)) (f:False) : throw(InvalidNumber(info)) - else : - token-eaten(Token(BigIntLit(str),info)) + else : token-eaten(Token(to-int(str), info)) + ;else : token-eaten(Token(BigIntLit(str),info)) + ;else : ;match(to-long(str)) : ; (l:Long) : ; if l < (to-long("2147483647") as Long) and l > (to-long("-2147483648") as Long) : token-eaten(Token(to-int(str), info)) ; else : token-eaten(Token(l, info)) ; (l:False) : token-eaten(Token(to-int(str), info)) - ;else : token-eaten(Token(to-int(str), info)) <- ADAM CHANGE, FROM THIS defn eat-here-string () : if EATER[0] == '\\' and EATER[1] == '<' : diff --git a/src/main/stanza/firrtl-test-main.stanza b/src/main/stanza/firrtl-test-main.stanza index a5050c47..9762966b 100644 --- a/src/main/stanza/firrtl-test-main.stanza +++ b/src/main/stanza/firrtl-test-main.stanza @@ -3,6 +3,7 @@ #include<"compiler/stz-algorithms.stanza"> #include<"compiler/stz-parser.stanza"> #include<"compiler/stz-lexer.stanza"> +#include("bigint.stanza") #include("firrtl-lexer.stanza") #include("firrtl-ir.stanza") #include("ir-utils.stanza") @@ -13,7 +14,6 @@ #include("compilers.stanza") #include("flo.stanza") #include("verilog.stanza") -#include("bigint.stanza") ;Custom Packages #include("custom-passes.stanza") diff --git a/src/main/stanza/ir-parser.stanza b/src/main/stanza/ir-parser.stanza index 44b51f30..b0ab8652 100644 --- a/src/main/stanza/ir-parser.stanza +++ b/src/main/stanza/ir-parser.stanza @@ -82,6 +82,9 @@ defsyntax firrtl : int = (?x) when unwrap-token(x) typeof Int : unwrap-token(x) + string = (?x) when unwrap-token(x) typeof String : + unwrap-token(x) + ;Parses next form if long literal intorlong = (?x) when unwrap-token(x) typeof Int|Long : unwrap-token(x) @@ -90,9 +93,6 @@ defsyntax firrtl : sym = (?x) when unwrap-token(x) typeof Symbol : unwrap-token(x) - bigint = (?x) when unwrap-token(x) typeof BigInt : - unwrap-token(x) - ;Error Handling Productions defrule : ;Error if not an identifier @@ -111,10 +111,6 @@ defsyntax firrtl : =! = (=) : `= =! != () : FPE(form, "Expected a '=' here.") - ;Error if not a single bigint - bigint$ = (?i:#bigint ?rest ...) when empty?(rest) : i - bigint$ != () : FPE(form, "Expected a single big integer literal here.") - ;Error if not a single integer int$ = (?i:#int ?rest ...) when empty?(rest) : i int$ != () : FPE(form, "Expected a single integer literal here.") @@ -199,7 +195,7 @@ defsyntax firrtl : type = (?t:#typeterm ?ops:#typeop ...) : apply-suffix-ops(t, ops) type = (?t:#clktype) : t - typeop = ((@get ?size:#bigint$)) : (fn (t) : VectorType(t, size[0])) + typeop = ((@get ?size:#int$)) : (fn (t) : VectorType(t, size[0])) typeterm = (?t:#inttype) : t typeterm = ({?fs:#field ... ?rest ...}) : @@ -218,7 +214,7 @@ defsyntax firrtl : accdir = (rdwr) : RDWR defrule width : - width = (?x:#bigint) : + width = (?x:#int) : if num-words(x) == 1 : IntWidth(x[0]) else if num-words(x) == 2 : LongWidth(to-long(x[1]) * to-long(1 << 32) + to-long(x[0])) else : IntWidth(x[0]) @@ -261,16 +257,21 @@ defsyntax firrtl : defrule exp : ;Suffix Operators exp = (?x:#expterm ?ops:#expop ...) : apply-suffix-ops(x, ops) - expop = ((@get ?f:#bigint)) : (fn (x) : Index(x, f[0], UnknownType())) + expop = ((@get ?f:#int)) : (fn (x) : Index(x, f[0], UnknownType())) expop = (. ?f:#id!) : (fn (x) : Subfield(x, f, UnknownType())) ;Prefix Operators - expterm = (?t:#inttype(?v:#bigint$)) : + expterm = (?t:#inttype(?v:#string)) : + match(t) : + (t:UIntType) : UIntValue(BigIntLit(v as String), width(t)) + (t:SIntType) : SIntValue(BigIntLit(v as String), width(t)) + + expterm = (?t:#inttype(?v:#int$)) : match(t) : - (t:UIntType) : UIntValue(v, width(t)) - (t:SIntType) : SIntValue(v, width(t)) + (t:UIntType) : UIntValue(BigIntLit(abs(v as Int)), width(t)) + (t:SIntType) : SIntValue(BigIntLit(v as Int), width(t)) - expterm = (?op:#sym(?es:#exp ... ?ints:#bigint ... ?rest ...)) : + expterm = (?op:#sym(?es:#exp ... ?ints:#int ... ?rest ...)) : if not empty?(rest) : FPE(rest, "Illegal operands to primitive operator.") match(primop(op)) : diff --git a/src/main/stanza/verilog.stanza b/src/main/stanza/verilog.stanza index d39c89e4..ca47170b 100644 --- a/src/main/stanza/verilog.stanza +++ b/src/main/stanza/verilog.stanza @@ -65,8 +65,14 @@ defn emit-signed-if-any (e:Expression,ls:List<Expression>) -> String : defn emit (e:Expression) -> String : match(e) : (e:Ref) : to-string $ name(e) - (e:UIntValue) : string-join $ [width!(type(e)) "'" value(e)] - (e:SIntValue) : string-join $ [width!(type(e)) "'s" value(e)] + (e:UIntValue) : + val str = to-string(value(e)) + val out = substring(str,1,length(str) - 1) + string-join $ [width!(type(e)) "'" out] + (e:SIntValue) : ;string-join $ [width!(type(e)) "'s" value(e)] + val str = to-string(value(e)) + val out = substring(str,1,length(str) - 1) + string-join $ [width!(type(e)) "'s" out] (e:Subfield) : error("Non-supported expression") (e:Index) : error("Non-supported expression") (e:DoPrim) : diff --git a/test/chisel3/Test.fir b/test/chisel3/Test.fir index aea7acde..1a39b93a 100644 --- a/test/chisel3/Test.fir +++ b/test/chisel3/Test.fir @@ -3,7 +3,10 @@ circuit Test : module Test : - wire x : UInt<10> - x := UInt(5151) - x := UInt(515151512512412414124124124124) + wire x : UInt + x := UInt(0) + x := UInt(1) + x := UInt(10) + x := UInt(21474836) + x := UInt("h21474836") |
