aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorazidar2015-08-26 15:07:12 -0700
committerazidar2015-08-26 15:07:53 -0700
commitb6bf5ee9b29a117c1fcb3b7ec19ce1ce07132ffd (patch)
treec65e8d722c77fbbaa42c4b3d98e3d0ba6cdb9fca
parentcf1fe102a99efee192288061849165072c699c2e (diff)
Fixed bug where firrtl was incorrectly judging the width of a bigint. #36 #37.
-rw-r--r--src/main/stanza/bigint2.stanza36
-rw-r--r--src/main/stanza/errors.stanza4
-rw-r--r--src/main/stanza/ir-parser.stanza21
-rw-r--r--src/main/stanza/ir-utils.stanza8
-rw-r--r--src/main/stanza/passes.stanza4
-rw-r--r--test/errors/width/Conservative.fir6
-rw-r--r--test/errors/width/SmallWidth.fir3
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 :