From 7b93b0f8c48e39cc9730cf9f91340cf733dadafe Mon Sep 17 00:00:00 2001 From: Chick Markley Date: Fri, 18 Oct 2019 19:44:08 -0700 Subject: Interval Data Type Support for Chisel (#1210) Plan to be released with 3.3. Breaks experimental Range API. Adds new Interval type and associated support. This commit adds the following: - Renamed Range to IntervalRange to avoid name collision with scala Range - Changed RangeTransform macro to Return an IntervalRange - Improved error messages on missing comma or decimal - Added notational support for binary point - Some formatting cleanup also - SIntFactory - Change to use IntervalRange API - UIntFactory - UInt from range has custom width computation - It does not need to deal with lowerbound extending bit requirements - Code to handle special case of range"[0,0]" to have a width of 1 - IR.scala - Removed Bound and other constraint code that was duplicating firrtl stuff - Added new RangeType - Added IntervalRange class and object - RangeSpec - modified just a bit to handle notational differences - previous range interpolator returned tuple now returns IntervalRange - Add IntervalType to emitter - Added IntervalSpec with many tests - Added ScalaIntervalSimulatorSpec which tests golden model for Interval - Added ScalaIntervalSimulator which is a golden model for Interval - This gold may not have been polished to a high sheen - Add IntervalLit cases to Converter - Add Interval PrimOps to IR - asInterval, wrap, squz, clip, setp, decp, incp - Add IntervalLit class to IR - Add Interval to MonoConnect - Add Interval Type to Bits (in experimental package) - add conversions to Interval from other types - Add Interval clone stuff to Data - Add Literal creation helpers to chisel3 package - these may move to experimental if I can figure that out--- .../src/main/scala/chisel3/package.scala | 222 +++++++++++---------- 1 file changed, 122 insertions(+), 100 deletions(-) (limited to 'chiselFrontend/src/main/scala/chisel3/package.scala') diff --git a/chiselFrontend/src/main/scala/chisel3/package.scala b/chiselFrontend/src/main/scala/chisel3/package.scala index 51bcf1fe..3af21d57 100644 --- a/chiselFrontend/src/main/scala/chisel3/package.scala +++ b/chiselFrontend/src/main/scala/chisel3/package.scala @@ -1,118 +1,140 @@ // See LICENSE for license details. +import chisel3.internal.firrtl.BinaryPoint + /** This package contains the main chisel3 API. */ package object chisel3 { // scalastyle:ignore package.object.name import internal.firrtl.{Port, Width} - import internal.sourceinfo.{SourceInfo, VecTransform} - import internal.{Builder, chiselRuntimeDeprecated} + import internal.Builder import scala.language.implicitConversions - /** - * These implicit classes allow one to convert scala.Int|scala.BigInt to - * Chisel.UInt|Chisel.SInt by calling .asUInt|.asSInt on them, respectively. - * The versions .asUInt(width)|.asSInt(width) are also available to explicitly - * mark a width for the new literal. - * - * Also provides .asBool to scala.Boolean and .asUInt to String - * - * Note that, for stylistic reasons, one should avoid extracting immediately - * after this call using apply, ie. 0.asUInt(1)(0) due to potential for - * confusion (the 1 is a bit length and the 0 is a bit extraction position). - * Prefer storing the result and then extracting from it. - * - * Implementation note: the empty parameter list (like `U()`) is necessary to prevent - * interpreting calls that have a non-Width parameter as a chained apply, otherwise things like - * `0.asUInt(16)` (instead of `16.W`) compile without error and produce undesired results. - */ - implicit class fromBigIntToLiteral(bigint: BigInt) { - /** Int to Bool conversion, allowing compact syntax like 1.B and 0.B - */ - def B: Bool = bigint match { // scalastyle:ignore method.name - case bigint if bigint == 0 => Bool.Lit(false) - case bigint if bigint == 1 => Bool.Lit(true) - case bigint => Builder.error(s"Cannot convert $bigint to Bool, must be 0 or 1"); Bool.Lit(false) - } - /** Int to UInt conversion, recommended style for constants. - */ - def U: UInt = UInt.Lit(bigint, Width()) // scalastyle:ignore method.name - /** Int to SInt conversion, recommended style for constants. - */ - def S: SInt = SInt.Lit(bigint, Width()) // scalastyle:ignore method.name - /** Int to UInt conversion with specified width, recommended style for constants. - */ - def U(width: Width): UInt = UInt.Lit(bigint, width) // scalastyle:ignore method.name - /** Int to SInt conversion with specified width, recommended style for constants. - */ - def S(width: Width): SInt = SInt.Lit(bigint, width) // scalastyle:ignore method.name - - /** Int to UInt conversion, recommended style for variables. - */ - def asUInt(): UInt = UInt.Lit(bigint, Width()) - /** Int to SInt conversion, recommended style for variables. - */ - def asSInt(): SInt = SInt.Lit(bigint, Width()) - /** Int to UInt conversion with specified width, recommended style for variables. - */ - def asUInt(width: Width): UInt = UInt.Lit(bigint, width) - /** Int to SInt conversion with specified width, recommended style for variables. - */ - def asSInt(width: Width): SInt = SInt.Lit(bigint, width) - } + /** + * These implicit classes allow one to convert scala.Int|scala.BigInt to + * Chisel.UInt|Chisel.SInt by calling .asUInt|.asSInt on them, respectively. + * The versions .asUInt(width)|.asSInt(width) are also available to explicitly + * mark a width for the new literal. + * + * Also provides .asBool to scala.Boolean and .asUInt to String + * + * Note that, for stylistic reasons, one should avoid extracting immediately + * after this call using apply, ie. 0.asUInt(1)(0) due to potential for + * confusion (the 1 is a bit length and the 0 is a bit extraction position). + * Prefer storing the result and then extracting from it. + * + * Implementation note: the empty parameter list (like `U()`) is necessary to prevent + * interpreting calls that have a non-Width parameter as a chained apply, otherwise things like + * `0.asUInt(16)` (instead of `16.W`) compile without error and produce undesired results. + */ + implicit class fromBigIntToLiteral(bigint: BigInt) { + /** Int to Bool conversion, allowing compact syntax like 1.B and 0.B + */ + def B: Bool = bigint match { // scalastyle:ignore method.name + case bigint if bigint == 0 => Bool.Lit(false) + case bigint if bigint == 1 => Bool.Lit(true) + case bigint => Builder.error(s"Cannot convert $bigint to Bool, must be 0 or 1"); Bool.Lit(false) + } + /** Int to UInt conversion, recommended style for constants. + */ + def U: UInt = UInt.Lit(bigint, Width()) // scalastyle:ignore method.name + /** Int to SInt conversion, recommended style for constants. + */ + def S: SInt = SInt.Lit(bigint, Width()) // scalastyle:ignore method.name + /** Int to UInt conversion with specified width, recommended style for constants. + */ + def U(width: Width): UInt = UInt.Lit(bigint, width) // scalastyle:ignore method.name + /** Int to SInt conversion with specified width, recommended style for constants. + */ + def S(width: Width): SInt = SInt.Lit(bigint, width) // scalastyle:ignore method.name - implicit class fromIntToLiteral(int: Int) extends fromBigIntToLiteral(int) - implicit class fromLongToLiteral(long: Long) extends fromBigIntToLiteral(long) - - implicit class fromStringToLiteral(str: String) { - /** String to UInt parse, recommended style for constants. - */ - def U: UInt = str.asUInt() // scalastyle:ignore method.name - /** String to UInt parse with specified width, recommended style for constants. - */ - def U(width: Width): UInt = str.asUInt(width) // scalastyle:ignore method.name - - /** String to UInt parse, recommended style for variables. - */ - def asUInt(): UInt = { - val bigInt = parse(str) - UInt.Lit(bigInt, Width(bigInt.bitLength max 1)) - } - /** String to UInt parse with specified width, recommended style for variables. - */ - def asUInt(width: Width): UInt = UInt.Lit(parse(str), width) - - protected def parse(n: String) = { - val (base, num) = n.splitAt(1) - val radix = base match { - case "x" | "h" => 16 - case "d" => 10 - case "o" => 8 - case "b" => 2 - case _ => Builder.error(s"Invalid base $base"); 2 - } - BigInt(num.filterNot(_ == '_'), radix) - } - } + /** Int to UInt conversion, recommended style for variables. + */ + def asUInt(): UInt = UInt.Lit(bigint, Width()) + /** Int to SInt conversion, recommended style for variables. + */ + def asSInt(): SInt = SInt.Lit(bigint, Width()) + /** Int to UInt conversion with specified width, recommended style for variables. + */ + def asUInt(width: Width): UInt = UInt.Lit(bigint, width) + /** Int to SInt conversion with specified width, recommended style for variables. + */ + def asSInt(width: Width): SInt = SInt.Lit(bigint, width) + } - implicit class fromBooleanToLiteral(boolean: Boolean) { - /** Boolean to Bool conversion, recommended style for constants. - */ - def B: Bool = Bool.Lit(boolean) // scalastyle:ignore method.name + implicit class fromIntToLiteral(int: Int) extends fromBigIntToLiteral(int) + implicit class fromLongToLiteral(long: Long) extends fromBigIntToLiteral(long) - /** Boolean to Bool conversion, recommended style for variables. - */ - def asBool(): Bool = Bool.Lit(boolean) + implicit class fromStringToLiteral(str: String) { + /** String to UInt parse, recommended style for constants. + */ + def U: UInt = str.asUInt() // scalastyle:ignore method.name + /** String to UInt parse with specified width, recommended style for constants. + */ + def U(width: Width): UInt = str.asUInt(width) // scalastyle:ignore method.name + + /** String to UInt parse, recommended style for variables. + */ + def asUInt(): UInt = { + val bigInt = parse(str) + UInt.Lit(bigInt, Width(bigInt.bitLength max 1)) + } + /** String to UInt parse with specified width, recommended style for variables. + */ + def asUInt(width: Width): UInt = UInt.Lit(parse(str), width) + + protected def parse(n: String): BigInt = { + val (base, num) = n.splitAt(1) + val radix = base match { + case "x" | "h" => 16 + case "d" => 10 + case "o" => 8 + case "b" => 2 + case _ => Builder.error(s"Invalid base $base"); 2 } + BigInt(num.filterNot(_ == '_'), radix) + } + } - // Fixed Point is experimental for now, but we alias the implicit conversion classes here - // to minimize disruption with existing code. - implicit class fromDoubleToLiteral(double: Double) extends experimental.FixedPoint.Implicits.fromDoubleToLiteral(double) - implicit class fromIntToBinaryPoint(int: Int) extends experimental.FixedPoint.Implicits.fromIntToBinaryPoint(int) + implicit class fromIntToBinaryPoint(int: Int) { + def BP: BinaryPoint = BinaryPoint(int) // scalastyle:ignore method.name + } - implicit class fromIntToWidth(int: Int) { - def W: Width = Width(int) // scalastyle:ignore method.name - } + implicit class fromBooleanToLiteral(boolean: Boolean) { + /** Boolean to Bool conversion, recommended style for constants. + */ + def B: Bool = Bool.Lit(boolean) // scalastyle:ignore method.name + + /** Boolean to Bool conversion, recommended style for variables. + */ + def asBool(): Bool = Bool.Lit(boolean) + } + + // Fixed Point is experimental for now, but we alias the implicit conversion classes here + // to minimize disruption with existing code. + implicit class fromDoubleToLiteral(double: Double) + extends experimental.FixedPoint.Implicits.fromDoubleToLiteral(double) + + // Interval is experimental for now, but we alias the implicit conversion classes here + // to minimize disruption with existing code. + implicit class fromIntToLiteralInterval(int: Int) + extends experimental.Interval.Implicits.fromIntToLiteralInterval(int) + + implicit class fromLongToLiteralInterval(long: Long) + extends experimental.Interval.Implicits.fromLongToLiteralInterval(long) + + implicit class fromBigIntToLiteralInterval(bigInt: BigInt) + extends experimental.Interval.Implicits.fromBigIntToLiteralInterval(bigInt) + + implicit class fromDoubleToLiteralInterval(double: Double) + extends experimental.Interval.Implicits.fromDoubleToLiteralInterval(double) + + implicit class fromBigDecimalToLiteralInterval(bigDecimal: BigDecimal) + extends experimental.Interval.Implicits.fromBigDecimalToLiteralInterval(bigDecimal) + + implicit class fromIntToWidth(int: Int) { + def W: Width = Width(int) // scalastyle:ignore method.name + } val WireInit = WireDefault -- cgit v1.2.3