diff options
| author | azidar | 2015-08-26 15:07:12 -0700 |
|---|---|---|
| committer | azidar | 2015-08-26 15:07:53 -0700 |
| commit | b6bf5ee9b29a117c1fcb3b7ec19ce1ce07132ffd (patch) | |
| tree | c65e8d722c77fbbaa42c4b3d98e3d0ba6cdb9fca | |
| parent | cf1fe102a99efee192288061849165072c699c2e (diff) | |
Fixed bug where firrtl was incorrectly judging the width of a bigint. #36 #37.
| -rw-r--r-- | src/main/stanza/bigint2.stanza | 36 | ||||
| -rw-r--r-- | src/main/stanza/errors.stanza | 4 | ||||
| -rw-r--r-- | src/main/stanza/ir-parser.stanza | 21 | ||||
| -rw-r--r-- | src/main/stanza/ir-utils.stanza | 8 | ||||
| -rw-r--r-- | src/main/stanza/passes.stanza | 4 | ||||
| -rw-r--r-- | test/errors/width/Conservative.fir | 6 | ||||
| -rw-r--r-- | test/errors/width/SmallWidth.fir | 3 |
7 files changed, 65 insertions, 17 deletions
diff --git a/src/main/stanza/bigint2.stanza b/src/main/stanza/bigint2.stanza index 64c587ee..bc2e9f36 100644 --- a/src/main/stanza/bigint2.stanza +++ b/src/main/stanza/bigint2.stanza @@ -17,15 +17,27 @@ defn as-digit (c: Char) -> Int : defn num-words (b:BigInt) : length(d(b)) +defn shamt (c:Char) : + if c == 'b': 1 + else if c == 'h': 4 + else: error("Unsupported BigInt base.") + defn req-words (num-bits:Int) : (num-bits + word-size - 1) / word-size defn to-hex (b:BigInt) -> String : defn as-hex (i: Int) -> String : substring(all-digits,i,i + 1) var li = List<String>() + val tib = num-bits(b) % 4 for i in 0 to num-bits(b) by 4 do : val word-index = i / 32 val bit-index = i % 32 - val digit = (d(b)[word-index] >> (bit-index)) & 15 + var mask = 15 + + val digit = + if (i + tib) == num-bits(b) : + (d(b)[word-index] >> bit-index) & (pow(2,tib) - 1) + else : + (d(b)[word-index] >> bit-index) & 15 li = List(as-hex(digit),li) var saw-not-zero? = false val li* = Vector<String>() @@ -93,6 +105,16 @@ public defmethod to-string (b:BigInt) : to-hex(b) public defmethod print (o:OutputStream, b:BigInt) : print(o, to-string(b)) +public defn req-num-bits (b:BigInt) -> Int : + var msb = 0 + var seen? = false + for i in 0 to num-bits(b) do : + val index = num-bits(b) - 1 - i + if b[index] != 0 and seen? == false : + msb = index + seen? = true + msb + 1 + public defn BigIntZero (num-bits:Int) -> BigInt : val num-words = (num-bits + word-size - 1) / word-size val d = Array<Int>(num-words) @@ -109,19 +131,17 @@ public defn BigIntLit (data:Int, num-bits:Int) -> BigInt : b public defn BigIntLit (data:String) -> BigInt : - val base = data[0] - val shamt = if base == 'b': 1 else if base == 'h': 4 else: error("Unsupported BigInt base.") - val digits = substring(data, 1) - val num-bits = length(digits) * shamt - BigIntLit(digits,shamt,num-bits) + val num-bits = (length(data) - 1) * shamt(data[0]) + BigIntLit(data,num-bits) -public defn BigIntLit (digits:String, shamt:Int, num-bits:Int) -> BigInt : +public defn BigIntLit (data:String, num-bits:Int) -> BigInt : val lit = BigIntZero(num-bits) + val digits = substring(data, 1) ;; println-all(["BASE " base " SHAMT " shamt " DIGITS " digits]) for i in 0 to num-words(lit) do : d(lit)[i] = 0 for i in 0 to length(digits) do : - val off = (length(digits) - 1 - i) * shamt + val off = (length(digits) - 1 - i) * shamt(data[0]) val wi = off / word-size val bi = off % word-size d(lit)[wi] = d(lit)[wi] | (as-digit(digits[i]) << bi) diff --git a/src/main/stanza/errors.stanza b/src/main/stanza/errors.stanza index fd3dfc2a..69073f9f 100644 --- a/src/main/stanza/errors.stanza +++ b/src/main/stanza/errors.stanza @@ -918,14 +918,14 @@ public defn check-width (c:Circuit) -> Circuit : (e:UIntValue) : match(width(e)) : (w:LongWidth) : - if max(to-long(1),to-long(num-bits(value(e)) - 1)) > width(w) : + if max(to-long(1),to-long(req-num-bits(value(e)) - 1)) > width(w) : add(errors,WidthTooSmall(info,to-string(value(e)))) (w) : add(errors,UninferredWidth(info)) check-width-w(info,width(e)) (e:SIntValue) : match(width(e)) : (w:LongWidth) : - if to-long(num-bits(value(e))) > width(w) : + if to-long(req-num-bits(value(e))) > width(w) : add(errors,WidthTooSmall(info,to-string(value(e)))) (w) : add(errors,UninferredWidth(info)) check-width-w(info,width(e)) diff --git a/src/main/stanza/ir-parser.stanza b/src/main/stanza/ir-parser.stanza index d3d9c379..f81777f5 100644 --- a/src/main/stanza/ir-parser.stanza +++ b/src/main/stanza/ir-parser.stanza @@ -277,9 +277,24 @@ defsyntax firrtl : ;Prefix Operators expterm = (?t:#inttype(?v:#string)) : + val b = BigIntLit(v as String) match(t) : - (t:UIntType) : UIntValue(BigIntLit(v as String), width(t)) - (t:SIntType) : SIntValue(BigIntLit(v as String), width(t)) + (t:UIntType) : + match(width(t)) : + (w:LongWidth) : + if to-long(max(1,(req-num-bits(b) - 1))) > width(w) : + FPE(form, "Width too small for UIntValue.") + UIntValue(b, w) + (w) : + UIntValue(b, w) + (t:SIntType) : + match(width(t)) : + (w:LongWidth) : + if to-long(req-num-bits(b)) > width(w) : + FPE(form, "Width too small for SIntValue.") + SIntValue(b, w) + (w) : + SIntValue(b, w) expterm = (?t:#inttype(?v:#int$)) : match(t) : @@ -288,7 +303,7 @@ defsyntax firrtl : FPE(form, "UIntValue cannot be negative.") match(width(t)) : (w:LongWidth) : - UIntValue(BigIntLit(v as Int,to-int(width(w))),w) + UIntValue(BigIntLit(v as Int,to-int(width(w)) + 1),w) (w) : val num-bits = req-num-bits(v as Int) UIntValue(BigIntLit(v as Int,num-bits), LongWidth(max(1,num-bits - 1))) diff --git a/src/main/stanza/ir-utils.stanza b/src/main/stanza/ir-utils.stanza index 0c3140ed..a234ff81 100644 --- a/src/main/stanza/ir-utils.stanza +++ b/src/main/stanza/ir-utils.stanza @@ -500,6 +500,14 @@ public defn merge!<?K,?V> (a:HashTable<?K,?V>, b:HashTable<K,V>) : for e in b do : a[key(e)] = value(e) +public defn pow (x:Int,y:Int) -> Int : + var x* = 1 + var y* = y + while y* != 0 : + x* = times(x*,x) + y* = minus(y*,1) + x* + public defn pow (x:Long,y:Long) -> Long : var x* = to-long(1) var y* = y diff --git a/src/main/stanza/passes.stanza b/src/main/stanza/passes.stanza index 8a03fb10..fead9ac2 100644 --- a/src/main/stanza/passes.stanza +++ b/src/main/stanza/passes.stanza @@ -1983,14 +1983,14 @@ defn gen-constraints (m:Module, h:HashTable<Symbol,Type>, v:Vector<WGeq>) -> Mod match(width(e)) : (w:UnknownWidth) : val w* = VarWidth(firrtl-gensym(`w,width-name-hash)) - add(v,WGeq(w*,LongWidth(max(1,num-bits(value(e)) - 1)))) + add(v,WGeq(w*,LongWidth(max(1,req-num-bits(value(e)) - 1)))) UIntValue(value(e),w*) (w) : e (e:SIntValue) : match(width(e)) : (w:UnknownWidth) : val w* = VarWidth(firrtl-gensym(`w,width-name-hash)) - add(v,WGeq(w*,LongWidth(num-bits(value(e))))) + add(v,WGeq(w*,LongWidth(req-num-bits(value(e))))) SIntValue(value(e),w*) (w) : e (e) : e diff --git a/test/errors/width/Conservative.fir b/test/errors/width/Conservative.fir new file mode 100644 index 00000000..43aa648f --- /dev/null +++ b/test/errors/width/Conservative.fir @@ -0,0 +1,6 @@ +; RUN: firrtl -i %s -o %s.v -X verilog -p ciwT 2>&1 | tee %s.out | FileCheck %s +; CHECK: Width too small for UIntValue. + +circuit Top : + module Top : + node bar = UInt<1>("h1111") diff --git a/test/errors/width/SmallWidth.fir b/test/errors/width/SmallWidth.fir index 9e26699e..0ee60ec0 100644 --- a/test/errors/width/SmallWidth.fir +++ b/test/errors/width/SmallWidth.fir @@ -1,6 +1,5 @@ ; RUN: firrtl -i %s -o %s.v -X verilog -p ciwT 2>&1 | tee %s.out | FileCheck %s -; CHECK: Width too small for constant "h121". -; CHECK: Width too small for constant "h13333". +; CHECK: Width too small for UIntValue. circuit Top : module Top : |
