diff --git a/.gitignore b/.gitignore index 31c614f2..e1b65df5 100644 --- a/.gitignore +++ b/.gitignore @@ -14,3 +14,5 @@ test-reports/ *.new *~ /eclipse.bin +/ucli.key +/cpp diff --git a/ChangeLog b/ChangeLog index 86fa7fb4..291b8fe9 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,14 +1,4 @@ -ChangeLog for Chisel v2.2.25 3/25/2015 +ChangeLog for Chisel v2.2.38 -Detect and issue an error for double Module() wrapping - #385 -Fix Data width lost in Vec #384. -For test, use JUnitSuite over AssertionsForJUnit -In Verilog, fix bug for similar modules, some not emitted -Better Namespace conflict resolution for Verilog -Fix for multiply instantiated modules in Chisel result in redundant (functionally equivalent) module definitions in generated Verilog #374 -In CPP, better detection of signals to randomize -Disallow comparisons between Nodes and non-Nodes -Include type of missing Parameter in error message -Address issue with width-inference of right-shift -Update emulator_{api,mod}.h to eliminate C++ compiler warnings. -Update README to reflect current build procedure. +Move {as,to}{U,S}Int definitions to Node.scala, and add them as Bundle key words. +Update deprecated Fill() usage in FillApp.scala. diff --git a/Makefile b/Makefile index 6485dc12..26fc1af5 100644 --- a/Makefile +++ b/Makefile @@ -1,23 +1,34 @@ +# Retain all intermediate files. +.SECONDARY: + SBT ?= sbt SBT_FLAGS ?= -Dsbt.log.noformat=true RM_DIRS := test-outputs test-reports -CLEAN_DIRS := doc +CLEAN_DIRS := SRC_DIR ?= . -SYSTEMC ?= $(SRC_DIR)/../../systemc/systemc-2.3.1 +#SYSTEMC ?= $(SRC_DIR)/../../systemc/systemc-2.3.1 +SYSCTESTS ?= $(addsuffix .sysctest,$(notdir $(basename $(wildcard $(SRC_DIR)/src/test/scala/SysCTest/*.scala)))) CHISEL_JAR ?= $(SRC_DIR)/target/scala-2.10/chisel_2.10-2.3-SNAPSHOT.jar -DRIVER ?= $(SRC_DIR)/src/test/resources/AddFilterSysCdriver.cpp TEST_OUTPUT_DIR ?= ./test-outputs -.PHONY: smoke publish-local check clean jenkins-build sysctest coverage test +.PHONY: smoke publish-local check clean jenkins-build sysctest coverage scaladoc test compile style + +SMOKE_TESTS ?= StdlibSuite default: publish-local -smoke: +compile: $(SBT) $(SBT_FLAGS) compile publish-local: - $(SBT) $(SBT_FLAGS) publish-local + $(SBT) $(SBT_FLAGS) +publish-local + +smoke: + $(SBT) $(SBT_FLAGS) "test-only $(SMOKE_TESTS) -- -l org.scalatest.tags.Slow" + +style: + $(SBT) $(SBT_FLAGS) scalastyle test:scalastyle check test: $(SBT) $(SBT_FLAGS) test @@ -31,6 +42,9 @@ clean: for dir in $(CLEAN_DIRS); do $(MAKE) -C $$dir clean; done $(RM) -r $(RM_DIRS) +scaladoc: + $(SBT) $(SBT_FLAGS) doc test:doc + # Start off clean, then run tests for all supported configurations, and publish those versions of the code. # Then run coverage and style tests (for developer's use). # Don't publish the coverage test code since it contains hooks/references to the coverage test package @@ -42,20 +56,28 @@ jenkins-build: clean $(SBT) $(SBT_FLAGS) scalastyle coverage test $(SBT) $(SBT_FLAGS) coverageReport -sysctest: - mkdir -p $(TEST_OUTPUT_DIR) - $(MAKE) -C $(TEST_OUTPUT_DIR) -f ../Makefile SRC_DIR=.. syscbuildandruntest +.PHONY: SYSCDIR + +SYSCDIR: + @if [ -z "$(SYSTEMC)" ]; then echo "Please define SYSTEMC (the root of the systemc distribution) in your environment"; exit 1; fi + @if [ ! -d "$(SYSTEMC)" ]; then echo "SYSTEMC isn't a valid directory - $(SYSTEMC)"; exit 1; fi -syscbuildandruntest: AddFilter - ./AddFilter +sysctests: $(SYSCTESTS) SYSCDIR + +sysctest: $(firstword $(SYSCTESTS)) SYSCDIR + +%.sysctest: + mkdir -p $(TEST_OUTPUT_DIR) + $(MAKE) -C $(TEST_OUTPUT_DIR) -f ../Makefile SRC_DIR=.. $(basename $@).sysc + cd $(TEST_OUTPUT_DIR) && ./$(basename $@).sysc -AddFilter: AddFilter.h AddFilter.cpp $(SYSC_DRIVER) - $(CXX) AddFilter.cpp $(DRIVER) \ +%.sysc: %.h %.cpp $(SRC_DIR)/src/test/resources/%SysCdriver.cpp + $(CXX) -g $(filter-out %.h,$^) \ -I. -I$(SYSTEMC)/include -L$(SYSTEMC)/lib-macosx64 -lsystemc -o $@ -AddFilter.cpp AddFilter.h: AddFilter.class - scala -cp $(CHISEL_JAR):. AddFilter --targetDir . --genHarness --backend sysc --design AddFilter +%.h %.cpp: %.class + scala -cp $(CHISEL_JAR):. SysCTest.$(basename $@) --targetDir . --genHarness --backend sysc -AddFilter.class: $(CHISEL_JAR) ../src/test/scala/AddFilter.scala - scalac -cp $(CHISEL_JAR) ../src/test/scala/AddFilter.scala +%.class: ../src/test/scala/SysCTest/%.scala $(CHISEL_JAR) + scalac -cp $(CHISEL_JAR) $< diff --git a/README.md b/README.md index 576d930f..6a37bac0 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,8 @@ +#### NOTE: This README.md describes (and associated repository contains) version 2.x of Chisel, and while we continue to support this version of Chisel, we encourage people to migrate to the new version: [Chisel3](https://github.com/ucb-bar/chisel3) + +We've removed the Getting Started section of this document. +If you're just getting started, you should be using Chisel3. + About Chisel ============ @@ -10,119 +15,55 @@ language, which raises the level of hardware design abstraction by providing concepts including object orientation, functional programming, parameterized types, and type inference. -Chisel can generate a high-speed C++-based cycle-accurate software simulator, -or low-level Verilog designed to pass on to standard ASIC or FPGA tools -for synthesis and place and route. - Visit the [community website](http://chisel.eecs.berkeley.edu/) for more information. -Getting started -=============== - -Chisel Users ------------- +Documentation +------------- -To start working on a circuit with Chisel, create simple build.sbt -and scala source file containing your Chisel code as follow. +Documentation has been moved to a separate [repository](https://github.com/ucb-bar/chisel-doc). - $ cat build.sbt - scalaVersion := "2.10.4" - libraryDependencies += "edu.berkeley.cs" %% "chisel" % "latest.release" +Chisel3 +======= -(You want your build.sbt file to contain a reference to Scala version greater -or equal to 2.10 and a dependency on the Chisel library.) +We're releasing snapshot versions of Chisel3. To facilitate the +transition from Chisel2, you should ensure that your designs build and +test in Chisel3 compatibility mode by passing the following arguments +to Chisel: -Edit the source files for your circuit + --minimumCompatibility 3.0.0 - $ cat Hello.scala - import Chisel._ - - class HelloModule extends Module { - val io = new Bundle {} - printf("Hello World!\n") - } - - class HelloModuleTests(c: HelloModule) extends Tester(c) { - step(1) - } +If you invoke chiselMain() or chiselMainTest() directly, you should +add these arguments to your current argument list: object hello { def main(args: Array[String]): Unit = { - chiselMainTest(Array[String]("--backend", "c", "--compile", "--test", "--genHarness"), + chiselMainTest(Array[String]("--backend", "c", "--compile", "--test", "--genHarness", "--minimumCompatibility", "3.0.0"), () => Module(new HelloModule())){c => new HelloModuleTests(c)} } } -At this point you will need to [download and install sbt](http://www.scala-sbt.org/release/docs/Getting-Started/Setup.html#installing-sbt) -for your favorite distribution. You will need sbt version 0.13.0 or higher -because [recent versions of sbt](http://www.scala-sbt.org/0.13.0/docs/Community/Changes.html) -generate jars without the scala third-point version number -(i.e. chisel_2.10-2.0.2.jar instead of chisel_2.10*.2*-2.0.2.jar). - -Execute sbt run to generate the C++ simulation source for your circuit, and (assuming you have a g++ compiler installed), compile it, and execute it under the tester. - - $ sbt run - - -Going further, you should read on the [sbt directory structure](http://www.scala-sbt.org/release/docs/Getting-Started/Directories.html) -to organize your files for bigger projects. SBT is the "official" -build system for Scala but you can use any other Java build system you -like (Maven, etc). - -Chisel is implemented 100% in Scala! - - -Chisel developers ------------------ - -You should have git, make, scala, and sbt installed on your -development system. First, clone the Chisel repository and change to -the project directory: - - $ git clone https://github.com/ucb-bar/chisel.git - $ cd chisel - -Compile and install your local copy of Chisel: - - $ make clean test publish-local - -In order to use your local copy of Chisel in your own projects, you -will need to update your build.sbt files so the Chisel library -dependency is satisfied by your local copy. Replace - - libraryDependencies += "edu.berkeley.cs" %% "chisel" % "latest.release" - -with: - - libraryDependencies += "edu.berkeley.cs" %% "chisel" % "2.3-SNAPSHOT" - -Before you generate a pull request, run the following command -to insure all unit tests pass. - - $ make test - -You can follow Chisel metrics on style compliance and code coverage -on the [website](https://chisel.eecs.berkeley.edu/unit_test_trends.html). - -If you are debugging an issue in a third-party project which depends -on the Chisel jar, first check that the chisel version in your chisel -code base and in the third-party project library dependency match. -After editing the chisel code base, delete the local jar cache directory -to make sure you are not picking up incorrect jar files, then publish -the Chisel jar locally and remake your third-party project. Example: - - $ cat *srcTop*/chisel/project/build.scala - ... - version := "2.3-SNAPSHOT" - ... - - $ cat *srcTop*/riscv-sodor/project/build.scala - ... - libraryDependencies += "edu.berkeley.cs" %% "chisel" % "2.3-SNAPSHOT" - ... - - $ cd *srcTop*/chisel && make publish-local - $ cd *srcTop*/riscv-sodor && make run-emulator - +This will report errors for the following Chisel3 issues: + + * Vec(Reg) should be replaced with Reg(Vec), + * type-only vals (no associated data) must be wrapped in a Wire() if they will be the destination of a wiring operation (":=" or " < >"), + * masked bit patterns ('b??') should be created using BitPat(), not UInt() or Bits(), + * the "clone" method required for parameterized Bundles has been renamed "cloneType", + * the con and alt inputs to a Mux must be type-compatible - both signed or both unsigned, + * bulk-connection to a node that has been procedurally assigned-to is illegal, + * != is deprecated, use =/= instead, + * use SeqMem(...) instead of Mem(..., seqRead), + * use SeqMem(n:Int, out: => T) instead of SeqMem(out: => T, n:Int), + * use Mem(n:Int, t:T) instead of Mem(out:T, n:Int), + * use Vec(n:Int, gen: => T) instead of Vec(gen: => T, n:Int), + * Mem(..., orderedWrites) is no longer supported, + * masked writes are only supported for Mem[Vec[_]], + * connections between UInt and SInt are illegal. + * module io's must be wrapped in IO(). + +In addition, the following incompatibilities require code changes: + + * the Node class and object no longer exist (the class should have been private in Chisel2) + * printf() is defined in the Chisel object and produces simulation printf()'s. To use the Scala Predef.printf(), you need to qualify it with Predef. + * in Chisel2, bulk-connects <> with unconnected source components do not update connections from the unconnected components. In Chisel3, bulk-connects strictly adhere to last connection semantics and unconnected OUTPUTs will be connected to INPUTs resulting in the assignment of random values to those inputs. diff --git a/ReleaseNotes b/ReleaseNotes index 60d1fcde..403fad99 100644 --- a/ReleaseNotes +++ b/ReleaseNotes @@ -1,5 +1,8 @@ -ReleaseNotes for Chisel v2.2.25 3/25/2015 +ReleaseNotes for Chisel v2.2.38 -This release of Chisel is largely a maintenance release. -See the associated Changelog for issues resolved with this release. +This release of Chisel is a maintenance release, incorporating support for Chisel3's {as,to}{U,S}Int methods in all Chisel Data types. + +We will be removing support for Scala 2.10 in future Chisel +releases. Please verify your code compiles and runs correctly under +Scala 2.11. diff --git a/bin/build_graphs.py b/bin/build_graphs.py index 2a4d116c..b0da26eb 100644 --- a/bin/build_graphs.py +++ b/bin/build_graphs.py @@ -1,6 +1,6 @@ #!/usr/bin/env python -import fnmatch, json, os, re, sys, xml.dom.minidom +import fnmatch, json, os, re, sys, xml.dom.minidom, time from jinja2 import Environment, FileSystemLoader @@ -11,62 +11,73 @@ def get_element_text(node): result += text.data.strip() return result +def load_build_info(path): + """Load build.xml as output by Jenkins""" + doc = xml.dom.minidom.parse(path) + timestampElements = doc.documentElement.getElementsByTagName("timestamp") + assert timestampElements.length == 1 + timestampStr = get_element_text(timestampElements[0]) + localTimestamp = time.localtime(float(timestampStr)/1000) + GMTOffset = time.altzone if localTimestamp.tm_isdst else time.timezone + # print "timestamp: %s\n" % (timestampStr) + sign = "" + if GMTOffset < 0: + sign = '-' + GMTOffset = -GMTOffset + else: + sign = '+' + hourOffset = GMTOffset/3600 + minOffset = (GMTOffset - (hourOffset * 3600))/60 + hhmmOffset = '{}{:02d}{:02d}'.format(sign, hourOffset, minOffset) + timestamp = time.strftime("%Y-%m-%dT%H:%M:%S", localTimestamp) + hhmmOffset + return timestamp def load_test_results(path): - """Load junitResult.xml as outputed by Jenkins""" + """Load junitResult.xml as output by Jenkins""" doc = xml.dom.minidom.parse(path) - timestamp = get_element_text( - doc.documentElement.getElementsByTagName("timestamp")[0]) nb_tests = len(doc.documentElement.getElementsByTagName("case")) nb_failures = len( doc.documentElement.getElementsByTagName("errorStackTrace")) - return timestamp, nb_tests, nb_failures + return nb_tests, nb_failures def load_checkstyle_violations(path): - """Load violations.xml as outputed by Jenkins""" + """Load violations.xml as output by Jenkins""" nb_violations = 0 doc = xml.dom.minidom.parse(path) - look = re.match('.*/(\d\d\d\d-\d\d-\d\d)_(\d\d)-(\d\d)-(\d\d)/.*', path) - if look: - timestamp = "%sT%s:%s:%s-0700" % ( - look.group(1), look.group(2), look.group(3), look.group(4)) - for node in doc.documentElement.getElementsByTagName("file"): - nb_violations += int(node.getAttribute("count")) - return timestamp, nb_violations - raise ValueError("cannot extract timestamp for %s" % path) - + for node in doc.documentElement.getElementsByTagName("file"): + nb_violations += int(node.getAttribute("count")) + return nb_violations def load_coverage(path): - """Load coverage.xml as outputed by Jenkins""" + """Load coverage.xml as output by Jenkins""" doc = xml.dom.minidom.parse(path) - look = re.match('.*/(\d\d\d\d-\d\d-\d\d)_(\d\d)-(\d\d)-(\d\d)/.*', path) - if look: - timestamp = "%sT%s:%s:%s-0700" % ( - look.group(1), look.group(2), look.group(3), look.group(4)) - line_coverage = float(doc.documentElement.getAttribute("line-rate")) - return timestamp, line_coverage - raise ValueError("cannot extract timestamp for %s" % path) + line_coverage = float(doc.documentElement.getAttribute("line-rate")) + return line_coverage def main(args): failures = [] coverage = [] violations = [] - root_dir = os.getcwd() + root_dir = os.path.join(os.getcwd(), 'builds') for root, dirnames, filenames in os.walk(root_dir): + if not ('build.xml' in filenames): + continue + # General build info + timestamp = load_build_info(os.path.join(root, 'build.xml')) # unit test results for path in fnmatch.filter(filenames, 'junitResult.xml'): - timestamp, nb_tests, nb_failures = load_test_results( + nb_tests, nb_failures = load_test_results( os.path.join(root, path)) failures += [ (timestamp, float(nb_failures) / nb_tests) ] # checkstyle violations - for path in fnmatch.filter(filenames, 'violations.xml'): - timestamp, nb_violations = load_checkstyle_violations( - os.path.join(root, path)) + for dir in fnmatch.filter(dirnames, 'violations'): + path = os.path.join(root, dir, 'violations.xml') + nb_violations = load_checkstyle_violations(path) violations += [ (timestamp, nb_violations) ] # line coverage for path in fnmatch.filter(filenames, 'coverage.xml'): - timestamp, line_coverage = load_coverage( + line_coverage = load_coverage( os.path.join(root, path)) coverage += [ (timestamp, line_coverage) ] diff --git a/build.sbt b/build.sbt new file mode 100644 index 00000000..4a399dbc --- /dev/null +++ b/build.sbt @@ -0,0 +1,101 @@ +def versionToArray(v: String): Array[String] = v.split('.') + +lazy val chiselBuildSettings = Seq ( + organization := "edu.berkeley.cs", + // version := "2.2.40", + version := "2.3-SNAPSHOT", + name := "Chisel", + scalaVersion := "2.11.11", + crossScalaVersions := Seq("2.10.6", "2.11.11"), + //sourceDirectory := new File("@srcTop@"), + publishMavenStyle := true, + publishArtifact in Test := false, + pomIncludeRepository := { x => false }, + pomExtra := ( + http://chisel.eecs.berkeley.edu/ + + + BSD-style + http://www.opensource.org/licenses/bsd-license.php + repo + + + + https://github.com/ucb-bar/chisel.git + scm:git:github.com/ucb-bar/chisel.git + + + + jackbackrack + Jonathan Bachrach + http://people.csail.mit.edu/jrb/ + + + huytbvo + Huy Vo + + + ), + + publishTo <<= version { v: String => + val nexus = "https://oss.sonatype.org/" + if (v.trim.endsWith("SNAPSHOT")) + Some("snapshots" at nexus + "content/repositories/snapshots") + else + Some("releases" at nexus + "service/local/staging/deploy/maven2") + }, + + resolvers ++= Seq( + Resolver.sonatypeRepo("snapshots"), + Resolver.sonatypeRepo("releases") + ), + + /* Bumping "com.novocode" % "junit-interface" % "0.11", causes DelayTest testSeqReadBundle to fail + * in subtly disturbing ways on Linux (but not on Mac): + * - some fields in the generated .h file are re-named, + * - an additional field is added + * - the generated .cpp file has additional differences: + * - different temps in clock_lo + * - missing assignments + * - change of assignment order + * - use of "Tx" vs. "Tx.values" + */ + libraryDependencies += "com.novocode" % "junit-interface" % "0.10" % "test", + // scalatest and scalacheck ordinarily are needed only for testing, + // but since ChiselSpec is in main for clients of chisel and their tests, + // these are now required for the main build. + libraryDependencies += "org.scalatest" %% "scalatest" % "2.2.5", + libraryDependencies += "org.scalacheck" %% "scalacheck" % "1.12.5", + libraryDependencies <+= (scalaVersion)("org.scala-lang" % "scala-reflect" % _), + + // Execute tests in the current project serially. + // Tests from other projects may still run concurrently. + parallelExecution in Test := false, + scalacOptions ++= Seq("-deprecation", "-feature", "-language:reflectiveCalls", "-language:implicitConversions", "-language:existentials"), + javacOptions ++= Seq("-target", "1.7"), + scalacOptions in (Compile, doc) <++= (baseDirectory in LocalProject("chisel"), version) map { (bd, v) => + Seq("-diagrams", "-diagrams-max-classes", "25", "-sourcepath", bd.getAbsolutePath, "-doc-source-url", "https://github.com/ucb-bar/chisel/tree/master/€{FILE_PATH}.scala") + } + ) + +lazy val chisel = (project in file(".")). + enablePlugins(BuildInfoPlugin). + settings( + // We should really be using name.value, but currently, the package is "Chisel" (uppercase first letter) + buildInfoPackage := /* name.value */ "Chisel", + buildInfoOptions += BuildInfoOption.BuildTime, + buildInfoKeys := Seq[BuildInfoKey](buildInfoPackage, version, scalaVersion, sbtVersion), + // Move the managed source directory where git won't complain about it, + // and where we can easily package its files as part of the source jar artifact. + // We'd like to use versionToArray(), slice(), and mkString() to convert an explicit + // Scala version (like 2.10.6), into the leftmost two components (2.10), + // but this seems to run afoul of assumptions sbt makes about the inclusion + // of Scala-version-specfic code (we get + // BuildInfo is already defined as case class BuildInfo + // so use the full version spec. + //sourceManaged in Compile <<= (sourceDirectory in Compile, scalaVersion){ (s,v) => s / ("scala-" + versionToArray(v).slice(0,2).mkString(".") + "/src_managed") }, + sourceManaged in Compile <<= (sourceDirectory in Compile, scalaVersion){ (s,v) => s / ("scala-" + v + "/src_managed") }, + // Add the generated sources to the packagedSrc artifact since they are excluded by default. + mappings in (Compile, packageSrc) += { ((sourceManaged in Compile).value / "sbt-buildinfo" / "BuildInfo.scala") -> "BuildInfo.scala" } + ). + settings(chiselBuildSettings: _*) diff --git a/doc/manual/chisel.mtt b/chisel.mtt similarity index 66% rename from doc/manual/chisel.mtt rename to chisel.mtt index dd9eea3e..fbd25786 100644 --- a/doc/manual/chisel.mtt +++ b/chisel.mtt @@ -49,14 +49,14 @@ backend. \section{Options} %%%%%%%%%%%%%%%%% -\begin{Description}[\Opt{--allocateOnlyNeededShadowRegisters}]\setlength{\itemsep}{0cm} -\item[\Opt{--allocateOnlyNeededShadowRegisters}] (C++) Attempt to allocate +\begin{Description}[\Opt{allocateOnlyNeededShadowRegisters}]\setlength{\itemsep}{0cm} +\item[--\Opt{allocateOnlyNeededShadowRegisters}] (C++) Attempt to allocate only those shadow registers actually required. This reduces the size of the main C++ design object (especially when \Arg{--shadowRegisterInObject} is enabled), which in turn reduces compilation time. It should have no execution-time performance impact. -\item[\Opt{--assert}] Emit assertions. -\item[\OptArg{--backend}{\ backendname}] Use the specified backend where +\item[--\Opt{assert}] Emit assertions. +\item[--\OptArg{backend}{\ backendname}] Use the specified backend where \Arg{backendname} is one of \begin{itemize} \item[\Arg{c}] C++ emulation @@ -66,27 +66,27 @@ backend. \item[\Arg{sysc}] SystemC emulation \item[\Arg{v}] Verilog \end{itemize} -\item[\Opt{--checkPorts}] Hmmm -\item[\Opt{--compile}] Produce backend output -\item[\Opt{--compileInitializationUnoptimized}] (C++) Compile +\item[--\Opt{checkPorts}] Hmmm +\item[--\Opt{compile}] Produce backend output +\item[--\Opt{compileInitializationUnoptimized}] (C++) Compile initialization code at -O0, rarely used code at -O1. -\item[\OptArg{--configCollect}{\ project.class}] Hmmm -\item[\Opt{--configDump}] Hmmm -\item[\OptArg{--configInstance}{\ project.class}] Hmmm -\item[\Opt{--cse}] Do common subexpression elimination -\item[\Opt{--debug}] Hmmm -\item[\Opt{--debugMem}] Hmmm -\item[\Opt{--dumpTestInput}] Hmmm -\item[\Opt{--emitTempNodes}] Hmmm -\item[\Opt{--genHarness}] Hmmm -\item[\OptArg{--include}{\ includefilenames}] (C++) Generate include +\item[--\OptArg{configCollect}{\ project.class}] Hmmm +\item[--\Opt{configDump}] Hmmm +\item[--\OptArg{configInstance}{\ project.class}] Hmmm +\item[--\Opt{cse}] Do common subexpression elimination +\item[--\Opt{debug}] Hmmm +\item[--\Opt{debugMem}] Hmmm +\item[--\Opt{dumpTestInput}] Hmmm +\item[--\Opt{emitTempNodes}] Hmmm +\item[--\Opt{genHarness}] Hmmm +\item[--\OptArg{include}{\ includefilenames}] (C++) Generate include file statements for each of the (space-delimited) filenames. -\item[\Opt{--inlineMem}] Hmmm -\item[\Opt{--ioDebug}] Hmmm -\item[\Opt{--isVCDinline}] (C++) Generate VCD dump code without goto +\item[--\Opt{inlineMem}] Hmmm +\item[--\Opt{ioDebug}] Hmmm +\item[--\Opt{isVCDinline}] (C++) Generate VCD dump code without goto branches. Allows compiling smaller VCD dump functions, reducing C++ compile times. This will have some impact on execution-time performance. -\item[\OptArg{--lineLimitFunctions}{\ lines}] (C++) Limit the number of +\item[--\OptArg{lineLimitFunctions}{\ lines}] (C++) Limit the number of lines in a C++ function/method before splitting it up into multiple functions to reduce C++ compile times. The \Arg{lines} value specifies a loose upper limit on the number of lines output to a @@ -97,45 +97,46 @@ backend. of calling a single function, calls to multiple functions are generated. Reasonable values for this argument would be in the range from 256 to 2048. -\item[\Opt{--lineNumbers}] Hmmm -\item[\OptArg{--minimumLinesPerFile}{\ lines}] (C++) Limit the minimum +\item[--\Opt{lineNumbers}] Hmmm +\item[--\OptArg{minimumLinesPerFile}{\ lines}] (C++) Limit the minimum number of lines per file so as not to produce trivial files. This works in conjunction with \Arg{lineLimitFunctions} to break up a massive single file into multiple smaller (but not too small) files. Reasonable values for this argument would be in the range of 1024 to 32768. -\item[\OptArg{--moduleNamePrefix}{\ }] Hmmm -\item[\Opt{--noAssert}] Hmmm -\item[\Opt{--noCombLoop}] Hmmm -\item[\Opt{--noInlineMem}] Hmmm -\item[\Opt{--noIoDebug}] Hmmm -\item[\OptArg{--numCols}{\ columns}] Hmmm -\item[\OptArg{--numRows}{\ rows}] Hmmm -\item[\OptArg{--parallelMakeJobs}{\ jobs}] (C++) Generate a +\item[--\OptArg{moduleNamePrefix}{\ }] Hmmm +\item[--\Opt{noAssert}] Hmmm +\item[--\Opt{noCombLoop}] Hmmm +\item[--\Opt{noInlineMem}] Hmmm +\item[--\Opt{noIoDebug}] Hmmm +\item[--\OptArg{numCols}{\ columns}] Hmmm +\item[--\OptArg{numRows}{\ rows}] Hmmm +\item[--\OptArg{parallelMakeJobs}{\ jobs}] (C++) Generate a \File{Makefile} to compile multiple C++ files in parallel. The \Arg{jobs} argument specifies the amount of parallelism (the argument to the \Arg{-j} option to \Prog{make}). A value of -1 indicates that no value will be passed with the \Arg{-j} argument to \Prog{make}, which in turn should inform \Prog{make} not to limit the number of jobs that can run simultaneously. -\item[\Opt{--partitionIslands}] (C++, dot) Partition the graph into islands of +\item[--\Opt{partitionIslands}] (C++, dot) Partition the graph into islands of combinatorial logic that may be compiled and executed in parallel. -\item[\Opt{--reportDims}] Hmmm -\item[\Opt{--shadowRegisterInObject}] (C++) Allocate shadow registers +\item[--\Opt{reportDims}] Hmmm +\item[--\Opt{shadowRegisterInObject}] (C++) Allocate shadow registers in the global emulation object (as opposed to the local clock procedures). This is automatically enabled when \Arg{lineLimitFunctions} is in effect. -\item[\OptArg{--targetDir}{\ outputdir}] Hmmm -\item[\Opt{--test}] Hmmm -\item[\OptArg{--testerSeed}{\ seed}] Hmmm -\item[\Opt{--v}] Hmmm -\item[\Opt{--vcd}] Hmmm -\item[\Opt{--vcdMem}] Hmmm -\item[\Opt{--Wcomponent}] Hmmm -\item[\Opt{--Wconnection}] Hmmm -\item[\Opt{--wi}] Hmmm -\item[\Opt{--wio}] Hmmm -\item[\Opt{--wo}] Hmmm +\item[--\OptArg{targetDir}{\ outputdir}] Directory in which to place + generated files. +\item[--\Opt{test}] Run the tester on the simulation. +\item[--\OptArg{testerSeed}{\ seed}] Hmmm +\item[--\Opt{v}] short-cut for "--backend v" +\item[--\Opt{vcd}] Hmmm +\item[--\Opt{vcdMem}] Hmmm +\item[--\Opt{Wcomponent}] Hmmm +\item[--\Opt{Wconnection}] Hmmm +\item[--\Opt{wi}] Hmmm +\item[--\Opt{wio}] Hmmm +\item[--\Opt{wo}] Hmmm \end{Description} \section{Version} diff --git a/csrc/emulator_api.h b/csrc/emulator_api.h deleted file mode 120000 index f138c45b..00000000 --- a/csrc/emulator_api.h +++ /dev/null @@ -1 +0,0 @@ -../src/main/resources/emulator_api.h \ No newline at end of file diff --git a/csrc/emulator_mod.h b/csrc/emulator_mod.h deleted file mode 120000 index c515a419..00000000 --- a/csrc/emulator_mod.h +++ /dev/null @@ -1 +0,0 @@ -../src/main/resources/emulator_mod.h \ No newline at end of file diff --git a/csrc/tests.cpp b/csrc/tests.cpp index 3db9a652..2dafb523 100644 --- a/csrc/tests.cpp +++ b/csrc/tests.cpp @@ -4,7 +4,7 @@ template dat_t LITS(const char* str) { dat_t dat; - assert(dat_from_str(str, dat)); + assert(dat_from_hex(str, dat)); return dat; } diff --git a/doc/.gitignore b/doc/.gitignore deleted file mode 100644 index f1cfd767..00000000 --- a/doc/.gitignore +++ /dev/null @@ -1,6 +0,0 @@ -*.log -*.aux -installation.pdf -manual.pdf -tutorial.pdf -cheatsheet/cheatsheet.pdf diff --git a/doc/Makefile b/doc/Makefile deleted file mode 100644 index 57f20ebc..00000000 --- a/doc/Makefile +++ /dev/null @@ -1,82 +0,0 @@ -# Building the docs on osx will require to install Jinja2 and BeautifulSoup: -# $ pip install Jinja2 BeautifulSoup -# and the different tools for text to pdf: -# $ port install texlive-latex-extra texlive-latex-recommended \ -# texlive-htmlxml ImageMagick - -version := 2.2.0 - -PDFLATEX := pdflatex -WWW_PAGES := index.html documentation.html download.html faq.html releases.html -WWW_EXTRA := manual.html getting-started.html - -# The following subdirectories build documentation correctly. -PDF_DIRS := installation manual tutorial getting-started dac12-talk -PDFS := $(addsuffix .pdf,$(addprefix chisel-,$(PDF_DIRS))) - -LATEX2MAN := latex2man -MAN_PAGES := chisel.man - -srcDir := . -installTop:= ../www - -# Set the current release info -# RELEASE_TAGTEXT is something like: v2.2.18 125 g3501d7f -# i.e., the output of git describe with dashes replaced by spaces -RELEASE_TAGTEXT=$(subst -, ,$(shell git describe --tags release)) -RELEASE_TAG=$(firstword $(RELEASE_TAGTEXT)) -RELEASE_DATETEXT=$(shell git log -1 --format="%ai" $(RELEASE_TAG)) -RELEASE_DATE=$(firstword $(RELEASE_DATETEXT)) - -vpath %.tex $(srcDir)/bootcamp $(srcDir)/installation $(srcDir)/talks/dac12 $(srcDir)/manual $(srcDir)/tutorial $(srcDir)/getting-started - -vpath %.mtt $(srcDir)/bootcamp $(srcDir)/installation $(srcDir)/talks/dac12 $(srcDir)/manual $(srcDir)/tutorial $(srcDir)/getting-started - -all: $(WWW_PAGES) $(WWW_EXTRA) $(PDFS) - -extra: $(WWW_EXTRA) - -html: $(WWW_PAGES) - -pdf: $(PDFS) - -install: all - install -d $(installTop)/$(version)/figs - install -m 644 $(wildcard $(srcDir)/manual/figs/*.png $(srcDir)/tutorial/figs/*.png) $(installTop)/$(version)/figs - install -m 644 $(WWW_EXTRA) $(PDFS) $(installTop)/$(version) - install -m 644 $(WWW_PAGES) $(installTop) - - -chisel-%.pdf: %.tex - cd $(dir $<) && TEXINPUTS=".:$(PWD)/$(srcDir)/manual:${TEXINPUTS}" pdflatex -file-line-error -interaction nonstopmode -output-directory $(PWD) $(notdir $<) - mv $(subst .tex,.pdf,$(notdir $<)) $@ - -%.html: %.tex - cd $(dir $<) && TEXINPUTS=".:$(PWD)/$(srcDir)/manual:${TEXINPUTS}" htlatex $(notdir $<) $(PWD)/$(srcDir)/html.cfg "" -d/$(PWD)/ - mv $(subst .tex,.html,$(notdir $<)) $@~ - $(srcDir)/../bin/tex2html.py $@~ $@ - -%.man: %.mtt - # cd into the directory containing the .tex file and massage it - cd $(dir $<) && \ - sed -e "s/@VERSION@/$(RELEASE_TAG)/" -e "s/@DATE@/$(RELEASE_DATE)/" $(notdir $<) > $(basename $@).ttex ;\ - TEXINPUTS=".:$(PWD)/$(srcDir)/manual:${TEXINPUTS}" latex2man $(basename $@).ttex $@ - -%.html: $(srcDir)/templates/%.html $(srcDir)/templates/base.html - $(srcDir)/../bin/jinja2html.py $(notdir $<) $@ - -releases.html: $(srcDir)/templates/releases.html $(srcDir)/templates/base.html - sed -e "s/@VERSION@/$(RELEASE_TAG)/" -e "s/@DATE@/$(RELEASE_DATE)/" $< > $(dir $<)/$@.tmp - $(srcDir)/../bin/jinja2html.py $@.tmp $@ && ${RM} $(dir $<)/$@.tmp - -clean: - -rm -f $(addprefix manual/,*.4ct *.4tc *.css *.dvi *.html *.idv *.lg *.tmp *.xref) - -rm -f $(addprefix manual/figs/,bits-1.png bits-and.png bits-or-and.png node-hierarchy.png type-hierarchy.png) - -rm -f $(addprefix tutorial/,*.4ct *.4tc *.css *.dvi *.html *.idv *.lg *.tmp *.xref) - -rm -f $(addprefix tutorial/figs/,DUT.png DUT.svg condupdates.png) - -rm -f $(addprefix getting-started/,*.4ct *.4tc *.css *.dvi *.html *.idv *.lg *.tmp *.xref) getting-started?.html - -rm -f $(WWW_PAGES) $(PDFS) $(WWW_EXTRA) $(addsuffix .1,$(WWW_EXTRA)) $(patsubst %.html,%.css,$(WWW_EXTRA)) - -rm -f *~ *.aux *.log *.nav *.out *.snm *.toc *.vrb - -rm -f *.jpg *.png - -rm -f manual/chisel.man manual/chisel.ttex - diff --git a/doc/README b/doc/README new file mode 100644 index 00000000..2af516dc --- /dev/null +++ b/doc/README @@ -0,0 +1,8 @@ +Chisel documentation (non-tutorial) has been moved to the chisel-doc repo: + + https://github.com/ucb-bar/chisel-doc + +Tutorial documentation has been moved to the chisel-tutorial repo: + + https://github.com/ucb-bar/chisel-tutorial/doc/tutorial + diff --git a/doc/bootcamp/bootcamp-20130930.tex b/doc/bootcamp/bootcamp-20130930.tex deleted file mode 100644 index ffddba81..00000000 --- a/doc/bootcamp/bootcamp-20130930.tex +++ /dev/null @@ -1,2280 +0,0 @@ -\documentclass[xcolor=pdflatex,dvipsnames,table]{beamer} -\usepackage{epsfig,graphicx} -\usepackage{palatino} -\usepackage{fancybox} -\usepackage{relsize} -\usepackage[procnames]{listings} - -\input{../style/scala.tex} -\input{../style/talk.tex} - -\title{Chisel Bootcamp 3} -\author{Jonathan Bachrach} -\date{\today} -\institute[UC Berkeley]{EECS UC Berkeley} - -\begin{document} - -\begin{frame} -\titlepage -\end{frame} -\addtocounter{framenumber}{-1} - -% \begin{frame}[fragile]{tutorial.scala} -% \begin{scala} -% package Tutorial { -% -% import Chisel._ -% -% object Tutorial { -% def main(args: Array[String]): Unit = { -% val tut_args = args.slice(1, args.length) ++ -% Array("--targetDir", "../emulator", "--genHarness") -% args(0) match { -% case "gcd" => -% chiselMain(tut_args, () => new GCD()) -% ... -% } -% } -% } -% -% } -% \end{scala} -% \end{frame} - -\begin{frame}[fragile]{Goals for Bootcamp} - -\begin{itemize} -\item get yout started with Chisel -\item get a basic working knowledge of Chisel -\item learn how to think in Chisel -\item know where to get more information -\end{itemize} - -\end{frame} - -\setbeamercolor{frametitle}{bg=\frametitleproblemcolor} -\begin{frame}[fragile]{Logging into EC2} - -\begin{scala} -ssh ubuntu@xxx -password: bootcamp -\end{scala} -\noindent -where \code{xxx} corresponds to your EC2 instance written on your airbears slip - -\end{frame} -\setbeamercolor{frametitle}{bg=\frametitledefaultcolor} - -\setbeamercolor{frametitle}{bg=\frametitleproblemcolor} -\begin{frame}[fragile]{Using Screen} -to prevent lossage of state if disconnected ... when you first log in, type -\begin{scala} -screen -\end{scala} - -when you log back into the instance, type -\begin{scala} -screen -r -\end{scala} - -\end{frame} -\setbeamercolor{frametitle}{bg=\frametitledefaultcolor} - -\setbeamercolor{frametitle}{bg=\frametitleproblemcolor} -\begin{frame}[fragile]{Getting the Latest} - -\begin{scala} -cd chisel-tutorial -git pull -\end{scala} - -\end{frame} -\setbeamercolor{frametitle}{bg=\frametitledefaultcolor} - -\begin{frame}[fragile]{chisel-tutorial repo} -\begin{FramedSemiVerb} -chisel-tutorial/ - Makefile - examples/ \comment{\# Contains chisel examples} - Makefile - build.sbt \comment{\# Contains project description} - FullAdder.scala ... - problems/ \comment{\# Contains skeletal files for tutorial problems} - Makefile - build.sbt \comment{\# Contains project description} - Accumulator.scala ... - solutions/ \comment{\# Contains solutions to problems} - Makefile - build.sbt \comment{\# Contains project description} - Counter.scala ... -\end{FramedSemiVerb} -\end{frame} - -\setbeamercolor{frametitle}{bg=\frametitleproblemcolor} -\begin{frame}[fragile]{Get This} - -\begin{center} -\fbox{ -\url{chisel.eecs.berkeley.edu/bootcamp-20130930.pdf} -} -\end{center} - -\end{frame} -\setbeamercolor{frametitle}{bg=\frametitledefaultcolor} - -\begin{frame}[fragile] -\frametitle{Chisel} - -\begin{columns}[c] - -\column{0.55\textwidth} - -\begin{itemize} -\item A hardware construction language -\begin{itemize} -\item ``synthesizable by construction'' -\end{itemize} -\item {\color{red}{\bf Not} Scala -> Verilog} -\item Best of hardware and software design ideas -\item Embedded within Scala language to leverage mindshare and language design -\item Multiple targets -\begin{itemize} -\item Simulation and synthesis -\item Memory IP is target-specific -\end{itemize} -\end{itemize} - -\column{0.40\textwidth} - -\begin{center} -single source \\ -\includegraphics[width=0.99\textwidth]{../talks/retreat-1/figs/graph-and-targets.pdf} \\ -multiple targets \\ -\end{center} - -\end{columns} -\note{single source generates two different verilog outputs, one for fpga and one for asic. surprisingly difficult to generate each. for example, chisel has abstraction for memories.} -\end{frame} - -\begin{frame}[fragile] -\frametitle{The Scala Programming Language} - -\begin{columns}[c] - -\column{0.75\textwidth} - -\begin{itemize} -\item Compiled to JVM -\begin{itemize} -\item Good performance -\item Great Java interoperability -\item Mature debugging, execution environments -\end{itemize} -\item Object Oriented -\begin{itemize} -\item Factory Objects, Classes -\item Traits, overloading etc -\item Strongly typed with type inference -\end{itemize} -\item Functional -\begin{itemize} -\item Higher order functions -\item Anonymous functions -\item Currying etc -\end{itemize} -\item Extensible -\begin{itemize} -\item Domain Specific Languages (DSLs) -\end{itemize} -\item Fairly Popular -\begin{itemize} -\item Twitter -\item many Universities -\end{itemize} -\end{itemize} - -\column{0.25\textwidth} - -\begin{center} -\includegraphics[height=0.4\textheight]{figs/programming-scala.pdf} \\ -\includegraphics[height=0.4\textheight]{figs/programming-in-scala.pdf} -\end{center} - -\end{columns} -\note{compiles to jvm, includes powerful features to support abstraction, as makes it easy to embed DSLs} -\end{frame} - -\include{scala-intro} - -\begin{frame}[fragile] -\frametitle{Algebraic Graph Construction} - -\begin{columns} -\column{0.35\textwidth} -{\lstset{basicstyle={\Large\ttfamily}} -\begin{scala} -Mux(x > y, x, y) -\end{scala} -} - -\column{0.6\textwidth} - -\begin{center} -\includegraphics[width=0.9\textwidth]{figs/max2.pdf} -\end{center} -\end{columns} -\end{frame} - -\begin{frame}[fragile] -\frametitle{Creating Module} - -\begin{columns} -\column{0.45\textwidth} - -{\lstset{basicstyle={\scriptsize\ttfamily}} -\begin{scala} -class Max2 extends Module { - val io = new Bundle { - val x = UInt(INPUT, 8) - val y = UInt(INPUT, 8) - val z = UInt(OUTPUT, 8) } - io.z := Mux(io.x > io.y, io.x, io.y) -} -\end{scala} -} - -\column{0.45\textwidth} -\begin{center} -\includegraphics[width=0.95\textwidth]{figs/Max2c.pdf} \\ -\end{center} -\end{columns} - -\end{frame} - -\begin{frame}[fragile] -\frametitle{Connecting Modules} - -\begin{columns} -\column{0.3\textwidth} -\begin{scala} -val m1 = - Module(new Max2()) -m1.io.x := a -m1.io.y := b -val m2 = - Module(new Max2()) -m2.io.x := c -m2.io.y := d -val m3 = - Module(new Max2()) -m3.io.x := m1.io.z -m3.io.y := m2.io.z -\end{scala} - -\column{0.6\textwidth} - -\begin{center} -\includegraphics[width=0.99\textwidth]{figs/Max4.pdf} \\ -\end{center} -\end{columns} - -\end{frame} - - -\begin{frame}[fragile] -\frametitle{Defining Construction Functions} - -\begin{columns} - -\column{0.45\textwidth} - -\begin{scala} -def Max2(x, y) = Mux(x > y, x, y) -\end{scala} -\begin{scala} -Max2(x, y) -\end{scala} - -\column{0.5\textwidth} - -\begin{center} -\includegraphics[width=0.95\textwidth]{figs/Max2.pdf} \\[1cm] -\end{center} - -\end{columns} - -\end{frame} - -\begin{frame}[fragile] -\frametitle{Functional Construction} - -\begin{columns} - -\column{0.5\textwidth} - -{\lstset{basicstyle={\scriptsize\ttfamily}} -\begin{scala} -class MaxN(n: Int, w: Int) extends Module { - val io = new Bundle { - val in = Vec.fill(n){ UInt(INPUT, w) } - val out = UInt(OUTPUT, w) - } - io.out := io.in.reduceLeft(Max2) -} -\end{scala} -} - -\column{0.4\textwidth} - -\begin{center} -\includegraphics[width=0.99\textwidth]{figs/reduceMax.pdf} \\ -\end{center} - -\end{columns} - -\end{frame} - -\begin{frame}[fragile] -\frametitle{Example} -\begin{columns} - -\column{0.45\textwidth} - -\begin{footnotesize} -\begin{scala} -class GCD extends Module { - val io = new Bundle { - val a = UInt(INPUT, 16) - val b = UInt(INPUT, 16) - val z = UInt(OUTPUT, 16) - val valid = Bool(OUTPUT) } - val x = Reg(init = io.a) - val y = Reg(init = io.b) - when (x > y) { - x := x - y - } .otherwise { - y := y - x - } - io.z := x - io.valid := y === UInt(0) -} -\end{scala} -\end{footnotesize} - -\column{0.45\textwidth} - -\begin{center} -\includegraphics[width=0.9\textwidth]{figs/gcd.pdf} -\end{center} - -\end{columns} -\end{frame} - -\setbeamercolor{frametitle}{bg=\frametitleproblemcolor} -\begin{frame}[fragile]{Running the Chisel Simulation} - -\begin{bash} -cd ~/chisel-tutorial/examples -make GCD.out -\end{bash} - -{\lstset{basicstyle={\scriptsize\ttfamily}} -\begin{bash} -... -PASSED -[success] Total time: 2 s, completed Feb 28, 2013 8:14:37 PM -\end{bash} -} - -\end{frame} -\setbeamercolor{frametitle}{bg=\frametitledefaultcolor} - -\setbeamercolor{frametitle}{bg=\frametitleproblemcolor} -\begin{frame}[fragile]{Generating Verilog} - -\begin{bash} -cd ~/chisel-tutorial/examples -make GCD.v -\end{bash} - -The Verilog source is roughly divided into three parts: - -\begin{enumerate} -\item Module declaration with input and outputs -\item Temporary wire and register declaration used for holding intermediate values -\item Register assignments in \verb+always @ (posedge clk)+ -\end{enumerate} - -\end{frame} -\setbeamercolor{frametitle}{bg=\frametitledefaultcolor} - -\begin{frame}[fragile]{FullAdder -- Type Inference} - -\begin{columns} -\column{0.4\textwidth} - -{\lstset{basicstyle={\scriptsize\ttfamily}} -\begin{scala} -class FullAdder extends Module { - val io = new Bundle { - val a = UInt(INPUT, 1) - val b = UInt(INPUT, 1) - val cin = UInt(INPUT, 1) - val sum = UInt(OUTPUT, 1) - val cout = UInt(OUTPUT, 1) - } - // Generate the sum - val a_xor_b = io.a ^ io.b - io.sum := a_xor_b ^ io.cin - // Generate the carry - val a_and_b = io.a & io.b - val b_and_cin = io.b & io.cin - val a_and_cin = io.a & io.cin - io.cout := - a_and_b | b_and_cin | a_and_cin -} -\end{scala} -} - -\column{0.55\textwidth} - -\begin{center} -\includegraphics[width=0.9\textwidth]{../getting-started/figs/Full_Adder.jpg} -\end{center} - -\end{columns} - -\end{frame} - -\begin{frame}[fragile]{FullAdder Verilog -- Width Inference 1} - -\begin{columns} -\column{0.45\textwidth} - -{\lstset{basicstyle={\scriptsize\ttfamily}} -\begin{scala} -class FullAdder extends Module { - val io = new Bundle { - val a = UInt(INPUT, 1) - val b = UInt(INPUT, 1) - val cin = UInt(INPUT, 1) - val sum = UInt(OUTPUT, 1) - val cout = UInt(OUTPUT, 1) - } - // Generate the sum - val a_xor_b = io.a ^ io.b - io.sum := a_xor_b ^ io.cin - // Generate the carry - val a_and_b = io.a & io.b - val b_and_cin = io.b & io.cin - val a_and_cin = io.a & io.cin - io.cout := - a_and_b | b_and_cin | a_and_cin -} -\end{scala} -} - -\column{0.45\textwidth} - -{\lstset{basicstyle={\scriptsize\ttfamily}} -\begin{scala} -module FullAdder( - input io_a, - input io_b, - input io_cin, - output io_sum, - output io_cout); - wire T0; - wire a_and_cin; - wire T1; - wire b_and_cin; - wire a_and_b; - wire T2; - wire a_xor_b; - - assign io_cout = T0; - assign T0 = T1 | a_and_cin; - assign a_and_cin = io_a & io_cin; - assign T1 = a_and_b | b_and_cin; - assign b_and_cin = io_b & io_cin; - assign a_and_b = io_a & io_b; - assign io_sum = T2; - assign T2 = a_xor_b ^ io_cin; - assign a_xor_b = io_a ^ io_b; -endmodule -\end{scala} -} - -\end{columns} - -\end{frame} - -\begin{frame}[fragile]{FullAdder2 Verilog -- Width Inference 2} - -\begin{columns} -\column{0.45\textwidth} - -{\lstset{basicstyle={\scriptsize\ttfamily}} -\begin{scala} -class FullAdder2 extends Module { - val io = new Bundle { - val a = UInt(INPUT, 2) - val b = UInt(INPUT, 2) - val cin = UInt(INPUT, 2) - val sum = UInt(OUTPUT, 2) - val cout = UInt(OUTPUT, 2) - } - // Generate the sum - val a_xor_b = io.a ^ io.b - io.sum := a_xor_b ^ io.cin - // Generate the carry - val a_and_b = io.a & io.b - val b_and_cin = io.b & io.cin - val a_and_cin = io.a & io.cin - io.cout := - a_and_b | b_and_cin | a_and_cin -} -\end{scala} -} - -\column{0.45\textwidth} - -{\lstset{basicstyle={\scriptsize\ttfamily}} -\begin{scala} -module FullAdder( - input [1:0] io_a, - input [1:0] io_b, - input [1:0] io_cin, - output[1:0] io_sum, - output[1:0] io_cout); - wire[1:0] T0; - wire[1:0] a_and_cin; - wire[1:0] T1; - wire[1:0] b_and_cin; - wire[1:0] a_and_b; - wire[1:0] T2; - wire[1:0] a_xor_b; - - assign io_cout = T0; - assign T0 = T1 | a_and_cin; - assign a_and_cin = io_a & io_cin; - assign T1 = a_and_b | b_and_cin; - assign b_and_cin = io_b & io_cin; - assign a_and_b = io_a & io_b; - assign io_sum = T2; - assign T2 = a_xor_b ^ io_cin; - assign a_xor_b = io_a ^ io_b; -endmodule -\end{scala} -} - -\end{columns} - -\end{frame} - -\begin{frame}[fragile]{Using Registers} -\begin{scala} -// clock the new reg value on every cycle -val y = io.x -val z = Reg(next = y) -\end{scala} - -\begin{scala} -// clock the new reg value when the condition a > b -val x = Reg(UInt()) -when (a > b) { x := y } -.elsewhen (b > a) { x := z } -.otherwise { x := w } -\end{scala} -\end{frame} - -\begin{frame}[fragile]{Unconditional Register Update} - -\begin{columns} - -\column{0.42\textwidth} - -{\lstset{basicstyle={\scriptsize\ttfamily}} -\begin{scala} -class ShiftRegister extends Module { - val io = new Bundle { - val in = UInt(INPUT, 1) - val out = UInt(OUTPUT, 1) - } - val r0 = Reg(next = io.in) - val r1 = Reg(next = r0) - val r2 = Reg(next = r1) - val r3 = Reg(next = r2) - io.out := r3 -} -\end{scala} -} -\begin{center} -\includegraphics[width=0.9\textwidth]{figs/shift-register.pdf} -\end{center} - -\column{0.5\textwidth} - -{\lstset{basicstyle={\scriptsize\ttfamily}} -\begin{scala} -module ShiftRegister(input clk, input reset, - input io_in, - output io_out); - - reg[0:0] r3; - reg[0:0] r2; - reg[0:0] r1; - reg[0:0] r0; - - assign io_out = r3; - always @(posedge clk) begin - r3 <= r2; - r2 <= r1; - r1 <= r0; - r0 <= io_in; - end -endmodule -\end{scala} -} - -\end{columns} - -\end{frame} - -\begin{frame}[fragile]{Conditional Register Update} - -\begin{columns} - -\column{0.47\textwidth} - -\begin{scala} -class ShiftRegister extends Module { - val io = new Bundle { - val in = UInt(INPUT, 1) - val shift = Bool(INPUT) - val out = UInt(OUTPUT, 1) - } - - val r0 = Reg(UInt()) - val r1 = Reg(UInt()) - val r2 = Reg(UInt()) - val r3 = Reg(UInt()) - - when (io.shift) { - r0 := io.in - r1 := r0 - r2 := r1 - r3 := r2 - } - io.out := r3 -} -\end{scala} - -\column{0.45\textwidth} - -\begin{center} -\includegraphics[width=0.9\textwidth]{figs/enable-shift-register.pdf} -\end{center} - -\end{columns} - -\end{frame} - -\begin{frame}[fragile]{Conditional Register Update with Reset} - -\begin{scala} -class EnableShiftRegister extends Module { - val io = new Bundle { - val in = UInt(INPUT, 1) - val shift = Bool(INPUT) - val out = UInt(OUTPUT, 1) - } - // Register reset to zero - val r0 = Reg(init = UInt(0, 1)) - val r1 = Reg(init = UInt(0, 1)) - val r2 = Reg(init = UInt(0, 1)) - val r3 = Reg(init = UInt(0, 1)) - when (io.shift) { - r0 := io.in - r1 := r0 - r2 := r1 - r3 := r2 - } - io.out := r3 -} -\end{scala} - -\end{frame} - -\begin{frame}[fragile]{UInt Literals} -inferred width -\begin{scala} -UInt(1) // decimal 1-bit literal from Scala Int. -UInt("ha") // hexadecimal 4-bit literal from string. -UInt("o12") // octal 4-bit literal from string. -UInt("b1010") // binary 4-bit literal from string. -\end{scala} -specified widths -\begin{scala} -UInt("h_dead_beef") // 32-bit literal of type UInt. -UInt(1) // decimal 1-bit literal from Scala Int. -UInt("ha", 8) // hexadecimal 8-bit literal of type UInt. -UInt("o12", 6) // octal 6-bit literal of type UInt. -UInt("b1010", 12) // binary 12-bit literal of type UInt. -UInt(5, 8) // unsigned decimal 8-bit literal of type UInt. -\end{scala} -\end{frame} - - -\setbeamercolor{frametitle}{bg=\frametitleproblemcolor} -\begin{frame}[fragile]{Sequential Circuit Problem -- \tt Accumulator.scala} -\begin{itemize} -\item write sequential circuit that sums \code{in} values -\item in {\tt chisel-tutorial/problems/Accumulator.scala} -\item run {\tt make Accumulator.out} until passing -\end{itemize} -\begin{scala} -class Accumulator extends Module { - val io = new Bundle { - val in = UInt(INPUT, 1) - val out = UInt(OUTPUT, 8) - } - - // flush this out ... - - io.out := UInt(0) -} -\end{scala} -\end{frame} -\setbeamercolor{frametitle}{bg=\frametitledefaultcolor} - -\begin{frame}[fragile]{UInt Operations and Conditional Assignment} - -\begin{columns} -\column{0.5\textwidth} - -{\lstset{basicstyle={\tiny\ttfamily}} -\begin{scala} -class BasicALU extends Module { - val io = new Bundle { - val a = UInt(INPUT, 4) - val b = UInt(INPUT, 4) - val opcode = UInt(INPUT, 4) - val output = UInt(OUTPUT, 4) - } - io.output := UInt(0) - when (io.opcode === UInt(0)) { - io.output := io.a // pass A - } .elsewhen (io.opcode === UInt(1)) { - io.output := io.b // pass B - } .elsewhen (io.opcode === UInt(2)) { - io.output := io.a + UInt(1) // inc A by 1 - } .elsewhen (io.opcode === UInt(3)) { - io.output := io.a - UInt(1) // inc B by 1 - } .elsewhen (io.opcode === UInt(4)) { - io.output := io.a + UInt(4) // inc A by 4 - } .elsewhen (io.opcode === UInt(5)) { - io.output := io.a - UInt(4) // dec A by 4 - } .elsewhen (io.opcode === UInt(6)) { - io.output := io.a + io.b // add A and B - } .elsewhen (io.opcode === UInt(7)) { - io.output := io.a - io.b // sub B from A - } .elsewhen (io.opcode === UInt(8)) { - io.output := (io.a < io.b) // set on A < B - } .otherwise { - io.output := (io.a === io.b) // set on A == B - } -} -\end{scala} -} - -\column{0.4\textwidth} -\begin{itemize} -\item wire \code{io.output} defaulted to 0 and then -\item conditionally reassigned to based on opcode -\item unlike registers, wires are required to be defaulted -\item wires also allow forward declarations -\end{itemize} -\end{columns} -\end{frame} - -\begin{frame}[fragile]{UInt Operations} - -\begin{center} -\begin{tabular}{| c | c | c | } -\hline -Symbol & Operation & Output Type \\ \hline -\verb!+! & Add & UInt \\ \hline -\verb+-+ & Subtract & UInt \\ \hline -\verb+*+ & Multiply & UInt \\ \hline -\verb+/+ & UInt Divide & UInt \\ \hline -\verb+%+ & Modulo & UInt \\ \hline -\verb+~+ & Bitwise Negation & UInt \\ \hline -\verb+^+ & Bitwise XOR & UInt\\ \hline -\verb+&+ & Bitwise AND & UInt \\ \hline -\verb+|+ & Bitwise OR & Bool \\ \hline -\verb+===+ & Equal & Bool \\ \hline -\verb+!=+ & Not Equal & Bool \\ \hline -\verb+>+ & Greater & Bool \\ \hline -\verb+<+ & Less & Bool \\ \hline -\verb+>=+ & Greater or Equal & Bool \\ \hline -\verb+<=+ & Less or Equal & Bool \\ \hline -\end{tabular} -\end{center} - -\end{frame} - -\begin{frame}[fragile]{Bit Extraction} -\begin{scala} -// extracts the x through y bits of value -val x_to_y = value(x, y) -\end{scala} - -\begin{scala} -// extract the x-th bit from value -val x_of_value = value(x) -\end{scala} -\end{frame} - -\begin{frame}[fragile]{ByteSelector} - -\begin{scala} -class ByteSelector extends Module { - val io = new Bundle { - val in = UInt(INPUT, 32) - val offset = UInt(INPUT, 2) - val out = UInt(OUTPUT, 8) - } - io.out := UInt(0, width = 8) - when (io.offset === UInt(0)) { - io.out := io.in(7,0) // pull out lowest byte - } .elsewhen (io.offset === UInt(1)) { - io.out := io.in(15,8) // pull out second byte - } .elsewhen (io.offset === UInt(2)) { - io.out := io.in(23,16) // pull out third byte - } .otherwise { - io.out := io.in(31,24) // pull out highest byte - } -} -\end{scala} - -\end{frame} - -% \setbeamercolor{frametitle}{bg=\frametitleproblemcolor} -% \begin{frame}[fragile]{Instruction Decoder} -% -% {\lstset{basicstyle={\scriptsize\ttfamily}} -% \begin{scala} -% class LoadShiftRegister extends Module { -% val io = new Bundle { -% val inst = UInt(INPUT, 32) -% val rs0 = UInt(OUTPUT, 8) -% val rs1 = UInt(OUTPUT, 8) -% val rs2 = UInt(OUTPUT, 8) -% val isAdd = Bool(OUTPUT) -% val isSub = Bool(OUTPUT) -% val isMul = Bool(OUTPUT) -% val isDiv = Bool(OUTPUT) -% } -% io.isAdd := ... -% io.isSub := ... -% io.isMul := ... -% io.isDiv := ... -% io.rs0 := ... -% io.rs1 := ... -% io.rs2 := ... -% } -% \end{scala} -% } -% -% \end{frame} -% \setbeamercolor{frametitle}{bg=\frametitledefaultcolor} - -\begin{frame}[fragile]{Bit Concatenation and Filling} -You concatenating bits using \verb+Cat+: -\begin{scala} -val A = UInt(width = 32) -val B = UInt(width = 32) -val bus = Cat(A, B) // concatenate A and B -\end{scala} - -and replicate bits using \verb+Fill+: -\begin{scala} -// Replicate a bit string multiple times. -val usDebt = Fill(3, UInt("hA")) -\end{scala} - -\end{frame} - -\setbeamercolor{frametitle}{bg=\frametitleproblemcolor} -\begin{frame}[fragile]{LFSR16 -- \tt problems/lfsr16.scala} - -\begin{scala} -class LFSR16 extends Module { - val io = new Bundle { - val inc = Bool(INPUT) - val out = UInt(OUTPUT, 16) - } - // ... - io.out := UInt(0) -} -\end{scala} -\begin{itemize} -\item \verb+reg+, \verb+cat+, \verb+extract+, \verb+^+ -\item init reg to 1 -\item updates when \verb+inc+ asserted -\end{itemize} - -\begin{center} -\includegraphics[width=0.9\textwidth]{figs/LFSR16.pdf} -\end{center} - -\end{frame} -\setbeamercolor{frametitle}{bg=\frametitledefaultcolor} - -\begin{frame}[fragile]{UInt Bit Inference} -\begin{columns} -\column{0.4\textwidth} -\begin{scala} -class HiLoMultiplier() - extends Module { - val io = new Bundle { - val A = UInt(INPUT, 16) - val B = UInt(INPUT, 16) - val Hi = UInt(OUTPUT, 16) - val Lo = UInt(OUTPUT, 16) - } - val mult = io.A * io.B - io.Lo := mult(15, 0) - io.Hi := mult(31, 16) -} -\end{scala} - -\column{0.5\textwidth} - -{\lstset{basicstyle={\scriptsize\ttfamily}} -\begin{scala} -module HiLoMultiplier( - input [15:0] io_A, - input [15:0] io_B, - output[15:0] io_Hi, - output[15:0] io_Lo); - - wire[15:0] T0; - wire[31:0] mult; // inferred as 32 bits - wire[15:0] T1; - - assign io_Lo = T0; - assign T0 = mult[4'hf/*15*/:1'h0/*0*/]; - assign mult = io_A * io_B; - assign io_Hi = T1; - assign T1 = mult[5'h1f/*31*/:5'h10/*16*/]; -endmodule -\end{scala} -} - -\end{columns} - -\end{frame} - -\begin{frame}[fragile]{Bit Inference Rules} - -\begin{center} -\begin{tabular}{| l | l | l | } -\hline -Operation & Result Bit Width \\ \hline -\verb!Z = X + Y! & max(Width(X), Width(Y)) \\ \hline -\verb+Z = X - Y+ & max(Width(X), Width(Y)) \\ \hline -\verb+Z = X & Y+ & min(Width(X), Width(Y)) \\ \hline -\verb+Z = X | Y+ & max(Width(X), Width(Y)) \\ \hline -\verb+Z = X ^ Y+ & max(Width(X), Width(Y)) \\ \hline -\verb+Z = ~X+ & Width(X) \\ \hline -\verb+Z = Mux(C, X, Y)+ & max(Width(X), Width (Y)) \\ \hline -\verb+Z = X * Y+ & Width(X) + Width(Y) \\ \hline -\verb+Z = X << n+ & Width(X) + n \\ \hline -\verb+Z = X >> n+ & Width(X) - n \\ \hline -\verb+Z = Cat(X, Y)+ & Width(X) + Width(Y) \\ \hline -\verb+Z = Fill(n, x)+ & Width(X) + n \\ \hline -\end{tabular} -\end{center} - -\end{frame} - -\begin{frame}[fragile]{Bool Type} -The Chisel Bool is used to represent the result of logical expressions: -\begin{scala} -val change = io.a === io.b // change gets Bool type -when (change) { // execute if change is true - ... -} -\end{scala} - -You can instantiate a Bool value like this: -\begin{scala} -val true_value = Bool(true) -val false_value = Bool(false) -\end{scala} - -You can cast an UInt to a Bool as follows: -\begin{scala} -val bit = UInt(width = 1) ... -when (bit.toBool) { ... } -\end{scala} - -You can use a Bool as an UInt: -\begin{scala} -val bit = UInt(width = 1) ... -bit := a > b -\end{scala} - -\end{frame} - -\begin{frame}[fragile]{Bits Subtype Hierarchy} -\begin{itemize} -\item \verb+SInt+ is a signed integer type -\end{itemize} -\begin{center} -\includegraphics[height=0.7\textheight]{figs/bits-hierarchy.pdf} -\end{center} -\end{frame} - -\begin{frame}[fragile]{Bundles} - -\begin{columns} -\column{0.55\textwidth} -\begin{scala} -class MyFloat extends Bundle { - val sign = Bool() - val exponent = UInt(width = 8) - val significand = UInt(width = 23) -} - -val x = new MyFloat() -val xs = x.sign -\end{scala} - -\column{0.35\textwidth} - -\begin{center} -\includegraphics[height=0.9\textheight]{../cs250/figs/myfloat.pdf} -\end{center} - -\end{columns} -\end{frame} - -\begin{frame}[fragile]{Ports} - -\begin{columns} -\column{0.55\textwidth} - -\textbf{Data object with directions assigned to its members} - -\begin{scala} -class Decoupled extends Bundle { - val data = UInt(INPUT, 32) - val valid = Bool(OUTPUT) - val ready = Bool(INPUT) -} -\end{scala} - -\textbf{Direction assigned at instantiation time} - -\begin{scala} -class ScaleIO extends Bundle { - val in = new MyFloat().asInput - val scale = new MyFloat().asInput - val out = new MyFloat().asOutput -} -\end{scala} - -\column{0.35\textwidth} - -\begin{center} -\includegraphics[height=0.9\textheight]{../cs250/figs/fifoio.pdf} -\end{center} - -\end{columns} - -\end{frame} - -\begin{frame}[fragile]{Instantiating Modules} - -\begin{columns} - -\column{0.4\textwidth} - -{\lstset{basicstyle={\tiny\ttfamily}} -\begin{scala} -// A 4-bit adder with carry in and carry out -class Adder4 extends Module { - val io = new Bundle { - val A = UInt(INPUT, 4) - val B = UInt(INPUT, 4) - val Cin = UInt(INPUT, 1) - val Sum = UInt(OUTPUT, 4) - val Cout = UInt(OUTPUT, 1) - } - // Adder for bit 0 - val Adder0 = Module(new FullAdder()) - Adder0.io.a := io.A(0) - Adder0.io.b := io.B(0) - Adder0.io.cin := io.Cin - val s0 = Adder0.io.sum - // Adder for bit 1 - val Adder1 = Module(new FullAdder()) - Adder1.io.a := io.A(1) - Adder1.io.b := io.B(1) - Adder1.io.cin := Adder0.io.cout - val s1 = Cat(Adder1.io.sum, s0) - ... - // Adder for bit 3 - val Adder3 = Module(new FullAdder()) - Adder3.io.a := io.A(3) - Adder3.io.b := io.B(3) - Adder3.io.cin := Adder2.io.cout - io.Sum := Cat(Adder3.io.sum, s2) - io.Cout := Adder3.io.cout -} -\end{scala} -} - -\column{0.5\textwidth} - -\begin{center} -\includegraphics[width=0.9\textwidth]{../getting-started/figs/4_Bit_Adder.jpg} -\end{center} - -\begin{itemize} -\item inherits from \verb+Module+ class, -\item contains an interface stored in a port field named \verb+io+, and -\item wires together subcircuits in its constructor. -\end{itemize} - -\end{columns} - -\end{frame} - -\begin{frame}[fragile]{Vecs} -constructing vecs -\begin{scala} -val myVec1 = Vec.fill( ) { } -val myVec2 = Vec(, , ...) -\end{scala} - -creating a vec of wires -\begin{scala} -val ufix5_vec10 = Vec.fill(10) { UInt(width = 5) } -\end{scala} - - -creating a vec of regs -\begin{scala} -val reg_vec32 = Vec.fill(32){ Reg() } -\end{scala} - -writing -\begin{scala} -reg_vec32(1) := UInt(0) -\end{scala} - -reading -\begin{scala} -val reg5 = reg_vec(5) -\end{scala} - -\end{frame} - -\setbeamercolor{frametitle}{bg=\frametitleproblemcolor} -\begin{frame}[fragile]{Vec Shift Reg -- problems/VecShiftRegister.scala} - -\begin{itemize} -\item add loadability to shift register -\item change interface to use vec's -\end{itemize} - -{\lstset{basicstyle={\scriptsize\ttfamily}} -\begin{scala} -class VecShiftRegister extends Module { - val io = new Bundle { - val ins = Vec.fill(4){ UInt(INPUT, 1) } - val load = Bool(INPUT) - val shift = Bool(INPUT) - val out = UInt(OUTPUT, 1) - } - val delays = Vec.fill(4){ Reg(UInt()) } - when ( ...) { - // fill in here ... - } .elsewhen (io.shift) { - ... - } - io.out := delays(3) -} -\end{scala} -} - -\end{frame} -\setbeamercolor{frametitle}{bg=\frametitledefaultcolor} - -% \begin{frame}[fragile]{Scala Console} -% \begin{FramedVerb} -% \end{FramedVerb} -% \end{frame} - -\begin{frame}[fragile]{Defining a Tester} - -\begin{columns} -\column{0.45\textwidth} -{\lstset{basicstyle={\tiny\ttfamily}} -\begin{scala} -package Tutorial -import Chisel._ -import scala.collection.mutable.HashMap -import scala.util.Random - -class ByteSelector extends Module { - val io = new Bundle { - val in = UInt(INPUT, 32) - val offset = UInt(INPUT, 2) - val out = UInt(OUTPUT, 8) - } - io.out := UInt(0, width=8) - ... -} - -class ByteSelectorTests(c: ByteSelector) - extends Tester(c, Array(c.io)) { - defTests { - var allGood = true - val vars = new HashMap[Node, Node]() - val test_in = 12345678 - for (t <- 0 until 4) { - vars(c.io.in) = UInt(test_in) - vars(c.io.offset) = UInt(t) - val ref_out = - UInt((test_in >> (t * 8)) & 0xFF) - vars(c.io.out) = ref_out - allGood = step(vars) && allGood - } - allGood - } -} -\end{scala} -} -\column{0.45\textwidth} -{\lstset{basicstyle={\tiny\ttfamily}} -\begin{scala} -class Tester[T <: Module] - (val c: T, val testNodes: Array[Node]) - -def defTests(body: => Boolean) - -def step(vars: HashMap[Node, Node]): Boolean -\end{scala} -} -\begin{tiny} -\begin{itemize} -\item user subclasses \code{Tester} defining DUT and -\code{testNodes} and tests in \code{defTests} body -\item \code{vars} is mapping from \code{testNodes} to literals, called bindings -\item \code{step} runs test with given bindings, where -var values for input ports are sent to DUT, -DUT computes next outputs, and -DUT sends next outputs to Chisel -\item finally \code{step} compares received values against var values - for and returns false if any comparisons fail - output ports -\end{itemize} -\end{tiny} - -\begin{center} -\includegraphics[width=0.9\textwidth]{../tutorial/figs/DUT.pdf} -\end{center} - -\end{columns} -\end{frame} - -\begin{frame}[fragile]{Simulation Debug Output} - -{\lstset{basicstyle={\tiny\ttfamily}} -\begin{scala} -> cd chisel-tutorial/examples -> make ByteSelector.out -STARTING ../emulator/problems/ByteSelector ---- -INPUTS - INPUT(ByteSelector__io_in.ByteSelector) = 12345678 - INPUT(ByteSelector__io_offset.ByteSelector) = 0 -OUTPUTS - READ OUTPUT(ByteSelector__io_out.ByteSelector) = 78 - EXPECTED: OUTPUT(ByteSelector__io_out.ByteSelector) = 78 - SUCCESS ---- -INPUTS - INPUT(ByteSelector__io_in.ByteSelector) = 12345678 - INPUT(ByteSelector__io_offset.ByteSelector) = 1 -OUTPUTS - READ OUTPUT(ByteSelector__io_out.ByteSelector) = 97 - EXPECTED: OUTPUT(ByteSelector__io_out.ByteSelector) = 97 - SUCCESS ---- -... ---- -INPUTS - INPUT(ByteSelector__io_in.ByteSelector) = 12345678 - INPUT(ByteSelector__io_offset.ByteSelector) = 3 -OUTPUTS - READ OUTPUT(ByteSelector__io_out.ByteSelector) = 0 - EXPECTED: OUTPUT(ByteSelector__io_out.ByteSelector) = 0 - SUCCESS -PASSED // Final pass assertion -[success] Total time: 26 s, ... -\end{scala} -} - -\end{frame} - -\begin{frame}{Testbench Ingredients} - -\begin{itemize} -\item Define hash map for I/O and any initializations -\item Set inputs to device under test in hash map -\item Determine expected output for simulation advance for hash map -\item Advance simulation and track success/failure (ex. allGood) -\item Repeat until all appropriate test cases verified -\item Assert if test passed or failed (allGood) -\end{itemize} - -\end{frame} - -\setbeamercolor{frametitle}{bg=\frametitleproblemcolor} -\begin{frame}[fragile]{Testbench for MaxN -- \tt MaxN.scala} -\begin{columns} -\column{0.48\textwidth} - -\begin{itemize} -\item write a testbench for MaxN -\end{itemize} - -{\lstset{basicstyle={\scriptsize\ttfamily}} -\begin{scala} -class MaxN(val n: Int, val w: Int) - extends Module { - - def Max2(x: UInt, y: UInt) = - Mux(x > y, x, y) - - val io = new Bundle { - val ins = Vec.fill(n){ UInt(INPUT, w) } - val out = UInt(OUTPUT, w) - } - io.out := io.ins.reduceLeft(Max2) -} -\end{scala} -} -\begin{scala} -// returns random int in 0..lim-1 -val x = rnd.nextInt(lim) -\end{scala} - -\column{0.43\textwidth} - -{\lstset{basicstyle={\scriptsize\ttfamily}} -\begin{scala} -class MaxNTests(c: MaxN) - extends Tester(c, Array(c.io)) { - defTests { - var allGood = true - val vars = - new HashMap[Node, Node]() - val rnd = new Random() - for (i <- 0 until 10) { - vars.clear() - var mx = 0 - for (i <- 0 until c.n) { - // FILL THIS IN HERE - vars(c.io.ins(0)) = UInt(0) - } - // FILL THIS IN HERE - vars(c.io.out) = UInt(1) - allGood = step(vars) && allGood - } - allGood - } -} -\end{scala} -} -\end{columns} -\end{frame} -\setbeamercolor{frametitle}{bg=\frametitledefaultcolor} - -\begin{frame}[fragile]{Dynamically Accessed Vec} -\begin{scala} -class MemorySearch extends Module { - val io = new Bundle { - val target = UInt(INPUT, 4) - val en = Bool(INPUT) - val address = UInt(OUTPUT, 3) - val done = Bool(OUTPUT) - } - val index = Reg(init = UInt(0, width = 3)) - val list = Vec(UInt(0), UInt(4), UInt(15), UInt(14), - UInt(2), UInt(5), UInt(13)){ UInt(width = 4) } - val memVal = list(index) - val done = !io.en && ((memVal === io.target) || (index === UInt(7))) - when (io.en) { - index := UInt(0) - } .elsewhen (done === Bool(false)) { - index := index + UInt(1) - } - io.done := done - io.address := index -} -\end{scala} -\end{frame} - -\begin{frame}[fragile]{RAM} -RAM is supported using the \code{Mem} construct - -\begin{scala} -val m = Mem(Bits(width = 32), 32) -\end{scala} - -\noindent -where -\begin{itemize} -\item writes to Mems are positive-edge-triggered -\item reads are either combinational or positive-edge-triggered -\item ports are created by applying a \code{UInt} index -\end{itemize} -\end{frame} - -\begin{frame}[fragile]{32-entry Register File} - -\begin{scala} -val regs = Mem(Bits(width = 32), 32) -when (wrEn) { - regs(wrAddr) := wrData -} -val iDat = regs(iAddr) -val mDat = regs(mAddr) -\end{scala} - -\begin{center} -\includegraphics[height=0.55\textheight]{../cs250/figs/mem.pdf} -\end{center} - -\end{frame} - -\setbeamercolor{frametitle}{bg=\frametitleproblemcolor} -\begin{frame}[fragile]{Load/Search Mem -- \tt DynamicMemorySearch.scala} -\begin{scala} -class DynamicMemorySearch extends Module { - val io = new Bundle { - val isWr = Bool(INPUT) - val wrAddr = UInt(INPUT, 3) - val data = UInt(INPUT, 4) - val en = Bool(INPUT) - val target = UInt(OUTPUT, 3) - val done = Bool(OUTPUT) - } - val index = Reg(init = UInt(0, width = 3)) - val memVal = ... - val done = !io.en && ((memVal === io.target) || (index === UInt(7))) - // ... - when (io.en) { - index := UInt(0) - } .elsewhen (done === Bool(false)) { - index := index + UInt(1) - } - io.done := done - io.target := index -} -\end{scala} -\end{frame} -\setbeamercolor{frametitle}{bg=\frametitledefaultcolor} - -\begin{frame}[fragile]{Sequential Read Ports} -Sequential read ports are inferred when: -\begin{itemize} -\item optional parameter \code{seqRead} is set and -\item read address is a reg -\end{itemize} - -\begin{scala} -al ram1r1w = - Mem(UInt(width = 32), 1024, seqRead = true) -val reg_raddr = Reg(UInt()) -when (wen) { ram1r1w(waddr) := wdata } -when (ren) { reg_raddr := raddr } -val rdata = ram1r1w(reg_raddr) -\end{scala} - -\begin{center} -\includegraphics[height=0.4\textheight]{../cs250/figs/mem-seq-read.pdf} -\end{center} - -\end{frame} - -\begin{frame}[fragile]{Stack} - -{\lstset{basicstyle={\tiny\ttfamily}} -\begin{scala} -class Stack(depth: Int) extends Module { - val io = new Bundle { - val dataIn = UInt(INPUT, 32) - val dataOut = UInt(OUTPUT, 32) - val push = Bool(INPUT) - val pop = Bool(INPUT) - val en = Bool(INPUT) - } - // declare the memory for the stack - val stack_mem = Mem(UInt(width = 32), depth, seqRead = false) - val sp = Reg(init = UInt(0, width = log2Up(depth))) - val dataOut = Reg(init = UInt(0, width = 32)) - // Push condition - make sure stack isn't full - when(io.en && io.push && (sp != UInt(depth-1))) { - stack_mem(sp + UInt(1)) := io.dataIn - sp := sp + UInt(1) - } - // Pop condition - make sure the stack isn't empty - .elsewhen(io.en && io.pop && (sp > UInt(0))) { - sp := sp - UInt(1) - } - when(io.en) { - dataOut := stack_mem(sp) - } - io.dataOut := dataOut -} -\end{scala} -} - -\end{frame} - -\begin{frame}[fragile]{Scripting Hardware Generation} - -\begin{columns} -\column{0.5\textwidth} - -{\lstset{basicstyle={\tiny\ttfamily}} -\begin{scala} -// A n-bit adder with carry in and carry out -class Adder(n: Int) extends Module { - val io = new Bundle { - val A = UInt(INPUT, n) - val B = UInt(INPUT, n) - val Cin = UInt(INPUT, 1) - val Sum = UInt(OUTPUT, n) - val Cout = UInt(OUTPUT, 1) - } - // create a vector of FullAdders - val FAs = Vec.fill(n){ Module(new FullAdder()).io } - val carry = Vec.fill(n+1){ UInt(width = 1) } - val sum = Vec.fill(n){ Bool() } - - // first carry is the top level carry in - carry(0) := io.Cin - - // wire up the ports of the full adders - for(i <- 0 until n) { - FAs(i).a := io.A(i) - FAs(i).b := io.B(i) - FAs(i).cin := carry(i) - carry(i+1) := FAs(i).cout - sum(i) := FAs(i).sum.toBool() - } - io.Sum := sum.toBits().toUInt() - io.Cout := carry(n) -} -\end{scala} -} - -\column{0.4\textwidth} - -\begin{center} -\includegraphics[width=0.9\textwidth]{../getting-started/figs/4_Bit_Adder.jpg} -\end{center} -\end{columns} - -\end{frame} - -\input{../talks/microsoft/libs-to-langs-guts.tex} - -\setbeamercolor{frametitle}{bg=\frametitleproblemcolor} -\begin{frame}[fragile]{Mul Lookup Table Problem -- \tt Mul.scala} -\begin{itemize} -\item write 16x16 multiplication table using \code{Vec} -\end{itemize} -\begin{scala} -class Mul extends Module { - val io = new Bundle { - val x = UInt(INPUT, 4) - val y = UInt(INPUT, 4) - val z = UInt(OUTPUT, 8) - } - val muls = new ArrayBuffer[UInt]() - - // flush this out ... - - io.z := UInt(0) -} -\end{scala} - -hint: -\begin{scala} -val tab = Vec(muls) -io.z := tab(Cat(io.x, io.y)) -\end{scala} - -\end{frame} -\setbeamercolor{frametitle}{bg=\frametitledefaultcolor} - -\begin{frame}[fragile] -\frametitle{Valid Wrapper} - -\begin{columns} - -\column{0.65\textwidth} - -\begin{footnotesize} -\begin{scala} -class Valid[T <: Data](dtype: T) extends Bundle { - val data = dtype.clone.asOutput - val valid = Bool(OUTPUT) - override def clone = new Valid(dtype) -} - -class GCD extends Module { - val io = new Bundle { - val a = UInt(INPUT, 16) - val b = UInt(INPUT, 16) - val out = new Valid(UInt(OUTPUT, 16)) - } } - ... - io.out.data := x - io.out.valid := y === UInt(0) -} - -\end{scala} -\end{footnotesize} - -\column{0.3\textwidth} - -\begin{center} -\includegraphics[width=0.9\textwidth]{../talks/retreat-1/figs/valid.pdf} -\end{center} - -\end{columns} -\note{now gcd had a valid signal on its output. \\[1cm] -we can generalize this idea by defining a wrapper class that bundles a valid with a data signal. \\[1cm] -now we can rewrite GCD using an interface using this valid wrapper for its output. } - -\end{frame} - -\begin{frame}[fragile] -\frametitle{Function Filters} - -\begin{footnotesize} -\begin{scala} -abstract class Filter[T <: Data](dtype: T) extends Module { - val io = new Bundle { - val in = Valid(dtype).asInput - val out = Valid(dtype).asOutput -} } - -class FunctionFilter[T <: Data](dtype: T, f: T => T) extends Filter(dtype) { - io.out.valid := io.in.valid - io.out.bits := f(io.in) -} -\end{scala} -\end{footnotesize} - -\begin{center} -\includegraphics[height=0.4\textheight]{../talks/sketching13/figs/function-filter.pdf} -\end{center} - -\note{suppose we want to write hardware filters. \\[1cm] -one way to create a reusable filter would be \\[1cm] -to create a filter class that takes a function as argument that definines its filter operation.} - -\end{frame} - -\begin{frame}[fragile] -\frametitle{Clipping Filter} - -\begin{footnotesize} -\begin{scala} -def clippingFilter[T <: Bits](limit: Int, dtype: T) = - new FunctionFilter(dtype, x => min(limit, max(-limit, x))) -\end{scala} -\end{footnotesize} - -\begin{center} -\includegraphics[height=0.4\textheight]{../talks/retreat-1/figs/clipping-filter.pdf} -\end{center} -\note{using this reusable substrate then it is easy to create an instance of a filter.} -\end{frame} - - -\begin{frame}[fragile] -\frametitle{Shifting Filter} - -\begin{footnotesize} -\begin{scala} -def shiftingFilter[T <: Bits](shift: Int, dtype: T) = - new FunctionFilter(dtype, x => x >> shift) -\end{scala} -\end{footnotesize} - -\begin{center} -\includegraphics[height=0.4\textheight]{../talks/retreat-1/figs/shifting-filter.pdf} -\end{center} -\note{and reuse it for shift filter} -\end{frame} - -\begin{frame}[fragile]{Testing Decoupled Circuits} - -\begin{itemize} -\item using ovars for outputs -\item need to check outputs directly using \verb+litValue+ -\end{itemize} -\begin{scala} -class GCDTests(c: GCD) extends Tester(c, Array(c.io)) { - defTests { - val (a, b, z) = (64, 48, 16) - val svars = new HashMap[Node, Node]() - val ovars = new HashMap[Node, Node]() - var t = 0 - do { - svars(c.io.a) = UInt(a) - svars(c.io.b) = UInt(b) - step(svars, ovars) - t += 1 - } while (t <= 1 || ovars(c.io.v).litValue() == 0) - ovars(c.io.z).litValue() == z - } -} -\end{scala} - -\end{frame} - -\begin{frame}[fragile] -\frametitle{Chained Filter} - -\begin{footnotesize} -\begin{scala} -class ChainedFilter[T <: Num](dtype: T) extends Filter(dtype) = { - val shift = Module(new ShiftFilter(2, dtype)) - val clipper = Module(new ClippingFilter(1 << 7, dtype)) - io.in <> shift.io.in - shift.io.out <> clipper.io.in - clipper.io.out <> io.out -} -\end{scala} -% \begin{scala} -% class ChainedFilter[T <: Num](dtype: T) extends Filter(dtype) = { -% val fir = new TstFIR(dtype) -% val shift = new ShiftFilter(2, dtype) -% val clipper = new ClippingFilter(1 << 7, dtype) -% io.in <> fir.io.in -% fir.io.out <> shift.io.in -% shift.io.out <> clipper.io.in -% clipper.io.out <> io.out -% } -% \end{scala} -\end{footnotesize} - -\begin{center} -\includegraphics[height=0.4\textheight]{../talks/sketching13/figs/chained-filter2.pdf} -\end{center} -\note{and chain together...} -\end{frame} - -\begin{frame}[fragile]{Predicate Filter} -\begin{scala} -class PredicateFilter[T <: Data](dtype: T, f: T => Bool) - extends Filter(dtype) { - io.out.valid := io.in.valid && f(io.in.bits) - io.out.bits := io.in.bits -} -\end{scala} - -\begin{center} -\includegraphics[height=0.4\textheight]{figs/predicate-filter.pdf} -\end{center} -\end{frame} - -\setbeamercolor{frametitle}{bg=\frametitleproblemcolor} -\begin{frame}[fragile]{Predicate Filtering -- \tt SingleEvenFilter.scala} -\begin{itemize} -\item write filter that lets only even single digit numbers through -\end{itemize} -\begin{scala} -object SingleFilter { - def apply[T <: UInt](dtype: T) = // FILL IN FUNCTION BELOW - Module(new PredicateFilter(dtype, (x: T) => Bool(false))) -} - -object EvenFilter { - def apply[T <: UInt](dtype: T) = // FILL IN FUNCTION BELOW - Module(new PredicateFilter(dtype, (x: T) => Bool(false))) -} - -class SingleEvenFilter[T <: UInt](dtype: T) extends Filter(dtype) { - // FILL IN CONSTRUCTION AND WIRING - io.out := UInt(0) -} -\end{scala} -\end{frame} -\setbeamercolor{frametitle}{bg=\frametitledefaultcolor} - -\begin{frame}[fragile, shrink] -\frametitle{Functional Composition} - -% \begin{itemize} -% \item natural -% \item reusable -% \item composable -% \end{itemize} -% \vskip1cm - -\begin{Large} -\begin{columns} - -\column{0.45\textwidth} -\verb+Map(ins, x => x * y)+ \\ -\begin{center} -\includegraphics[height=0.6\textheight]{../bootcamp/figs/map.pdf} \\[2cm] -\end{center} - -\column{0.45\textwidth} -\vskip2mm -\verb+Chain(n, in, x => f(x))+ \\ -\begin{center} -\includegraphics[width=0.9\textwidth]{../bootcamp/figs/chain.pdf} \\ -\end{center} - -\verb+Reduce(ins, Max)+ \\ -\begin{center} -\includegraphics[width=0.9\textwidth]{../bootcamp/figs/reduce.pdf} \\ -\end{center} - -\end{columns} - -\end{Large} -\note{the previous example showed a simple use of functional programming. \\[1cm] -Scala provides strong support for functional programming and -it turns out that functional programming is a powerful way to define hardware. \\[1cm] -for example, you can create a parallel set of blocks using map and reduce to creation reduction trees and chain to create a pipeline.} -\end{frame} - -\begin{frame}[fragile]{Map / Reduce Generator} -\begin{footnotesize} -\begin{scala} -def delays[T <: Data](x: T, n: Int): List[T] = - if (n <= 1) List(x) else x :: taps(Reg(next = x), n-1) - -def FIR[T <: Num](hs: Seq[T], x: T): T = - (hs, delays(x, hs.length)).zipped.map( _ * _ ).reduce( _ + _ ) - -class TstFIR extends Module { - val io = new Bundle{ val x = SInt(INPUT, 8); val y = SInt(OUTPUT, 8) } - val h = Array(SInt(1), SInt(2), SInt(4)) - io.y := FIR(h, io.x) -} -\end{scala} -\end{footnotesize} -\begin{center} -\includegraphics[height=0.35\textheight]{../cs294-88/lectures/advanced-chisel/figs/inner-product-fir.png} -\end{center} -\note{as an advanced example, consider writing an FIR filter which is defined by the equation below. \\[1cm] -essentially it's a sum of products of coefficients and delayed versions of input.\\[1cm] -we can write this quite simply using map and reduce as above.} -\end{frame} - -\begin{frame}[fragile]{Chisel Standard Library -- \tt ChiselUtil.scala} -\begin{center} -\begin{tabular}{rl} -{\bf Bits Properities} & \code{log2Up}, \code{log2Down}, \code{isPow2}, \code{PopCount}\\ -{\bf Numeric Utilities} & \code{LFSR16}, \code{Reverse}, \code{FillInterleaved} \\ -{\bf Stateful Functions} & \code{ShiftRegister}, \code{Counter} \\ -{\bf Priority Encoding Functions} & \code{UIntToOH}, \code{OHToUInt}, \code{Mux1H} \\ -{\bf Priority Encoders} & \code{PriorityEncoder}, \code{PriorityEncoderOH} \\ -{\bf Vec Construction} & \code{Vec.fill}, \code{Vec.tabulate} \\ -{\bf Vec Functional} & \code{forall}, \code{exists}, \code{contains}, ... \\ -{\bf Queues and Pipes} & \code{Decoupled}, \code{Queue}, \code{Valid}, \code{Pipe} \\ -{\bf Arbiters} & \code{ArbiterIO}, \code{Arbiter}, \code{RRArbiter} \\ -\end{tabular} -\end{center} -\end{frame} - -\begin{frame}[fragile] -\frametitle{Queues} -\begin{itemize} -\item Required parameter \verb+entries+ controls depth -\item The width is determined from the inputs. -\end{itemize} -\begin{scala} -class QueueIO[T <: Data](type: T, entries: Int) extends Bundle { - val enq = Decoupled(data.clone).flip - val deq = Decoupled(data.clone) - val count = UFix(OUTPUT, log2Up(entries+1)) -} - -class Queue[T <: Data] - (type: T, entries: Int, - pipe: Boolean = false, - flow: Boolean = false - flushable: Boolean = false) - extends Module -\end{scala} -\begin{scala} -val q = new Queue(UInt(), 16) -q.io.enq <> producer.io.out -consumer.io.in <> q.io.deq -\end{scala} -\end{frame} - -\begin{frame}[fragile]{Multiple Clock Domains} -Clocks are first class and take an optional reset signal: -\begin{scala} -class Clock (reset: Bool) extends Node { - def reset: Bool // returns reset pin -} -\end{scala} - -There is a builtin implicit clock that state elements use by default: -\begin{scala} -var implicitClock = new Clock( implicitReset ) -\end{scala} - -Clocks can be defined from other clocks: -\begin{scala} -val clock2 = clock1 * 2 -val clock3 = clock1 / 2 -\end{scala} - -\end{frame} - -\begin{frame}[fragile]{Specifying a Clock Domain} -The clock for state elements and modules can be specified: -\begin{scala} -Reg(... clock: Clock = implicitClock) -Mem(... clock: Clock = implicitClock) -Module(... clock: Clock = implicitClock) -\end{scala} - -For example, a register can be created in a different clock domain as follows: -\begin{scala} -val reg = Reg(UInt(), clock = clock2) -\end{scala} - -\end{frame} - -\begin{frame}[fragile]{Crossing Clock Domains} -The most general technique to send data between domains is using an asynchronous queue: - -\begin{scala} -class AsyncQueue[T <: Data] - (dataType: T, depth: Int, enq_clk: Clock, deq_clock: Clock) extends Module -\end{scala} - -Using these queues, we can then move a signalA from clock domains clockA to signalB in clockB: - -\begin{scala} -val queue = new AsyncQueue(Uint(width = 32), 2, clockA, clockB) -fifo.enq.bits := signalA -signalB := fifo.deq.bits -fifo.valid := condA -fifo.ready := condB -... -\end{scala} - -\end{frame} - -\begin{frame}[fragile]{Multiple Clocks -- \tt MultipleClockDomains.scala} -\begin{scala} -class MultiClockDomain extends Module { - val io = new Bundle { - val start = Bool(INPUT) - val sum = Decoupled(UInt(OUTPUT)) - } - val fastClock = new Clock() - val slowClock = new Clock() - ... -} - -class MultiClockDomainTests(c: MultiClockDomain) - extends Tester(c, Array(c.io)) { - defTests { - val clocks = new HashMap[Clock, Int] - clocks(Module.implicitClock) = 2 - clocks(c.fastClock) = 4 - clocks(c.slowClock) = 6 - setClocks(clocks) - ... - } -} -\end{scala} -\end{frame} - -\begin{frame}[fragile]{Creating Your Own Project} -directory structure -\begin{bash} -Hello/ - build.sbt # scala configuration file - Hello.scala # your source file -\end{bash} - -\end{frame} - -\begin{frame}[fragile]{Writing Your Source File} - -{\lstset{basicstyle={\scriptsize\ttfamily}} -\begin{scala} -package Hello -import Chisel._ -import scala.collection.mutable.HashMap - -class Hello extends Module { - val io = new Bundle { - val out = UInt(OUTPUT, 8) } - io.out := UInt(33) -} - -class HelloTests(c: Hello) extends Tester(c, Array(c.io)) { - defTests { - val vars = new HashMap[Node, Node]() - vars(c.io.out) = UInt(33) - step(vars) - } -} - -object Hello { - def main(args: Array[String]): Unit = { - val args = Array("--backend", "c", "--genHarness", "--compile", "--test") - chiselMainTest(args, () => Module(new Hello())) { - c => new HelloTests(c) } -} } -\end{scala} -} - -\end{frame} - -\begin{frame}[fragile]{Setting Up Your SBT Configuration File} -\begin{scala} -scalaVersion := "2.10.2" - -addSbtPlugin("com.github.scct" % "sbt-scct" % "0.2") - -libraryDependencies += - "edu.berkeley.cs" %% "chisel" % "latest.release" -\end{scala} -\end{frame} - -\begin{frame}[fragile]{Compiling and Running} -Producing C++ -\begin{bash} -sbt run --backend c -\end{bash} - -Producing Verilog -\begin{bash} -sbt run --backend v -\end{bash} - -Running the Chisel Tests -\begin{bash} -sbt run --backend c --compile --test --genHarness -\end{bash} - -\end{frame} - -\begin{frame}[fragile]{chiselMain(Test) Command Line Arguments} -\begin{scala} -sbt -sbt> compile // compiles Chisel Scala code -sbt> run // compile and run Chisel Scala Code -sbt> run --backend c // produces C++ files -sbt> exit -\end{scala} - -with a complete set of command line arguments being:\\[2mm] - -\begin{tabular}{lll} -\verb+--backend v+ & generate verilog \\ -\verb+--backend c+ & generate C++ (default)\\ -\verb+--vcd+ & enable vcd dumping \\ -\verb+--targetDir+ & target pathname prefix \\ -\verb+--genHarness+ & generate harness file for C++ \\ -\verb+--debug+ & put all wires in C++ class file \\ -\verb+--compile+ & compiles generated C++ \\ -\verb+--test+ & runs tests using C++ app \\ -\end{tabular} -\end{frame} - -\setbeamercolor{frametitle}{bg=\frametitleproblemcolor} -\begin{frame}[fragile]{Make Your Own Project} -set hello project up -\begin{bash} -cd ~ -mkdir hello -cp ~/chisel-tutorial/hello/* hello -cd hello -sbt run -\end{bash} -make a change -\begin{itemize} -\item make output a function of an new input -\end{itemize} -\end{frame} -\setbeamercolor{frametitle}{bg=\frametitledefaultcolor} - -\begin{frame}{Chisel Workflow} -\begin{center} -\includegraphics[height=0.9\textheight]{../bootcamp/figs/chisel-workflow.pdf} -\end{center} -\end{frame} - -\begin{frame}[fragile]{printf / sprintf} -\begin{itemize} -\item during simulation -\begin{itemize} -\item \verb+printf+ prings the formatted string to the console on rising clock edges -\item \verb+sprintf+ returns the formatted string as a bit vector -\end{itemize} -\item format specifiers are -\begin{itemize} -\item \verb+%b+ -- binary number -\item \verb+%d+ -- decimal number -\item \verb+%x+ -- hexidecimal number -\item \verb+%s+ -- string consisting of a sequence of 8-bit extended ASCII chars -\item \verb+%%+ -- specifies a literal %. -\end{itemize} -\end{itemize} -the following prints the line \verb+"0x4142 16706 AB"+ on cycles when \verb+c+ is true: -\begin{scala} -val x = Bits(0x4142) -val s1 = sprintf("%x %s", x, x); -when (c) { printf("%d %s\n", x, s1); } -\end{scala} -\end{frame} - -\begin{frame}[fragile]{assert} -\begin{itemize} -\item simulation time assertions are provided by \verb+assert+ construct -\item if assert arguments false on rising edge then -\begin{itemize} -\item an error is printed and -\item simulation terminates -\end{itemize} -\end{itemize} -the following will terminate after 10 clock cycles: -\begin{scala} -val x = Reg(init = UInt(0, 4)) -x := x + UInt(1) -assert(x < UInt(10)) -\end{scala} -\end{frame} - -\begin{frame}[fragile]{Installation} -\begin{itemize} -\item on mac install: -\begin{itemize} -\item XCODE console tools -\end{itemize} -\item on windows install: -\begin{itemize} -\item cygwin -\end{itemize} -\item everywhere install: -\begin{itemize} -\item git -\item g++ version 4.0 or later -\item java -\end{itemize} -\item everywhere -\begin{itemize} -\item git clone https://github.com/ucb-bar/chisel-tutorial.git -\end{itemize} -\end{itemize} - -\end{frame} - -\begin{frame}[fragile]{Chisel Resources} -\begin{center} -\url{https://chisel.eecs.berkeley.edu/documentation.html} \\[0.25cm] -\begin{tabular}{rl} -\textbf{manual} & \code{manual.pdf} \\ -\textbf{bootcamp2012} & \code{bootcamp-20121026.pdf} \\ -\textbf{bootcamp2013} & \code{bootcamp-20130930.pdf} \\ -\textbf{tutorial} & \code{tutorial.pdf} \\ -\textbf{getting started} & \code{getting-started.pdf} \\ -\textbf{cs250 lectures} & \code{cs250-1.pdf}, \code{cs250-2.pdf}, \code{cs250-3.pdf} \\[0.5cm] -\end{tabular} -\url{https://github.com/ucb-bar/chisel/} \\[0.25cm] -\begin{tabular}{rl} -\textbf{setup} & \code{readme.md} \\ -\textbf{utils} & \code{src/main/scala/ChiselUtils.scala} \\[0.5cm] -\end{tabular} -\url{https://chisel.eecs.berkeley.edu/download.html} \\[0.25cm] -\begin{tabular}{rl} -\textbf{sodor} & \url{https://github.com/ucb-bar/sodor/} \\ -\textbf{virtualbox} & \url{https://chisel.eecs.berkeley.edu/chisel-riscv.box} \\ -\end{tabular} -\end{center} -\end{frame} - -\begin{frame}{Scala Resources} - -\begin{center} -\includegraphics[height=0.4\textheight]{../bootcamp/figs/programming-scala.pdf} \\ -\includegraphics[height=0.4\textheight]{../bootcamp/figs/programming-in-scala.pdf} -\end{center} - -\end{frame} - -\begin{frame}[fragile]{Projects Ideas} - -\begin{center} -\begin{tabular}{rl} -\textbf{audio processing} & \code{Echo.scala} \\ -\textbf{image processing} & \code{Darken.scala} \\ -\textbf{risc processor} & \code{Risc.scala} \\ -\textbf{game of life} & \code{Life.scala} \\ -\textbf{router} & \code{Router.scala} \\ -\textbf{map/reduce} & \code{FIR.scala}\\ -\textbf{network} & \\ -\textbf{decoupled filter} & \\ -\textbf{cryptography} & \\ -\textbf{serial multiplier} & \\ -\textbf{pong} & \\ -\end{tabular} -\end{center} - -\end{frame} - -\begin{frame}[fragile]{Keep in Touch} -\begin{center} -\begin{tabular}{rl} -\textbf{website} & \url{chisel.eecs.berkeley.edu} \\ -\textbf{mailing list} & \url{groups.google.com/group/chisel-users} \\ -\textbf{github} & \url{https://github.com/ucb-bar/chisel/} \\ -\textbf{features + bugs} & \url{https://github.com/ucb-bar/chisel/issues} \\ -\textbf{more questions} & \url{stackoverflow.com/quesions/tagged/chisel} \\ -\textbf{twitter} & {\tt \#chiselhdl} \\ -\textbf{me} & \url{jrb@eecs.berkeley.edu} \\ -\end{tabular} -\end{center} -\end{frame} - -\begin{frame}{Thanks} -\begin{itemize} -\item \textbf{Arrangements} -- Roxana and Kostas -\item \textbf{EC2 configuration} -- Sebastien Mirolo -\item \textbf{Bootcamp Materials} -- Vincent Lee, Stephen Twigg, Huy Vo -\item \textbf{Funding} -- Department of Energy, Department of Defense -\end{itemize} -\end{frame} - -\end{document} diff --git a/doc/bootcamp/bootcamp-20140206.tex b/doc/bootcamp/bootcamp-20140206.tex deleted file mode 100644 index 0f44891c..00000000 --- a/doc/bootcamp/bootcamp-20140206.tex +++ /dev/null @@ -1,2339 +0,0 @@ -\documentclass[xcolor=pdflatex,dvipsnames,table]{beamer} -\usepackage{epsfig,graphicx} -\usepackage{palatino} -\usepackage{fancybox} -\usepackage{relsize} -\usepackage[procnames]{listings} - -\input{../style/scala.tex} -\input{../style/talk.tex} - -\title{Chisel Bootcamp 4} -\author{Jonathan Bachrach} -\date{\today} -\institute[UC Berkeley]{EECS UC Berkeley} - -\begin{document} - -\begin{frame} -\titlepage -\end{frame} -\addtocounter{framenumber}{-1} - -% \begin{frame}[fragile]{tutorial.scala} -% \begin{scala} -% package Tutorial { -% -% import Chisel._ -% -% object Tutorial { -% def main(args: Array[String]): Unit = { -% val tut_args = args.slice(1, args.length) ++ -% Array("--targetDir", "../emulator", "--genHarness") -% args(0) match { -% case "gcd" => -% chiselMain(tut_args, () => new GCD()) -% ... -% } -% } -% } -% -% } -% \end{scala} -% \end{frame} - -\begin{frame}[fragile]{Goals for Bootcamp} - -\begin{itemize} -\item get you started with Chisel -\item get a basic working knowledge of Chisel -\item learn how to think in Chisel -\item know where to get more information -\end{itemize} - -\end{frame} - -\begin{frame}[fragile]{CS291C Specific Notes for Bootcamp} - -\begin{itemize} -\item teaching digital circuit design in chisel -\item will later teach -\begin{itemize} -\item floating point -\item fixed point -\item complex numbers -\item integration with matlab -\end{itemize} -\item new chisel release with DSP support coming soon -\end{itemize} - -\end{frame} - - -\setbeamercolor{frametitle}{bg=\frametitleproblemcolor} -\begin{frame}[fragile]{Logging into EC2} - -\begin{scala} -ssh ubuntu@xxx -password: bootcamp -\end{scala} -\noindent -where \code{xxx} corresponds to your EC2 instance written on your airbears slip - -\end{frame} -\setbeamercolor{frametitle}{bg=\frametitledefaultcolor} - -\setbeamercolor{frametitle}{bg=\frametitleproblemcolor} -\begin{frame}[fragile]{Using Screen} -to prevent lossage of state if disconnected ... when you first log in, type -\begin{scala} -screen -\end{scala} - -when you log back into the instance, type -\begin{scala} -screen -r -\end{scala} - -\end{frame} -\setbeamercolor{frametitle}{bg=\frametitledefaultcolor} - -\setbeamercolor{frametitle}{bg=\frametitleproblemcolor} -\begin{frame}[fragile]{Getting the Latest} - -if you don't have chisel-tutorial already -\begin{scala} -git clone https://github.com/ucb-bar/chisel-tutorial.git -cd chisel-tutorial -\end{scala} - -else, get the latest -\begin{scala} -cd chisel-tutorial -git pull -\end{scala} - -\end{frame} -\setbeamercolor{frametitle}{bg=\frametitledefaultcolor} - -\begin{frame}[fragile]{chisel-tutorial repo} -\begin{FramedSemiVerb} -chisel-tutorial/ - Makefile - examples/ \comment{\# Contains chisel examples} - Makefile - build.sbt \comment{\# Contains project description} - FullAdder.scala ... - problems/ \comment{\# Contains skeletal files for tutorial problems} - Makefile - build.sbt \comment{\# Contains project description} - Accumulator.scala ... - solutions/ \comment{\# Contains solutions to problems} - Makefile - build.sbt \comment{\# Contains project description} - Counter.scala ... -\end{FramedSemiVerb} -\end{frame} - -\setbeamercolor{frametitle}{bg=\frametitleproblemcolor} -\begin{frame}[fragile]{Get This} - -\begin{center} -\fbox{ -\url{chisel.eecs.berkeley.edu/2.0.6/chisel-bootcamp-20140206.pdf} -} -\end{center} - -\end{frame} -\setbeamercolor{frametitle}{bg=\frametitledefaultcolor} - -\begin{frame}[fragile] -\frametitle{Chisel} - -\begin{columns}[c] - -\column{0.55\textwidth} - -\begin{itemize} -\item A hardware construction language -\begin{itemize} -\item ``synthesizable by construction'' -\item creates graph representing hardware -\end{itemize} -\item Embedded within Scala language to leverage mindshare and language design -\item Best of hardware and software design ideas -\item Multiple targets -\begin{itemize} -\item Simulation and synthesis -\item Memory IP is target-specific \\[0.5cm] -\end{itemize} -\item {\color{red}{\bf Not} Scala app -> Verilog arch} -\end{itemize} - -\column{0.40\textwidth} - -\begin{center} -single source \\ -\includegraphics[width=0.99\textwidth]{../talks/retreat-1/figs/graph-and-targets.pdf} \\ -multiple targets \\ -\end{center} - -\end{columns} -\note{creates a graph if successfully created will correctly synthesize \\[1cm] -single source generates two different verilog outputs, one for fpga and one for asic. \\[1cm] -surprisingly difficult to generate each. for example, chisel has abstraction for memories.} -\end{frame} - -\begin{frame}[fragile] -\frametitle{The Scala Programming Language} - -\begin{columns}[c] - -\column{0.75\textwidth} - -\begin{itemize} -\item Object Oriented -\begin{itemize} -\item Factory Objects, Classes -\item Traits, overloading etc -\item Strongly typed with type inference -\end{itemize} -\item Functional -\begin{itemize} -\item Higher order functions -\item Anonymous functions -\item Currying etc -\end{itemize} -\item Extensible -\begin{itemize} -\item Domain Specific Languages (DSLs) -\end{itemize} -\item Compiled to JVM -\begin{itemize} -\item Good performance -\item Great Java interoperability -\item Mature debugging, execution environments -\end{itemize} -\item Growing Popularity -\begin{itemize} -\item Twitter -\item many Universities -\end{itemize} -\end{itemize} - -\column{0.25\textwidth} - -\begin{center} -\includegraphics[height=0.4\textheight]{figs/programming-scala.pdf} \\ -\includegraphics[height=0.4\textheight]{figs/programming-in-scala.pdf} -\end{center} - -\end{columns} -\note{powerful combination of scipting and type safety, \\[1cm] -includes powerful features to support abstraction, \\[1cm] -as makes it easy to embed DSLs, compiles to jvm} -\end{frame} - -\include{scala-intro} - -\begin{frame}[fragile] -\frametitle{Algebraic Graph Construction} - -\begin{columns} -\column{0.35\textwidth} -{\lstset{basicstyle={\Large\ttfamily}} -\begin{scala} -Mux(x > y, x, y) -\end{scala} -} - -\column{0.6\textwidth} - -\begin{center} -\includegraphics[width=0.9\textwidth]{figs/max2.pdf} -\end{center} -\end{columns} -\end{frame} - -\begin{frame}[fragile] -\frametitle{Creating Module} - -\begin{columns} -\column{0.45\textwidth} - -{\lstset{basicstyle={\scriptsize\ttfamily}} -\begin{scala} -class Max2 extends Module { - val io = new Bundle { - val x = UInt(INPUT, 8) - val y = UInt(INPUT, 8) - val z = UInt(OUTPUT, 8) } - io.z := Mux(io.x > io.y, io.x, io.y) -} -\end{scala} -} - -\column{0.45\textwidth} -\begin{center} -\includegraphics[width=0.95\textwidth]{figs/Max2c.pdf} \\ -\end{center} -\end{columns} - -\end{frame} - -\begin{frame}[fragile] -\frametitle{Connecting Modules} - -\begin{columns} -\column{0.3\textwidth} -\begin{scala} -val m1 = - Module(new Max2()) -m1.io.x := a -m1.io.y := b -val m2 = - Module(new Max2()) -m2.io.x := c -m2.io.y := d -val m3 = - Module(new Max2()) -m3.io.x := m1.io.z -m3.io.y := m2.io.z -\end{scala} - -\column{0.6\textwidth} - -\begin{center} -\includegraphics[width=0.99\textwidth]{figs/Max4.pdf} \\ -\end{center} -\end{columns} - -\end{frame} - - -\begin{frame}[fragile] -\frametitle{Defining Construction Functions} - -\begin{columns} - -\column{0.45\textwidth} - -\begin{scala} -def Max2(x, y) = Mux(x > y, x, y) -\end{scala} -\begin{scala} -Max2(x, y) -\end{scala} - -\column{0.5\textwidth} - -\begin{center} -\includegraphics[width=0.95\textwidth]{figs/Max2.pdf} \\[1cm] -\end{center} - -\end{columns} - -\end{frame} - -\begin{frame}[fragile] -\frametitle{Functional Construction} - -\begin{columns} - -\column{0.5\textwidth} - -{\lstset{basicstyle={\scriptsize\ttfamily}} -\begin{scala} -class MaxN(n: Int, w: Int) extends Module { - val io = new Bundle { - val in = Vec.fill(n){ UInt(INPUT, w) } - val out = UInt(OUTPUT, w) - } - io.out := io.in.reduceLeft(Max2) -} -\end{scala} -} - -\column{0.4\textwidth} - -\begin{center} -\includegraphics[width=0.99\textwidth]{figs/reduceMax.pdf} \\ -\end{center} - -\end{columns} - -\end{frame} - -\begin{frame}[fragile] -\frametitle{Example} -\begin{columns} - -\column{0.45\textwidth} - -\begin{footnotesize} -\begin{scala} -class GCD extends Module { - val io = new Bundle { - val a = UInt(INPUT, 16) - val b = UInt(INPUT, 16) - val z = UInt(OUTPUT, 16) - val valid = Bool(OUTPUT) } - val x = Reg(init = io.a) - val y = Reg(init = io.b) - when (x > y) { - x := x - y - } .otherwise { - y := y - x - } - io.z := x - io.valid := y === UInt(0) -} -\end{scala} -\end{footnotesize} - -\column{0.45\textwidth} - -\begin{center} -\includegraphics[width=0.9\textwidth]{figs/gcd.pdf} -\end{center} - -\end{columns} -\end{frame} - -\setbeamercolor{frametitle}{bg=\frametitleproblemcolor} -\begin{frame}[fragile]{Running the Chisel Simulation} - -\begin{bash} -cd ~/chisel-tutorial/examples -make GCD.out -\end{bash} - -{\lstset{basicstyle={\scriptsize\ttfamily}} -\begin{bash} -... -PASSED -[success] Total time: 2 s, completed Feb 28, 2013 8:14:37 PM -\end{bash} -} - -\end{frame} -\setbeamercolor{frametitle}{bg=\frametitledefaultcolor} - -\setbeamercolor{frametitle}{bg=\frametitleproblemcolor} -\begin{frame}[fragile]{Generating Verilog} - -\begin{bash} -cd ~/chisel-tutorial/examples -make GCD.v -\end{bash} - -The Verilog source is roughly divided into three parts: - -\begin{enumerate} -\item Module declaration with input and outputs -\item Temporary wire and register declaration used for holding intermediate values -\item Register assignments in \verb+always @ (posedge clk)+ -\end{enumerate} - -\end{frame} -\setbeamercolor{frametitle}{bg=\frametitledefaultcolor} - -\begin{frame}[fragile]{FullAdder -- Type Inference} - -\begin{columns} -\column{0.4\textwidth} - -{\lstset{basicstyle={\scriptsize\ttfamily}} -\begin{scala} -class FullAdder extends Module { - val io = new Bundle { - val a = UInt(INPUT, 1) - val b = UInt(INPUT, 1) - val cin = UInt(INPUT, 1) - val sum = UInt(OUTPUT, 1) - val cout = UInt(OUTPUT, 1) - } - // Generate the sum - val a_xor_b = io.a ^ io.b - io.sum := a_xor_b ^ io.cin - // Generate the carry - val a_and_b = io.a & io.b - val b_and_cin = io.b & io.cin - val a_and_cin = io.a & io.cin - io.cout := - a_and_b | b_and_cin | a_and_cin -} -\end{scala} -} - -\column{0.55\textwidth} - -\begin{center} -\includegraphics[width=0.9\textwidth]{../getting-started/figs/Full_Adder.jpg} -\end{center} - -\end{columns} - -\end{frame} - -\begin{frame}[fragile]{FullAdder Verilog -- Width Inference 1} - -\begin{columns} -\column{0.45\textwidth} - -{\lstset{basicstyle={\scriptsize\ttfamily}} -\begin{scala} -class FullAdder extends Module { - val io = new Bundle { - val a = UInt(INPUT, 1) - val b = UInt(INPUT, 1) - val cin = UInt(INPUT, 1) - val sum = UInt(OUTPUT, 1) - val cout = UInt(OUTPUT, 1) - } - // Generate the sum - val a_xor_b = io.a ^ io.b - io.sum := a_xor_b ^ io.cin - // Generate the carry - val a_and_b = io.a & io.b - val b_and_cin = io.b & io.cin - val a_and_cin = io.a & io.cin - io.cout := - a_and_b | b_and_cin | a_and_cin -} -\end{scala} -} - -\column{0.45\textwidth} - -{\lstset{basicstyle={\scriptsize\ttfamily}} -\begin{scala} -module FullAdder( - input io_a, - input io_b, - input io_cin, - output io_sum, - output io_cout); - wire T0; - wire a_and_cin; - wire T1; - wire b_and_cin; - wire a_and_b; - wire T2; - wire a_xor_b; - - assign io_cout = T0; - assign T0 = T1 | a_and_cin; - assign a_and_cin = io_a & io_cin; - assign T1 = a_and_b | b_and_cin; - assign b_and_cin = io_b & io_cin; - assign a_and_b = io_a & io_b; - assign io_sum = T2; - assign T2 = a_xor_b ^ io_cin; - assign a_xor_b = io_a ^ io_b; -endmodule -\end{scala} -} - -\end{columns} - -\end{frame} - -\begin{frame}[fragile]{FullAdder2 Verilog -- Width Inference 2} - -\begin{columns} -\column{0.45\textwidth} - -{\lstset{basicstyle={\scriptsize\ttfamily}} -\begin{scala} -class FullAdder2 extends Module { - val io = new Bundle { - val a = UInt(INPUT, 2) - val b = UInt(INPUT, 2) - val cin = UInt(INPUT, 2) - val sum = UInt(OUTPUT, 2) - val cout = UInt(OUTPUT, 2) - } - // Generate the sum - val a_xor_b = io.a ^ io.b - io.sum := a_xor_b ^ io.cin - // Generate the carry - val a_and_b = io.a & io.b - val b_and_cin = io.b & io.cin - val a_and_cin = io.a & io.cin - io.cout := - a_and_b | b_and_cin | a_and_cin -} -\end{scala} -} - -\column{0.45\textwidth} - -{\lstset{basicstyle={\scriptsize\ttfamily}} -\begin{scala} -module FullAdder( - input [1:0] io_a, - input [1:0] io_b, - input [1:0] io_cin, - output[1:0] io_sum, - output[1:0] io_cout); - wire[1:0] T0; - wire[1:0] a_and_cin; - wire[1:0] T1; - wire[1:0] b_and_cin; - wire[1:0] a_and_b; - wire[1:0] T2; - wire[1:0] a_xor_b; - - assign io_cout = T0; - assign T0 = T1 | a_and_cin; - assign a_and_cin = io_a & io_cin; - assign T1 = a_and_b | b_and_cin; - assign b_and_cin = io_b & io_cin; - assign a_and_b = io_a & io_b; - assign io_sum = T2; - assign T2 = a_xor_b ^ io_cin; - assign a_xor_b = io_a ^ io_b; -endmodule -\end{scala} -} - -\end{columns} - -\end{frame} - -\begin{frame}[fragile]{Using Registers} -\begin{scala} -// clock the new reg value on every cycle -val y = io.x -val z = Reg(next = y) -\end{scala} - -\begin{scala} -// clock the new reg value when the condition a > b -val x = Reg(UInt()) -when (a > b) { x := y } -.elsewhen (b > a) { x := z } -.otherwise { x := w } -\end{scala} -\end{frame} - -\begin{frame}[fragile]{Unconditional Register Update} - -\begin{columns} - -\column{0.42\textwidth} - -{\lstset{basicstyle={\scriptsize\ttfamily}} -\begin{scala} -class ShiftRegister extends Module { - val io = new Bundle { - val in = UInt(INPUT, 1) - val out = UInt(OUTPUT, 1) - } - val r0 = Reg(next = io.in) - val r1 = Reg(next = r0) - val r2 = Reg(next = r1) - val r3 = Reg(next = r2) - io.out := r3 -} -\end{scala} -} -\begin{center} -\includegraphics[width=0.9\textwidth]{figs/shift-register.pdf} -\end{center} - -\column{0.5\textwidth} - -{\lstset{basicstyle={\scriptsize\ttfamily}} -\begin{scala} -module ShiftRegister(input clk, input reset, - input io_in, - output io_out); - - reg[0:0] r3; - reg[0:0] r2; - reg[0:0] r1; - reg[0:0] r0; - - assign io_out = r3; - always @(posedge clk) begin - r3 <= r2; - r2 <= r1; - r1 <= r0; - r0 <= io_in; - end -endmodule -\end{scala} -} - -\end{columns} - -\end{frame} - -\begin{frame}[fragile]{Conditional Register Update} - -\begin{columns} - -\column{0.47\textwidth} - -\begin{scala} -class ShiftRegister extends Module { - val io = new Bundle { - val in = UInt(INPUT, 1) - val shift = Bool(INPUT) - val out = UInt(OUTPUT, 1) - } - - val r0 = Reg(UInt()) - val r1 = Reg(UInt()) - val r2 = Reg(UInt()) - val r3 = Reg(UInt()) - - when (io.shift) { - r0 := io.in - r1 := r0 - r2 := r1 - r3 := r2 - } - io.out := r3 -} -\end{scala} - -\column{0.45\textwidth} - -\begin{center} -\includegraphics[width=0.9\textwidth]{figs/enable-shift-register.pdf} -\end{center} - -\end{columns} - -\end{frame} - -\begin{frame}[fragile]{Conditional Register Update with Reset} - -\begin{scala} -class EnableShiftRegister extends Module { - val io = new Bundle { - val in = UInt(INPUT, 1) - val shift = Bool(INPUT) - val out = UInt(OUTPUT, 1) - } - // Register reset to zero - val r0 = Reg(init = UInt(0, 1)) - val r1 = Reg(init = UInt(0, 1)) - val r2 = Reg(init = UInt(0, 1)) - val r3 = Reg(init = UInt(0, 1)) - when (io.shift) { - r0 := io.in - r1 := r0 - r2 := r1 - r3 := r2 - } - io.out := r3 -} -\end{scala} - -\end{frame} - -\begin{frame}[fragile]{UInt Literals} -inferred width -\begin{scala} -UInt(1) // decimal 1-bit literal from Scala Int. -UInt("ha") // hexadecimal 4-bit literal from string. -UInt("o12") // octal 4-bit literal from string. -UInt("b1010") // binary 4-bit literal from string. -\end{scala} -specified widths -\begin{scala} -UInt("h_dead_beef") // 32-bit literal of type UInt. -UInt(1) // decimal 1-bit literal from Scala Int. -UInt("ha", 8) // hexadecimal 8-bit literal of type UInt. -UInt("o12", 6) // octal 6-bit literal of type UInt. -UInt("b1010", 12) // binary 12-bit literal of type UInt. -UInt(5, 8) // unsigned decimal 8-bit literal of type UInt. -\end{scala} -\end{frame} - - -\setbeamercolor{frametitle}{bg=\frametitleproblemcolor} -\begin{frame}[fragile]{Sequential Circuit Problem -- \tt Accumulator.scala} -\begin{itemize} -\item write sequential circuit that sums \code{in} values -\item in {\tt chisel-tutorial/problems/Accumulator.scala} -\item run {\tt make Accumulator.out} until passing -\end{itemize} -\begin{scala} -class Accumulator extends Module { - val io = new Bundle { - val in = UInt(INPUT, 1) - val out = UInt(OUTPUT, 8) - } - - // flush this out ... - - io.out := UInt(0) -} -\end{scala} -\end{frame} -\setbeamercolor{frametitle}{bg=\frametitledefaultcolor} - -\begin{frame}[fragile]{UInt Operations and Conditional Assignment} - -\begin{columns} -\column{0.5\textwidth} - -{\lstset{basicstyle={\tiny\ttfamily}} -\begin{scala} -class BasicALU extends Module { - val io = new Bundle { - val a = UInt(INPUT, 4) - val b = UInt(INPUT, 4) - val opcode = UInt(INPUT, 4) - val output = UInt(OUTPUT, 4) - } - io.output := UInt(0) - when (io.opcode === UInt(0)) { - io.output := io.a // pass A - } .elsewhen (io.opcode === UInt(1)) { - io.output := io.b // pass B - } .elsewhen (io.opcode === UInt(2)) { - io.output := io.a + UInt(1) // inc A by 1 - } .elsewhen (io.opcode === UInt(3)) { - io.output := io.a - UInt(1) // dec B by 1 - } .elsewhen (io.opcode === UInt(4)) { - io.output := io.a + UInt(4) // inc A by 4 - } .elsewhen (io.opcode === UInt(5)) { - io.output := io.a - UInt(4) // dec A by 4 - } .elsewhen (io.opcode === UInt(6)) { - io.output := io.a + io.b // add A and B - } .elsewhen (io.opcode === UInt(7)) { - io.output := io.a - io.b // sub B from A - } .elsewhen (io.opcode === UInt(8)) { - io.output := (io.a < io.b) // set on A < B - } .otherwise { - io.output := (io.a === io.b) // set on A == B - } -} -\end{scala} -} - -\column{0.4\textwidth} -\begin{itemize} -\item wire \code{io.output} defaulted to 0 and then -\item conditionally reassigned to based on opcode -\item unlike registers, wires are required to be defaulted -\item wires also allow forward declarations -\end{itemize} -\end{columns} -\end{frame} - -\begin{frame}[fragile]{UInt Operations} - -\begin{center} -\begin{tabular}{| c | c | c | } -\hline -Symbol & Operation & Output Type \\ \hline -\verb!+! & Add & UInt \\ \hline -\verb+-+ & Subtract & UInt \\ \hline -\verb+*+ & Multiply & UInt \\ \hline -\verb+/+ & UInt Divide & UInt \\ \hline -\verb+%+ & Modulo & UInt \\ \hline -\verb+~+ & Bitwise Negation & UInt \\ \hline -\verb+^+ & Bitwise XOR & UInt\\ \hline -\verb+&+ & Bitwise AND & UInt \\ \hline -\verb+|+ & Bitwise OR & Bool \\ \hline -{\color{red}\verb+===+} & Equal & Bool \\ \hline -\verb+!=+ & Not Equal & Bool \\ \hline -\verb+>+ & Greater & Bool \\ \hline -\verb+<+ & Less & Bool \\ \hline -\verb+>=+ & Greater or Equal & Bool \\ \hline -\verb+<=+ & Less or Equal & Bool \\ \hline -\end{tabular} -\end{center} - -\end{frame} - -\begin{frame}[fragile]{Bit Extraction} -\begin{scala} -// extracts the x through y bits of value -val x_to_y = value(x, y) -\end{scala} - -\begin{scala} -// extract the x-th bit from value -val x_of_value = value(x) -\end{scala} -\end{frame} - -\begin{frame}[fragile]{ByteSelector} - -\begin{scala} -class ByteSelector extends Module { - val io = new Bundle { - val in = UInt(INPUT, 32) - val offset = UInt(INPUT, 2) - val out = UInt(OUTPUT, 8) - } - io.out := UInt(0, width = 8) - when (io.offset === UInt(0)) { - io.out := io.in(7,0) // pull out lowest byte - } .elsewhen (io.offset === UInt(1)) { - io.out := io.in(15,8) // pull out second byte - } .elsewhen (io.offset === UInt(2)) { - io.out := io.in(23,16) // pull out third byte - } .otherwise { - io.out := io.in(31,24) // pull out highest byte - } -} -\end{scala} - -\end{frame} - -% \setbeamercolor{frametitle}{bg=\frametitleproblemcolor} -% \begin{frame}[fragile]{Instruction Decoder} -% -% {\lstset{basicstyle={\scriptsize\ttfamily}} -% \begin{scala} -% class LoadShiftRegister extends Module { -% val io = new Bundle { -% val inst = UInt(INPUT, 32) -% val rs0 = UInt(OUTPUT, 8) -% val rs1 = UInt(OUTPUT, 8) -% val rs2 = UInt(OUTPUT, 8) -% val isAdd = Bool(OUTPUT) -% val isSub = Bool(OUTPUT) -% val isMul = Bool(OUTPUT) -% val isDiv = Bool(OUTPUT) -% } -% io.isAdd := ... -% io.isSub := ... -% io.isMul := ... -% io.isDiv := ... -% io.rs0 := ... -% io.rs1 := ... -% io.rs2 := ... -% } -% \end{scala} -% } -% -% \end{frame} -% \setbeamercolor{frametitle}{bg=\frametitledefaultcolor} - -\begin{frame}[fragile]{Bit Concatenation and Filling} -You concatenating bits using \verb+Cat+: -\begin{scala} -val A = UInt(width = 32) -val B = UInt(width = 32) -val bus = Cat(A, B) // concatenate A and B -\end{scala} - -and replicate bits using \verb+Fill+: -\begin{scala} -// Replicate a bit string multiple times. -val usDebt = Fill(3, UInt("hA")) -\end{scala} - -\end{frame} - -\setbeamercolor{frametitle}{bg=\frametitleproblemcolor} -\begin{frame}[fragile]{LFSR16 -- \tt problems/lfsr16.scala} - -\begin{scala} -class LFSR16 extends Module { - val io = new Bundle { - val inc = Bool(INPUT) - val out = UInt(OUTPUT, 16) - } - // ... - io.out := UInt(0) -} -\end{scala} -\begin{itemize} -\item \verb+reg+, \verb+cat+, \verb+extract+, \verb+^+ -\item init reg to 1 -\item updates when \verb+inc+ asserted -\end{itemize} - -\begin{center} -\includegraphics[width=0.9\textwidth]{figs/LFSR16.pdf} -\end{center} - -\end{frame} -\setbeamercolor{frametitle}{bg=\frametitledefaultcolor} - -\begin{frame}[fragile]{UInt Bit Inference} -\begin{columns} -\column{0.4\textwidth} -\begin{scala} -class HiLoMultiplier() - extends Module { - val io = new Bundle { - val A = UInt(INPUT, 16) - val B = UInt(INPUT, 16) - val Hi = UInt(OUTPUT, 16) - val Lo = UInt(OUTPUT, 16) - } - val mult = io.A * io.B - io.Lo := mult(15, 0) - io.Hi := mult(31, 16) -} -\end{scala} - -\column{0.5\textwidth} - -{\lstset{basicstyle={\scriptsize\ttfamily}} -\begin{scala} -module HiLoMultiplier( - input [15:0] io_A, - input [15:0] io_B, - output[15:0] io_Hi, - output[15:0] io_Lo); - - wire[15:0] T0; - wire[31:0] mult; // inferred as 32 bits - wire[15:0] T1; - - assign io_Lo = T0; - assign T0 = mult[4'hf:1'h0]; - assign mult = io_A * io_B; - assign io_Hi = T1; - assign T1 = mult[5'h1f:5'h10]; -endmodule -\end{scala} -} - -\end{columns} - -\end{frame} - -\begin{frame}[fragile]{Bit Inference Rules} - -\begin{center} -\begin{tabular}{| l | l | l | } -\hline -Operation & Result Bit Width \\ \hline -\verb!Z = X + Y! & max(Width(X), Width(Y)) \\ \hline -\verb+Z = X - Y+ & max(Width(X), Width(Y)) \\ \hline -\verb+Z = X & Y+ & min(Width(X), Width(Y)) \\ \hline -\verb+Z = X | Y+ & max(Width(X), Width(Y)) \\ \hline -\verb+Z = X ^ Y+ & max(Width(X), Width(Y)) \\ \hline -\verb+Z = ~X+ & Width(X) \\ \hline -\verb+Z = Mux(C, X, Y)+ & max(Width(X), Width (Y)) \\ \hline -\verb+Z = X * Y+ & Width(X) + Width(Y) \\ \hline -\verb+Z = X << n+ & Width(X) + n \\ \hline -\verb+Z = X >> n+ & Width(X) - n \\ \hline -\verb+Z = Cat(X, Y)+ & Width(X) + Width(Y) \\ \hline -\verb+Z = Fill(n, x)+ & Width(X) + n \\ \hline -\end{tabular} -\end{center} - -\end{frame} - -\begin{frame}[fragile]{Bool Type} -The Chisel Bool is used to represent the result of logical expressions: -\begin{scala} -val change = io.a === io.b // change gets Bool type -when (change) { // execute if change is true - ... -} -\end{scala} - -You can instantiate a Bool value like this: -\begin{scala} -val true_value = Bool(true) -val false_value = Bool(false) -\end{scala} - -You can cast an UInt to a Bool as follows: -\begin{scala} -val bit = UInt(width = 1) ... -when (bit.toBool) { ... } -\end{scala} - -You can use a Bool as an UInt: -\begin{scala} -val bit = UInt(width = 1) ... -bit := a > b -\end{scala} - -\end{frame} - -\begin{frame}[fragile]{Bits Subtype Hierarchy} -\begin{itemize} -\item \verb+SInt+ is a signed integer type -\end{itemize} -\begin{center} -\includegraphics[height=0.7\textheight]{figs/bits-hierarchy.pdf} -\end{center} -\end{frame} - -\begin{frame}[fragile]{Bundles} - -\begin{columns} -\column{0.55\textwidth} -\begin{scala} -class MyFloat extends Bundle { - val sign = Bool() - val exponent = UInt(width = 8) - val significand = UInt(width = 23) -} - -val x = new MyFloat() -val xs = x.sign -\end{scala} - -\column{0.35\textwidth} - -\begin{center} -\includegraphics[height=0.9\textheight]{../cs250/figs/myfloat.pdf} -\end{center} - -\end{columns} -\end{frame} - -\begin{frame}[fragile]{Ports} - -\begin{columns} -\column{0.55\textwidth} - -\textbf{Data object with directions assigned to its members} - -\begin{scala} -class Decoupled extends Bundle { - val data = UInt(INPUT, 32) - val valid = Bool(OUTPUT) - val ready = Bool(INPUT) -} -\end{scala} - -\textbf{Direction assigned at instantiation time} - -\begin{scala} -class ScaleIO extends Bundle { - val in = new MyFloat().asInput - val scale = new MyFloat().asInput - val out = new MyFloat().asOutput -} -\end{scala} - -\column{0.35\textwidth} - -\begin{center} -\includegraphics[height=0.9\textheight]{../cs250/figs/fifoio.pdf} -\end{center} - -\end{columns} - -\end{frame} - -\begin{frame}[fragile]{Instantiating Modules} - -\begin{columns} - -\column{0.4\textwidth} - -{\lstset{basicstyle={\tiny\ttfamily}} -\begin{scala} -// A 4-bit adder with carry in and carry out -class Adder4 extends Module { - val io = new Bundle { - val A = UInt(INPUT, 4) - val B = UInt(INPUT, 4) - val Cin = UInt(INPUT, 1) - val Sum = UInt(OUTPUT, 4) - val Cout = UInt(OUTPUT, 1) - } - // Adder for bit 0 - val Adder0 = Module(new FullAdder()) - Adder0.io.a := io.A(0) - Adder0.io.b := io.B(0) - Adder0.io.cin := io.Cin - val s0 = Adder0.io.sum - // Adder for bit 1 - val Adder1 = Module(new FullAdder()) - Adder1.io.a := io.A(1) - Adder1.io.b := io.B(1) - Adder1.io.cin := Adder0.io.cout - val s1 = Cat(Adder1.io.sum, s0) - ... - // Adder for bit 3 - val Adder3 = Module(new FullAdder()) - Adder3.io.a := io.A(3) - Adder3.io.b := io.B(3) - Adder3.io.cin := Adder2.io.cout - io.Sum := Cat(Adder3.io.sum, s2) - io.Cout := Adder3.io.cout -} -\end{scala} -} - -\column{0.5\textwidth} - -\begin{center} -\includegraphics[width=0.9\textwidth]{../getting-started/figs/4_Bit_Adder.jpg} -\end{center} - -\begin{itemize} -\item inherits from \verb+Module+ class, -\item contains an interface stored in a port field named \verb+io+, and -\item wires together subcircuits in its constructor. -\end{itemize} - -\end{columns} - -\end{frame} - -\begin{frame}[fragile]{Vecs} -constructing vecs -\begin{scala} -val myVec1 = Vec.fill( ) { } -val myVec2 = Vec(, , ...) -\end{scala} - -creating a vec of wires -\begin{scala} -val ufix5_vec10 = Vec.fill(10) { UInt(width = 5) } -\end{scala} - - -creating a vec of regs -\begin{scala} -val reg_vec32 = Vec.fill(32){ Reg() } -\end{scala} - -writing -\begin{scala} -reg_vec32(1) := UInt(0) -\end{scala} - -reading -\begin{scala} -val reg5 = reg_vec(5) -\end{scala} - -\end{frame} - -\setbeamercolor{frametitle}{bg=\frametitleproblemcolor} -\begin{frame}[fragile]{Vec Shift Reg -- problems/VecShiftRegister.scala} - -\begin{itemize} -\item add loadability to shift register -\item change interface to use vec's -\end{itemize} - -{\lstset{basicstyle={\scriptsize\ttfamily}} -\begin{scala} -class VecShiftRegister extends Module { - val io = new Bundle { - val ins = Vec.fill(4){ UInt(INPUT, 1) } - val load = Bool(INPUT) - val shift = Bool(INPUT) - val out = UInt(OUTPUT, 1) - } - val delays = Vec.fill(4){ Reg(UInt()) } - when ( ... ) { - // fill in here ... - } .elsewhen (io.shift) { - ... - } - io.out := delays(3) -} -\end{scala} -} - -\end{frame} -\setbeamercolor{frametitle}{bg=\frametitledefaultcolor} - -% \begin{frame}[fragile]{Scala Console} -% \begin{FramedVerb} -% \end{FramedVerb} -% \end{frame} - -\begin{frame}[fragile]{Defining a Tester} - -\begin{columns} -\column{0.45\textwidth} -{\lstset{basicstyle={\tiny\ttfamily}} -\begin{scala} -package Tutorial -import Chisel._ -import scala.collection.mutable.HashMap -import scala.util.Random - -class ByteSelector extends Module { - val io = new Bundle { - val in = UInt(INPUT, 32) - val offset = UInt(INPUT, 2) - val out = UInt(OUTPUT, 8) - } - io.out := UInt(0, width=8) - ... -} - -class ByteSelectorTests(c: ByteSelector) - extends Tester(c, Array(c.io)) { - defTests { - var allGood = true - val vars = new HashMap[Node, Node]() - val test_in = 12345678 - for (t <- 0 until 4) { - vars(c.io.in) = UInt(test_in) - vars(c.io.offset) = UInt(t) - val ref_out = - UInt((test_in >> (t * 8)) & 0xFF) - vars(c.io.out) = ref_out - allGood = step(vars) && allGood - } - allGood - } -} -\end{scala} -} -\column{0.45\textwidth} -{\lstset{basicstyle={\tiny\ttfamily}} -\begin{scala} -class Tester[T <: Module] - (val c: T, val testNodes: Array[Node]) - -def defTests(body: => Boolean) - -def step(vars: HashMap[Node, Node]): Boolean -\end{scala} -} -\begin{tiny} -\begin{itemize} -\item user subclasses \code{Tester} defining DUT and -\code{testNodes} and tests in \code{defTests} body -\item \code{vars} is mapping from \code{testNodes} to literals, called bindings -\item \code{step} runs test with given bindings, where -var values for input ports are sent to DUT, -DUT computes next outputs, and -DUT sends next outputs to Chisel -\item finally \code{step} compares received values against var values - for and returns false if any comparisons fail - output ports -\end{itemize} -\end{tiny} - -\begin{center} -\includegraphics[width=0.9\textwidth]{../tutorial/figs/DUT.pdf} -\end{center} - -\end{columns} -\end{frame} - -\begin{frame}[fragile]{Simulation Debug Output} - -{\lstset{basicstyle={\tiny\ttfamily}} -\begin{scala} -> cd chisel-tutorial/examples -> make ByteSelector.out -STARTING ../emulator/problems/ByteSelector ---- -INPUTS - INPUT(ByteSelector__io_in.ByteSelector) = 12345678 - INPUT(ByteSelector__io_offset.ByteSelector) = 0 -OUTPUTS - READ OUTPUT(ByteSelector__io_out.ByteSelector) = 78 - EXPECTED: OUTPUT(ByteSelector__io_out.ByteSelector) = 78 - SUCCESS ---- -INPUTS - INPUT(ByteSelector__io_in.ByteSelector) = 12345678 - INPUT(ByteSelector__io_offset.ByteSelector) = 1 -OUTPUTS - READ OUTPUT(ByteSelector__io_out.ByteSelector) = 97 - EXPECTED: OUTPUT(ByteSelector__io_out.ByteSelector) = 97 - SUCCESS ---- -... ---- -INPUTS - INPUT(ByteSelector__io_in.ByteSelector) = 12345678 - INPUT(ByteSelector__io_offset.ByteSelector) = 3 -OUTPUTS - READ OUTPUT(ByteSelector__io_out.ByteSelector) = 0 - EXPECTED: OUTPUT(ByteSelector__io_out.ByteSelector) = 0 - SUCCESS -PASSED // Final pass assertion -[success] Total time: 26 s, ... -\end{scala} -} - -\end{frame} - -\begin{frame}{Testbench Ingredients} - -\begin{itemize} -\item Define hash map for I/O and any initializations -\item Set inputs to device under test in hash map -\item Determine expected output for simulation advance for hash map -\item Advance simulation and track success/failure (ex. allGood) -\item Repeat until all appropriate test cases verified -\item Assert if test passed or failed (allGood) -\end{itemize} - -\end{frame} - -\setbeamercolor{frametitle}{bg=\frametitleproblemcolor} -\begin{frame}[fragile]{Testbench for MaxN -- \tt MaxN.scala} -\begin{columns} -\column{0.49\textwidth} - -\begin{itemize} -\item write a testbench for MaxN -\end{itemize} - -{\lstset{basicstyle={\scriptsize\ttfamily}} -\begin{scala} -class MaxN(val n: Int, val w: Int) - extends Module { - - def Max2(x: UInt, y: UInt) = - Mux(x > y, x, y) - - val io = new Bundle { - val ins = Vec.fill(n){ UInt(INPUT, w) } - val out = UInt(OUTPUT, w) - } - io.out := io.ins.reduceLeft(Max2) -} -\end{scala} -} -\begin{scala} -// returns random int in 0..lim-1 -val x = rnd.nextInt(lim) -\end{scala} - -\column{0.42\textwidth} - -{\lstset{basicstyle={\scriptsize\ttfamily}} -\begin{scala} -class MaxNTests(c: MaxN) - extends Tester(c, Array(c.io)) { - defTests { - var allGood = true - val vars = - new HashMap[Node, Node]() - val rnd = new Random() - for (i <- 0 until 10) { - vars.clear() - var mx = 0 - for (i <- 0 until c.n) { - // FILL THIS IN HERE - vars(c.io.ins(0)) = UInt(0) - } - // FILL THIS IN HERE - vars(c.io.out) = UInt(1) - allGood = step(vars) && allGood - } - allGood - } -} -\end{scala} -} -\end{columns} -\end{frame} -\setbeamercolor{frametitle}{bg=\frametitledefaultcolor} - -\begin{frame}[fragile]{Dynamically Accessed Vec} -\begin{scala} -class MemorySearch extends Module { - val io = new Bundle { - val target = UInt(INPUT, 4) - val en = Bool(INPUT) - val address = UInt(OUTPUT, 3) - val done = Bool(OUTPUT) - } - val index = Reg(init = UInt(0, width = 3)) - val list = Vec(UInt(0), UInt(4), UInt(15), UInt(14), - UInt(2), UInt(5), UInt(13)){ UInt(width = 4) } - val memVal = list(index) - val done = !io.en && ((memVal === io.target) || (index === UInt(7))) - when (io.en) { - index := UInt(0) - } .elsewhen (done === Bool(false)) { - index := index + UInt(1) - } - io.done := done - io.address := index -} -\end{scala} -\end{frame} - -\begin{frame}[fragile]{RAM} -RAM is supported using the \code{Mem} construct - -\begin{scala} -val m = Mem(Bits(width = 32), 32) -\end{scala} - -\noindent -where -\begin{itemize} -\item writes to Mems are positive-edge-triggered -\item reads are either combinational or positive-edge-triggered -\item ports are created by applying a \code{UInt} index -\end{itemize} -\end{frame} - -\begin{frame}[fragile]{32-entry Register File} - -\begin{scala} -val regs = Mem(Bits(width = 32), 32) -when (wrEn) { - regs(wrAddr) := wrData -} -val iDat = regs(iAddr) -val mDat = regs(mAddr) -\end{scala} - -\begin{center} -\includegraphics[height=0.55\textheight]{../cs250/figs/mem.pdf} -\end{center} - -\end{frame} - -\setbeamercolor{frametitle}{bg=\frametitleproblemcolor} -\begin{frame}[fragile]{Load/Search Mem -- \tt DynamicMemorySearch.scala} -\begin{scala} -class DynamicMemorySearch extends Module { - val io = new Bundle { - val isWr = Bool(INPUT) - val wrAddr = UInt(INPUT, 3) - val data = UInt(INPUT, 4) - val en = Bool(INPUT) - val target = UInt(OUTPUT, 3) - val done = Bool(OUTPUT) - } - val index = Reg(init = UInt(0, width = 3)) - val memVal = ... - val done = !io.en && ((memVal === io.target) || (index === UInt(7))) - // ... - when (io.en) { - index := UInt(0) - } .elsewhen (done === Bool(false)) { - index := index + UInt(1) - } - io.done := done - io.target := index -} -\end{scala} -\end{frame} -\setbeamercolor{frametitle}{bg=\frametitledefaultcolor} - -\begin{frame}[fragile]{Sequential Read Ports} -Sequential read ports are inferred when: -\begin{itemize} -\item optional parameter \code{seqRead} is set and -\item read address is a reg -\end{itemize} - -\begin{scala} -val ram1r1w = Mem(UInt(width = 32), 1024, seqRead = true) -val reg_raddr = Reg(UInt()) -when (wen) { ram1r1w(waddr) := wdata } -when (ren) { reg_raddr := raddr } -val rdata = ram1r1w(reg_raddr) -\end{scala} - -\begin{center} -\includegraphics[height=0.4\textheight]{../cs250/figs/mem-seq-read.pdf} -\end{center} - -\end{frame} - -\begin{frame}[fragile]{Stack} - -{\lstset{basicstyle={\tiny\ttfamily}} -\begin{scala} -class Stack(depth: Int) extends Module { - val io = new Bundle { - val dataIn = UInt(INPUT, 32) - val dataOut = UInt(OUTPUT, 32) - val push = Bool(INPUT) - val pop = Bool(INPUT) - val en = Bool(INPUT) - } - // declare the memory for the stack - val stack_mem = Mem(UInt(width = 32), depth, seqRead = false) - val sp = Reg(init = UInt(0, width = log2Up(depth))) - val dataOut = Reg(init = UInt(0, width = 32)) - // Push condition - make sure stack isn't full - when(io.en && io.push && (sp != UInt(depth-1))) { - stack_mem(sp + UInt(1)) := io.dataIn - sp := sp + UInt(1) - } - // Pop condition - make sure the stack isn't empty - .elsewhen(io.en && io.pop && (sp > UInt(0))) { - sp := sp - UInt(1) - } - when(io.en) { - dataOut := stack_mem(sp) - } - io.dataOut := dataOut -} -\end{scala} -} - -\end{frame} - -\begin{frame}[fragile]{Scripting Hardware Generation} - -\begin{columns} -\column{0.5\textwidth} - -{\lstset{basicstyle={\tiny\ttfamily}} -\begin{scala} -// A n-bit adder with carry in and carry out -class Adder(n: Int) extends Module { - val io = new Bundle { - val A = UInt(INPUT, n) - val B = UInt(INPUT, n) - val Cin = UInt(INPUT, 1) - val Sum = UInt(OUTPUT, n) - val Cout = UInt(OUTPUT, 1) - } - // create a vector of FullAdders - val FAs = Vec.fill(n){ Module(new FullAdder()).io } - val carry = Vec.fill(n+1){ UInt(width = 1) } - val sum = Vec.fill(n){ Bool() } - - // first carry is the top level carry in - carry(0) := io.Cin - - // wire up the ports of the full adders - for(i <- 0 until n) { - FAs(i).a := io.A(i) - FAs(i).b := io.B(i) - FAs(i).cin := carry(i) - carry(i+1) := FAs(i).cout - sum(i) := FAs(i).sum.toBool() - } - io.Sum := sum.toBits().toUInt() - io.Cout := carry(n) -} -\end{scala} -} - -\column{0.4\textwidth} - -\begin{center} -\includegraphics[width=0.9\textwidth]{../getting-started/figs/4_Bit_Adder.jpg} -\end{center} -\end{columns} - -\end{frame} - -\input{../talks/microsoft/libs-to-langs-guts-in-scala.tex} - -\setbeamercolor{frametitle}{bg=\frametitleproblemcolor} -\begin{frame}[fragile]{Mul Lookup Table Problem -- \tt Mul.scala} -\begin{itemize} -\item write 16x16 multiplication table using \code{Vec} -\end{itemize} -\begin{scala} -class Mul extends Module { - val io = new Bundle { - val x = UInt(INPUT, 4) - val y = UInt(INPUT, 4) - val z = UInt(OUTPUT, 8) - } - val muls = new ArrayBuffer[UInt]() - - // flush this out ... - - io.z := UInt(0) -} -\end{scala} - -hint: -\begin{scala} -val tab = Vec(muls) -io.z := tab(Cat(io.x, io.y)) -\end{scala} - -\end{frame} -\setbeamercolor{frametitle}{bg=\frametitledefaultcolor} - -\begin{frame}[fragile] -\frametitle{Valid Wrapper} - -\begin{columns} - -\column{0.65\textwidth} - -\begin{footnotesize} -\begin{scala} -class Valid[T <: Data](dtype: T) extends Bundle { - val data = dtype.clone.asOutput - val valid = Bool(OUTPUT) - override def clone = new Valid(dtype) -} - -class GCD extends Module { - val io = new Bundle { - val a = UInt(INPUT, 16) - val b = UInt(INPUT, 16) - val out = new Valid(UInt(OUTPUT, 16)) - } } - ... - io.out.data := x - io.out.valid := y === UInt(0) -} - -\end{scala} -\end{footnotesize} - -\column{0.3\textwidth} - -\begin{center} -\includegraphics[width=0.9\textwidth]{../talks/retreat-1/figs/valid.pdf} -\end{center} - -\end{columns} -\note{now gcd had a valid signal on its output. \\[1cm] -we can generalize this idea by defining a wrapper class that bundles a valid with a data signal. \\[1cm] -now we can rewrite GCD using an interface using this valid wrapper for its output. } - -\end{frame} - -\begin{frame}[fragile] -\frametitle{Function Filters} - -\begin{footnotesize} -\begin{scala} -abstract class Filter[T <: Data](dtype: T) extends Module { - val io = new Bundle { - val in = Valid(dtype).asInput - val out = Valid(dtype).asOutput -} } - -class FunctionFilter[T <: Data](dtype: T, f: T => T) extends Filter(dtype) { - io.out.valid := io.in.valid - io.out.bits := f(io.in) -} -\end{scala} -\end{footnotesize} - -\begin{center} -\includegraphics[height=0.4\textheight]{../talks/sketching13/figs/function-filter.pdf} -\end{center} - -\note{suppose we want to write hardware filters. \\[1cm] -one way to create a reusable filter would be \\[1cm] -to create a filter class that takes a function as argument that definines its filter operation.} - -\end{frame} - -\begin{frame}[fragile] -\frametitle{Clipping Filter} - -\begin{footnotesize} -\begin{scala} -def clippingFilter[T <: Bits](limit: Int, dtype: T) = - new FunctionFilter(dtype, x => min(limit, max(-limit, x))) -\end{scala} -\end{footnotesize} - -\begin{center} -\includegraphics[height=0.4\textheight]{../talks/retreat-1/figs/clipping-filter.pdf} -\end{center} -\note{using this reusable substrate then it is easy to create an instance of a filter.} -\end{frame} - - -\begin{frame}[fragile] -\frametitle{Shifting Filter} - -\begin{footnotesize} -\begin{scala} -def shiftingFilter[T <: Bits](shift: Int, dtype: T) = - new FunctionFilter(dtype, x => x >> shift) -\end{scala} -\end{footnotesize} - -\begin{center} -\includegraphics[height=0.4\textheight]{../talks/retreat-1/figs/shifting-filter.pdf} -\end{center} -\note{and reuse it for shift filter} -\end{frame} - -\begin{frame}[fragile]{Testing Decoupled Circuits} - -\begin{itemize} -\item using ovars for outputs -\item need to check outputs directly using \verb+litValue+ -\end{itemize} -\begin{scala} -class GCDTests(c: GCD) extends Tester(c, Array(c.io)) { - defTests { - val (a, b, z) = (64, 48, 16) - val svars = new HashMap[Node, Node]() - val ovars = new HashMap[Node, Node]() - var t = 0 - do { - svars(c.io.a) = UInt(a) - svars(c.io.b) = UInt(b) - step(svars, ovars) - t += 1 - } while (t <= 1 || ovars(c.io.v).litValue() == 0) - ovars(c.io.z).litValue() == z - } -} -\end{scala} - -\end{frame} - -\begin{frame}[fragile] -\frametitle{Chained Filter} - -\begin{footnotesize} -\begin{scala} -class ChainedFilter[T <: Num](dtype: T) extends Filter(dtype) = { - val shift = Module(new ShiftFilter(2, dtype)) - val clipper = Module(new ClippingFilter(1 << 7, dtype)) - io.in <> shift.io.in - shift.io.out <> clipper.io.in - clipper.io.out <> io.out -} -\end{scala} -% \begin{scala} -% class ChainedFilter[T <: Num](dtype: T) extends Filter(dtype) = { -% val fir = new TstFIR(dtype) -% val shift = new ShiftFilter(2, dtype) -% val clipper = new ClippingFilter(1 << 7, dtype) -% io.in <> fir.io.in -% fir.io.out <> shift.io.in -% shift.io.out <> clipper.io.in -% clipper.io.out <> io.out -% } -% \end{scala} -\end{footnotesize} - -\begin{center} -\includegraphics[height=0.4\textheight]{../talks/sketching13/figs/chained-filter2.pdf} -\end{center} -\note{and chain together...} -\end{frame} - -\begin{frame}[fragile]{Predicate Filter} -\begin{scala} -class PredicateFilter[T <: Data](dtype: T, f: T => Bool) - extends Filter(dtype) { - io.out.valid := io.in.valid && f(io.in.bits) - io.out.bits := io.in.bits -} -\end{scala} - -\begin{center} -\includegraphics[height=0.4\textheight]{figs/predicate-filter.pdf} -\end{center} -\end{frame} - -\setbeamercolor{frametitle}{bg=\frametitleproblemcolor} -\begin{frame}[fragile]{Predicate Filtering -- \tt SingleEvenFilter.scala} -\begin{itemize} -\item write filter that lets only even single digit numbers through -\end{itemize} -\begin{scala} -object SingleFilter { - def apply[T <: UInt](dtype: T) = // FILL IN FUNCTION BELOW - Module(new PredicateFilter(dtype, (x: T) => Bool(false))) -} - -object EvenFilter { - def apply[T <: UInt](dtype: T) = // FILL IN FUNCTION BELOW - Module(new PredicateFilter(dtype, (x: T) => Bool(false))) -} - -class SingleEvenFilter[T <: UInt](dtype: T) extends Filter(dtype) { - // FILL IN CONSTRUCTION AND WIRING - io.out := UInt(0) -} -\end{scala} -\end{frame} -\setbeamercolor{frametitle}{bg=\frametitledefaultcolor} - -\begin{frame}[fragile, shrink] -\frametitle{Functional Composition} - -% \begin{itemize} -% \item natural -% \item reusable -% \item composable -% \end{itemize} -% \vskip1cm - -\begin{Large} -\begin{columns} - -\column{0.45\textwidth} -\verb+Map(ins, x => x * y)+ \\ -\begin{center} -\includegraphics[height=0.6\textheight]{../bootcamp/figs/map.pdf} \\[2cm] -\end{center} - -\column{0.45\textwidth} -\vskip2mm -\verb+Chain(n, in, x => f(x))+ \\ -\begin{center} -\includegraphics[width=0.9\textwidth]{../bootcamp/figs/chain.pdf} \\ -\end{center} - -\verb+Reduce(ins, Max)+ \\ -\begin{center} -\includegraphics[width=0.9\textwidth]{../bootcamp/figs/reduce.pdf} \\ -\end{center} - -\end{columns} - -\end{Large} -\note{the previous example showed a simple use of functional programming. \\[1cm] -Scala provides strong support for functional programming and -it turns out that functional programming is a powerful way to define hardware. \\[1cm] -for example, you can create a parallel set of blocks using map and reduce to creation reduction trees and chain to create a pipeline.} -\end{frame} - -\begin{frame}[fragile]{Flo Map / Reduce Generator} - -{\lstset{basicstyle={\scriptsize\ttfamily}} -\begin{scala} -object FloDelays { - def apply(x: Flo, n: Int): List[Flo] = - if (n <= 1) List(x) else x :: FloDelays(RegNext(x), n-1) -} -object FloFIR { - def apply(ws: Seq[Flo], x: T): T = - (ws, FloDelays(x, ws.length)).zipped.map( _ * _ ).reduce( _ + _ ) -} -class FIR extends Module { - val io = new Bundle { val x = Flo(INPUT); val z = Flo(OUTPUT) } - val ws = Array(Flo(0.25), Flo(0.75)) - io.z := FloFIR(ws, io.x) -} -\end{scala} -} -\begin{center} -\includegraphics[height=0.35\textheight]{../cs294-88/lectures/advanced-chisel/figs/inner-product-fir.png} -\end{center} -\note{as an advanced example, consider writing an FIR filter which is defined by the equation below. \\[1cm] -essentially it's a sum of products of coefficients and delayed versions of input.\\[1cm] -we can write this quite simply using map and reduce as above.} -\end{frame} - -\begin{frame}[fragile]{Generic Map / Reduce Generator} - -{\lstset{basicstyle={\scriptsize\ttfamily}} -\begin{scala} -object Delays { - def apply[U <: Data](x: U, n: Int): List[U] = - if (n <= 1) List(x) else x :: Delays(RegNext(x), n-1) -} -object GenFIR { - def apply[T <: Data with Num[T]](ws: Seq[T], x: T): T = - (ws, Delays(x, ws.length)).zipped.map( _ * _ ).reduce( _ + _ ) -} -class FIR extends Module { - val io = new Bundle { val x = Flo(INPUT); val z = Flo(OUTPUT) } - val ws = Array(Flo(0.25), Flo(0.75)) - io.z := GenFIR(ws, io.x) -} -\end{scala} -} -\begin{center} -\includegraphics[height=0.35\textheight]{../cs294-88/lectures/advanced-chisel/figs/inner-product-fir.png} -\end{center} -\note{as an advanced example, consider writing an FIR filter which is defined by the equation below. \\[1cm] -essentially it's a sum of products of coefficients and delayed versions of input.\\[1cm] -we can write this quite simply using map and reduce as above.} -\end{frame} - -\begin{frame}[fragile]{Chisel Standard Library -- \tt ChiselUtil.scala} -\begin{center} -\begin{tabular}{rl} -{\bf Bits Properities} & \code{log2Up}, \code{log2Down}, \code{isPow2}, \code{PopCount}\\ -{\bf Numeric Utilities} & \code{LFSR16}, \code{Reverse}, \code{FillInterleaved} \\ -{\bf Stateful Functions} & \code{ShiftRegister}, \code{Counter} \\ -{\bf Priority Encoding Functions} & \code{UIntToOH}, \code{OHToUInt}, \code{Mux1H} \\ -{\bf Priority Encoders} & \code{PriorityEncoder}, \code{PriorityEncoderOH} \\ -{\bf Vec Construction} & \code{Vec.fill}, \code{Vec.tabulate} \\ -{\bf Vec Functional} & \code{forall}, \code{exists}, \code{contains}, ... \\ -{\bf Queues and Pipes} & \code{Decoupled}, \code{Queue}, \code{Valid}, \code{Pipe} \\ -{\bf Arbiters} & \code{ArbiterIO}, \code{Arbiter}, \code{RRArbiter} \\ -\end{tabular} -\end{center} -\end{frame} - -\begin{frame}[fragile] -\frametitle{Queues} -\begin{itemize} -\item Required parameter \verb+entries+ controls depth -\item The width is determined from the inputs. -\end{itemize} -\begin{scala} -class QueueIO[T <: Data](type: T, entries: Int) extends Bundle { - val enq = Decoupled(data.clone).flip - val deq = Decoupled(data.clone) - val count = UFix(OUTPUT, log2Up(entries+1)) -} - -class Queue[T <: Data] - (type: T, entries: Int, - pipe: Boolean = false, - flow: Boolean = false - flushable: Boolean = false) - extends Module -\end{scala} -\begin{scala} -val q = new Queue(UInt(), 16) -q.io.enq <> producer.io.out -consumer.io.in <> q.io.deq -\end{scala} -\end{frame} - -\begin{frame}[fragile]{Multiple Clock Domains} -Clocks are first class and take an optional reset signal: -\begin{scala} -class Clock (reset: Bool) extends Node { - def reset: Bool // returns reset pin -} -\end{scala} - -There is a builtin implicit clock that state elements use by default: -\begin{scala} -var implicitClock = new Clock( implicitReset ) -\end{scala} - -Clocks can be defined from other clocks: -\begin{scala} -val clock2 = clock1 * 2 -val clock3 = clock1 / 2 -\end{scala} - -\end{frame} - -\begin{frame}[fragile]{Specifying a Clock Domain} -The clock for state elements and modules can be specified: -\begin{scala} -Reg(... clock: Clock = implicitClock) -Mem(... clock: Clock = implicitClock) -Module(... clock: Clock = implicitClock) -\end{scala} - -For example, a register can be created in a different clock domain as follows: -\begin{scala} -val reg = Reg(UInt(), clock = clock2) -\end{scala} - -\end{frame} - -\begin{frame}[fragile]{Crossing Clock Domains} -The most general technique to send data between domains is using an asynchronous queue: - -\begin{scala} -class AsyncQueue[T <: Data] - (dataType: T, depth: Int, enq_clk: Clock, deq_clock: Clock) extends Module -\end{scala} - -Using these queues, we can then move a signalA from clock domains clockA to signalB in clockB: - -\begin{scala} -val queue = new AsyncQueue(Uint(width = 32), 2, clockA, clockB) -fifo.enq.bits := signalA -signalB := fifo.deq.bits -fifo.valid := condA -fifo.ready := condB -... -\end{scala} - -\end{frame} - -\begin{frame}[fragile]{Multiple Clocks -- \tt MultipleClockDomains.scala} -\begin{scala} -class MultiClockDomain extends Module { - val io = new Bundle { - val start = Bool(INPUT) - val sum = Decoupled(UInt(OUTPUT)) - } - val fastClock = new Clock() - val slowClock = new Clock() - ... -} - -class MultiClockDomainTests(c: MultiClockDomain) - extends Tester(c, Array(c.io)) { - defTests { - val clocks = new HashMap[Clock, Int] - clocks(Module.implicitClock) = 2 - clocks(c.fastClock) = 4 - clocks(c.slowClock) = 6 - setClocks(clocks) - ... - } -} -\end{scala} -\end{frame} - -\begin{frame}[fragile]{Creating Your Own Project} -directory structure -\begin{bash} -Hello/ - build.sbt # scala configuration file - Hello.scala # your source file -\end{bash} - -\end{frame} - -\begin{frame}[fragile]{Writing Your Source File} - -{\lstset{basicstyle={\scriptsize\ttfamily}} -\begin{scala} -package Hello -import Chisel._ -import scala.collection.mutable.HashMap - -class Hello extends Module { - val io = new Bundle { - val out = UInt(OUTPUT, 8) } - io.out := UInt(33) -} - -class HelloTests(c: Hello) extends Tester(c, Array(c.io)) { - defTests { - val vars = new HashMap[Node, Node]() - vars(c.io.out) = UInt(33) - step(vars) - } -} - -object Hello { - def main(args: Array[String]): Unit = { - val args = Array("--backend", "c", "--genHarness", "--compile", "--test") - chiselMainTest(args, () => Module(new Hello())) { - c => new HelloTests(c) } -} } -\end{scala} -} - -\end{frame} - -\begin{frame}[fragile]{Setting Up Your SBT Configuration File} -\begin{scala} -scalaVersion := "2.10.2" - -addSbtPlugin("com.github.scct" % "sbt-scct" % "0.2") - -libraryDependencies += - "edu.berkeley.cs" %% "chisel" % "latest.release" -\end{scala} -\end{frame} - -\begin{frame}[fragile]{Compiling and Running} -Producing C++ -\begin{bash} -sbt run --backend c -\end{bash} - -Producing Verilog -\begin{bash} -sbt run --backend v -\end{bash} - -Running the Chisel Tests -\begin{bash} -sbt run --backend c --compile --test --genHarness -\end{bash} - -\end{frame} - -\begin{frame}[fragile]{chiselMain(Test) Command Line Arguments} -\begin{scala} -sbt -sbt> compile // compiles Chisel Scala code -sbt> run // compile and run Chisel Scala Code -sbt> run --backend c // produces C++ files -sbt> exit -\end{scala} - -with a complete set of command line arguments being:\\[2mm] - -\begin{tabular}{lll} -\verb+--backend v+ & generate verilog \\ -\verb+--backend c+ & generate C++ (default)\\ -\verb+--vcd+ & enable vcd dumping \\ -\verb+--targetDir+ & target pathname prefix \\ -\verb+--genHarness+ & generate harness file for C++ \\ -\verb+--debug+ & put all wires in C++ class file \\ -\verb+--compile+ & compiles generated C++ \\ -\verb+--test+ & runs tests using C++ app \\ -\end{tabular} -\end{frame} - -\setbeamercolor{frametitle}{bg=\frametitleproblemcolor} -\begin{frame}[fragile]{Make Your Own Project} -set hello project up -\begin{bash} -cd ~ -mkdir hello -cp ~/chisel-tutorial/hello/* hello -cd hello -sbt run -\end{bash} -make a change -\begin{itemize} -\item make output a function of an new input -\end{itemize} -\end{frame} -\setbeamercolor{frametitle}{bg=\frametitledefaultcolor} - -\begin{frame}{Chisel Workflow} -\begin{center} -\includegraphics[height=0.9\textheight]{../bootcamp/figs/chisel-workflow.pdf} -\end{center} -\end{frame} - -\begin{frame}[fragile]{printf / sprintf} -\begin{itemize} -\item during simulation -\begin{itemize} -\item \verb+printf+ prings the formatted string to the console on rising clock edges -\item \verb+sprintf+ returns the formatted string as a bit vector -\end{itemize} -\item format specifiers are -\begin{itemize} -\item \verb+%b+ -- binary number -\item \verb+%d+ -- decimal number -\item \verb+%x+ -- hexidecimal number -\item \verb+%e+ -- floating point number in scientific notation -\item \verb+%s+ -- string consisting of a sequence of 8-bit extended ASCII chars -\item \verb+%%+ -- specifies a literal %. -\end{itemize} -\end{itemize} -the following prints the line \verb+"0x4142 16706 AB"+ on cycles when \verb+c+ is true: -\begin{scala} -val x = Bits(0x4142) -val s1 = sprintf("%x %s", x, x); -when (c) { printf("%d %s\n", x, s1); } -\end{scala} -\end{frame} - -\begin{frame}[fragile]{assert} -\begin{itemize} -\item simulation time assertions are provided by \verb+assert+ construct -\item if assert arguments false on rising edge then -\begin{itemize} -\item an error is printed and -\item simulation terminates -\end{itemize} -\end{itemize} -the following will terminate after 10 clock cycles: -\begin{scala} -val x = Reg(init = UInt(0, 4)) -x := x + UInt(1) -assert(x < UInt(10)) -\end{scala} -\end{frame} - -\begin{frame}[fragile]{Installation} -\begin{itemize} -\item on mac install: -\begin{itemize} -\item XCODE console tools -\end{itemize} -\item on windows install: -\begin{itemize} -\item cygwin -\end{itemize} -\item everywhere install: -\begin{itemize} -\item git -\item g++ version 4.0 or later -\item java -\end{itemize} -\item everywhere -\begin{itemize} -\item git clone https://github.com/ucb-bar/chisel-tutorial.git -\end{itemize} -\end{itemize} - -\end{frame} - -\begin{frame}[fragile]{Chisel Resources} -\begin{center} -\url{https://chisel.eecs.berkeley.edu/documentation.html} \\[0.25cm] -\begin{tabular}{rl} -\textbf{manual} & \code{manual.pdf} \\ -\textbf{bootcamp2014} & \code{bootcamp-20140206.pdf} \\ -\textbf{bootcamp2012} & \code{bootcamp-20121026.pdf} \\ -\textbf{tutorial} & \code{tutorial.pdf} \\ -\textbf{getting started} & \code{getting-started.pdf} \\ -\textbf{cs250 lectures} & \code{cs250-1.pdf}, \code{cs250-2.pdf}, \code{cs250-3.pdf} \\[0.5cm] -\end{tabular} -\url{https://github.com/ucb-bar/chisel/} \\[0.25cm] -\begin{tabular}{rl} -\textbf{setup} & \code{readme.md} \\ -\textbf{utils} & \code{src/main/scala/ChiselUtils.scala} \\[0.5cm] -\end{tabular} -\url{https://chisel.eecs.berkeley.edu/download.html} \\[0.25cm] -\begin{tabular}{rl} -\textbf{sodor} & \url{https://github.com/ucb-bar/sodor/} \\ -% \textbf{virtualbox} & \url{https://chisel.eecs.berkeley.edu/chisel-riscv.box} \\ -\end{tabular} -\end{center} -\end{frame} - -\begin{frame}{Scala Resources} - -\begin{center} -\includegraphics[height=0.4\textheight]{../bootcamp/figs/programming-scala.pdf} \\ -\includegraphics[height=0.4\textheight]{../bootcamp/figs/programming-in-scala.pdf} -\end{center} - -\end{frame} - -\begin{frame}[fragile]{Projects Ideas} - -\begin{center} -\begin{tabular}{rl} -\textbf{audio processing} & \code{Echo.scala} \\ -\textbf{image processing} & \code{Darken.scala} \\ -\textbf{risc processor} & \code{Risc.scala} \\ -\textbf{game of life} & \code{Life.scala} \\ -\textbf{router} & \code{Router.scala} \\ -\textbf{map/reduce} & \code{FIR.scala}\\ -\textbf{network} & \\ -\textbf{decoupled filter} & \\ -\textbf{cryptography} & \\ -\textbf{serial multiplier} & \\ -\textbf{pong} & \\ -\end{tabular} -\end{center} - -\end{frame} - -\begin{frame}[fragile]{Keep in Touch} -\begin{center} -\begin{tabular}{rl} -\textbf{website} & \url{chisel.eecs.berkeley.edu} \\ -\textbf{mailing list} & \url{groups.google.com/group/chisel-users} \\ -\textbf{github} & \url{https://github.com/ucb-bar/chisel/} \\ -\textbf{features + bugs} & \url{https://github.com/ucb-bar/chisel/issues} \\ -\textbf{more questions} & \url{stackoverflow.com/quesions/tagged/chisel} \\ -\textbf{twitter} & {\tt \#chiselhdl} \\ -\textbf{me} & \url{jrb@eecs.berkeley.edu} \\ -\end{tabular} -\end{center} -\end{frame} - -\begin{frame}{Thanks} -\begin{itemize} -\item \textbf{Arrangements} -- Borivoje Nikolic -\item \textbf{Educational Machines} -- Michael Zimmer -\item \textbf{Bootcamp Materials} -- Vincent Lee, Stephen Twigg, Huy Vo -\item \textbf{Funding} -- Department of Energy, Department of Defense -\end{itemize} -\end{frame} - -\end{document} diff --git a/doc/bootcamp/bootcamp.tex b/doc/bootcamp/bootcamp.tex deleted file mode 100644 index 6844a678..00000000 --- a/doc/bootcamp/bootcamp.tex +++ /dev/null @@ -1,2333 +0,0 @@ -\documentclass[xcolor=pdflatex,dvipsnames,table]{beamer} -\usepackage{epsfig,graphicx} -\usepackage{palatino} -\usepackage{fancybox} -\usepackage{relsize} -\usepackage[procnames]{listings} - -\input{../style/scala.tex} -\input{../style/talk.tex} - -\title{Chisel Bootcamp} -\author{Jonathan Bachrach} -\date{\today} -\institute[UC Berkeley]{EECS UC Berkeley} - -\begin{document} - -\begin{frame} -\titlepage -\end{frame} -\addtocounter{framenumber}{-1} - -% \begin{frame}[fragile]{tutorial.scala} -% \begin{scala} -% package Tutorial { -% -% import Chisel._ -% -% object Tutorial { -% def main(args: Array[String]): Unit = { -% val tut_args = args.slice(1, args.length) ++ -% Array("--targetDir", "../emulator", "--genHarness") -% args(0) match { -% case "gcd" => -% chiselMain(tut_args, () => new GCD()) -% ... -% } -% } -% } -% -% } -% \end{scala} -% \end{frame} - -\begin{frame}[fragile]{Goals for Bootcamp} - -\begin{itemize} -\item get you started with Chisel -\item get a basic working knowledge of Chisel -\item learn how to think in Chisel -\item know where to get more information -\end{itemize} - -\end{frame} - -\setbeamercolor{frametitle}{bg=\frametitleproblemcolor} -\begin{frame}[fragile]{Bootcamp Chisel Installation} -\begin{scala} --Install VirtualBox --File->Import appliance, chisel-vm.ova --Start --Login (username: chisel-bootcamp, password: chisel) --GTKWave, Emacs, etc. all installed -\end{scala} -\end{frame} -\setbeamercolor{frametitle}{bg=\frametitledefaultcolor} - -\setbeamercolor{frametitle}{bg=\frametitleproblemcolor} -\begin{frame}[fragile]{Development Tool Installation} - -\begin{itemize} -\item {\bf MacOSX}: - -\begin{itemize} -\item Install XCODE, including console tools. -\end{itemize} - -\item {\bf Linux}: - -\begin{itemize} -\item To prepare your Linux platform for Chisel, you will need to install the following packages: -\begin{itemize} -\item \verb|g++| -\item \verb+openjdk-7-jre+ -\end{itemize} -\item using -\begin{itemize} -\item \verb+sudo apt-get install+ -\end{itemize} -\end{itemize} - -\end{itemize} -\end{frame} -\setbeamercolor{frametitle}{bg=\frametitledefaultcolor} - -\setbeamercolor{frametitle}{bg=\frametitleproblemcolor} -\begin{frame}[fragile]{Getting the Chisel Tutorial} - -\begin{scala} -git clone https://github.com/ucb-bar/chisel-tutorial.git -cd chisel-tutorial -\end{scala} -\end{frame} -\setbeamercolor{frametitle}{bg=\frametitledefaultcolor} - -\setbeamercolor{frametitle}{bg=\frametitleproblemcolor} -\begin{frame}[fragile]{Chisel Tutorial Contents} -\begin{FramedSemiVerb} -chisel-tutorial/ - Makefile - examples/ \comment{\# Contains chisel examples} - Makefile - build.sbt \comment{\# Contains project description} - FullAdder.scala ... - problems/ \comment{\# Contains skeletal files for tutorial problems} - Makefile - build.sbt \comment{\# Contains project description} - Accumulator.scala ... - solutions/ \comment{\# Contains solutions to problems} - Makefile - build.sbt \comment{\# Contains project description} - Counter.scala ... -\end{FramedSemiVerb} -\end{frame} -\setbeamercolor{frametitle}{bg=\frametitledefaultcolor} - -\setbeamercolor{frametitle}{bg=\frametitleproblemcolor} -\begin{frame}[fragile]{Test It} - -\begin{bash} -cd $TUT_DIR -make -\end{bash} - -% \begin{bash} -% cd $TUT_DIR/examples -% make check Parity.out -% \end{bash} - -\vspace{1cm} -\noindent -If your system is set up correctly, you should see a messsage \verb+[success]+ followed by the total time of the run, and date and time of completion. - -\end{frame} -\setbeamercolor{frametitle}{bg=\frametitledefaultcolor} - - -\setbeamercolor{frametitle}{bg=\frametitleproblemcolor} -\begin{frame}[fragile]{Get This} - -\begin{center} -\fbox{ -\url{chisel.eecs.berkeley.edu/chisel-bootcamp.pdf} -} -\end{center} - -\end{frame} -\setbeamercolor{frametitle}{bg=\frametitledefaultcolor} - -\begin{frame}[fragile] -\frametitle{Chisel} - -\begin{columns}[c] - -\column{0.55\textwidth} - -\begin{itemize} -\item A hardware construction language -\begin{itemize} -\item ``synthesizable by construction'' -\item creates graph representing hardware -\end{itemize} -\item Embedded within Scala language to leverage mindshare and language design -\item Best of hardware and software design ideas -\item Multiple targets -\begin{itemize} -\item Simulation and synthesis -\item Memory IP is target-specific \\[0.5cm] -\end{itemize} -\item {\color{red}{\bf Not} Scala app -> Verilog arch} -\end{itemize} - -\column{0.40\textwidth} - -\begin{center} -single source \\ -\includegraphics[width=0.99\textwidth]{../talks/retreat-1/figs/graph-and-targets.pdf} \\ -multiple targets \\ -\end{center} - -\end{columns} -\note{creates a graph if successfully created will correctly synthesize \\[1cm] -single source generates two different verilog outputs, one for fpga and one for asic. \\[1cm] -surprisingly difficult to generate each. for example, chisel has abstraction for memories.} -\end{frame} - -\begin{frame}[fragile] -\frametitle{The Scala Programming Language} - -\begin{columns}[c] - -\column{0.75\textwidth} - -\begin{itemize} -\item Object Oriented -\begin{itemize} -\item Factory Objects, Classes -\item Traits, overloading etc -\item Strongly typed with type inference -\end{itemize} -\item Functional -\begin{itemize} -\item Higher order functions -\item Anonymous functions -\item Currying etc -\end{itemize} -\item Extensible -\begin{itemize} -\item Domain Specific Languages (DSLs) -\end{itemize} -\item Compiled to JVM -\begin{itemize} -\item Good performance -\item Great Java interoperability -\item Mature debugging, execution environments -\end{itemize} -\item Growing Popularity -\begin{itemize} -\item Twitter -\item many Universities -\end{itemize} -\end{itemize} - -\column{0.25\textwidth} - -\begin{center} -\includegraphics[height=0.4\textheight]{figs/programming-scala.pdf} \\ -\includegraphics[height=0.4\textheight]{figs/programming-in-scala.pdf} -\end{center} - -\end{columns} -\note{powerful combination of scipting and type safety, \\[1cm] -includes powerful features to support abstraction, \\[1cm] -as makes it easy to embed DSLs, compiles to jvm} -\end{frame} - -\include{scala-intro} - -\begin{frame}[fragile] -\frametitle{Algebraic Graph Construction} - -\begin{columns} -\column{0.35\textwidth} -{\lstset{basicstyle={\Large\ttfamily}} -\begin{scala} -Mux(x > y, x, y) -\end{scala} -} - -\column{0.6\textwidth} - -\begin{center} -\includegraphics[width=0.9\textwidth]{figs/max2.pdf} -\end{center} -\end{columns} -\end{frame} - -\begin{frame}[fragile] -\frametitle{Creating Module} - -\begin{columns} -\column{0.45\textwidth} - -{\lstset{basicstyle={\scriptsize\ttfamily}} -\begin{scala} -class Max2 extends Module { - val io = new Bundle { - val x = UInt(INPUT, 8) - val y = UInt(INPUT, 8) - val z = UInt(OUTPUT, 8) } - io.z := Mux(io.x > io.y, io.x, io.y) -} -\end{scala} -} - -\column{0.45\textwidth} -\begin{center} -\includegraphics[width=0.95\textwidth]{figs/Max2c.pdf} \\ -\end{center} -\end{columns} - -\end{frame} - -\begin{frame}[fragile] -\frametitle{Connecting Modules} - -\begin{columns} -\column{0.3\textwidth} -\begin{scala} -val m1 = - Module(new Max2()) -m1.io.x := a -m1.io.y := b -val m2 = - Module(new Max2()) -m2.io.x := c -m2.io.y := d -val m3 = - Module(new Max2()) -m3.io.x := m1.io.z -m3.io.y := m2.io.z -\end{scala} - -\column{0.6\textwidth} - -\begin{center} -\includegraphics[width=0.99\textwidth]{figs/Max4.pdf} \\ -\end{center} -\end{columns} - -\end{frame} - - -\begin{frame}[fragile] -\frametitle{Defining Construction Functions} - -\begin{columns} - -\column{0.45\textwidth} - -\begin{scala} -def Max2(x, y) = Mux(x > y, x, y) -\end{scala} -\begin{scala} -Max2(x, y) -\end{scala} - -\column{0.5\textwidth} - -\begin{center} -\includegraphics[width=0.95\textwidth]{figs/Max2.pdf} \\[1cm] -\end{center} - -\end{columns} - -\end{frame} - -\begin{frame}[fragile] -\frametitle{Functional Construction} - -\begin{columns} - -\column{0.5\textwidth} - -{\lstset{basicstyle={\scriptsize\ttfamily}} -\begin{scala} -class MaxN(n: Int, w: Int) extends Module { - val io = new Bundle { - val in = Vec.fill(n){ UInt(INPUT, w) } - val out = UInt(OUTPUT, w) - } - io.out := io.in.reduceLeft(Max2) -} -\end{scala} -} - -\column{0.4\textwidth} - -\begin{center} -\includegraphics[width=0.99\textwidth]{figs/reduceMax.pdf} \\ -\end{center} - -\end{columns} - -\end{frame} - -\begin{frame}[fragile] -\frametitle{Example} -\begin{columns} - -\column{0.45\textwidth} - -\begin{footnotesize} -\begin{scala} -class GCD extends Module { - val io = new Bundle { - val a = UInt(INPUT, 16) - val b = UInt(INPUT, 16) - val z = UInt(OUTPUT, 16) - val valid = Bool(OUTPUT) } - val x = Reg(init = io.a) - val y = Reg(init = io.b) - when (x > y) { - x := x - y - } .otherwise { - y := y - x - } - io.z := x - io.valid := y === UInt(0) -} -\end{scala} -\end{footnotesize} - -\column{0.45\textwidth} - -\begin{center} -\includegraphics[width=0.9\textwidth]{figs/gcd.pdf} -\end{center} - -\end{columns} -\end{frame} - -\setbeamercolor{frametitle}{bg=\frametitleproblemcolor} -\begin{frame}[fragile]{Running the Chisel Simulation} - -\begin{bash} -cd ~/chisel-tutorial/examples -make GCD.out -\end{bash} - -{\lstset{basicstyle={\scriptsize\ttfamily}} -\begin{bash} -... -PASSED -[success] Total time: 2 s, completed Feb 28, 2013 8:14:37 PM -\end{bash} -} - -\end{frame} -\setbeamercolor{frametitle}{bg=\frametitledefaultcolor} - -\setbeamercolor{frametitle}{bg=\frametitleproblemcolor} -\begin{frame}[fragile]{Generating Verilog} - -\begin{bash} -cd ~/chisel-tutorial/examples -make GCD.v -\end{bash} - -The Verilog source is roughly divided into three parts: - -\begin{enumerate} -\item Module declaration with input and outputs -\item Temporary wire and register declaration used for holding intermediate values -\item Register assignments in \verb+always @ (posedge clk)+ -\end{enumerate} - -\end{frame} -\setbeamercolor{frametitle}{bg=\frametitledefaultcolor} - -\begin{frame}[fragile]{FullAdder -- Type Inference} - -\begin{columns} -\column{0.4\textwidth} - -{\lstset{basicstyle={\scriptsize\ttfamily}} -\begin{scala} -class FullAdder extends Module { - val io = new Bundle { - val a = UInt(INPUT, 1) - val b = UInt(INPUT, 1) - val cin = UInt(INPUT, 1) - val sum = UInt(OUTPUT, 1) - val cout = UInt(OUTPUT, 1) - } - // Generate the sum - val a_xor_b = io.a ^ io.b - io.sum := a_xor_b ^ io.cin - // Generate the carry - val a_and_b = io.a & io.b - val b_and_cin = io.b & io.cin - val a_and_cin = io.a & io.cin - io.cout := - a_and_b | b_and_cin | a_and_cin -} -\end{scala} -} - -\column{0.55\textwidth} - -\begin{center} -\includegraphics[width=0.9\textwidth]{../getting-started/figs/Full_Adder.jpg} -\end{center} - -\end{columns} - -\end{frame} - -\begin{frame}[fragile]{FullAdder Verilog -- Width Inference 1} - -\begin{columns} -\column{0.45\textwidth} - -{\lstset{basicstyle={\scriptsize\ttfamily}} -\begin{scala} -class FullAdder extends Module { - val io = new Bundle { - val a = UInt(INPUT, 1) - val b = UInt(INPUT, 1) - val cin = UInt(INPUT, 1) - val sum = UInt(OUTPUT, 1) - val cout = UInt(OUTPUT, 1) - } - // Generate the sum - val a_xor_b = io.a ^ io.b - io.sum := a_xor_b ^ io.cin - // Generate the carry - val a_and_b = io.a & io.b - val b_and_cin = io.b & io.cin - val a_and_cin = io.a & io.cin - io.cout := - a_and_b | b_and_cin | a_and_cin -} -\end{scala} -} - -\column{0.45\textwidth} - -{\lstset{basicstyle={\scriptsize\ttfamily}} -\begin{scala} -module FullAdder( - input io_a, - input io_b, - input io_cin, - output io_sum, - output io_cout); - wire T0; - wire a_and_cin; - wire T1; - wire b_and_cin; - wire a_and_b; - wire T2; - wire a_xor_b; - - assign io_cout = T0; - assign T0 = T1 | a_and_cin; - assign a_and_cin = io_a & io_cin; - assign T1 = a_and_b | b_and_cin; - assign b_and_cin = io_b & io_cin; - assign a_and_b = io_a & io_b; - assign io_sum = T2; - assign T2 = a_xor_b ^ io_cin; - assign a_xor_b = io_a ^ io_b; -endmodule -\end{scala} -} - -\end{columns} - -\end{frame} - -\begin{frame}[fragile]{FullAdder2 Verilog -- Width Inference 2} - -\begin{columns} -\column{0.45\textwidth} - -{\lstset{basicstyle={\scriptsize\ttfamily}} -\begin{scala} -class FullAdder2 extends Module { - val io = new Bundle { - val a = UInt(INPUT, 2) - val b = UInt(INPUT, 2) - val cin = UInt(INPUT, 2) - val sum = UInt(OUTPUT, 2) - val cout = UInt(OUTPUT, 2) - } - // Generate the sum - val a_xor_b = io.a ^ io.b - io.sum := a_xor_b ^ io.cin - // Generate the carry - val a_and_b = io.a & io.b - val b_and_cin = io.b & io.cin - val a_and_cin = io.a & io.cin - io.cout := - a_and_b | b_and_cin | a_and_cin -} -\end{scala} -} - -\column{0.45\textwidth} - -{\lstset{basicstyle={\scriptsize\ttfamily}} -\begin{scala} -module FullAdder( - input [1:0] io_a, - input [1:0] io_b, - input [1:0] io_cin, - output[1:0] io_sum, - output[1:0] io_cout); - wire[1:0] T0; - wire[1:0] a_and_cin; - wire[1:0] T1; - wire[1:0] b_and_cin; - wire[1:0] a_and_b; - wire[1:0] T2; - wire[1:0] a_xor_b; - - assign io_cout = T0; - assign T0 = T1 | a_and_cin; - assign a_and_cin = io_a & io_cin; - assign T1 = a_and_b | b_and_cin; - assign b_and_cin = io_b & io_cin; - assign a_and_b = io_a & io_b; - assign io_sum = T2; - assign T2 = a_xor_b ^ io_cin; - assign a_xor_b = io_a ^ io_b; -endmodule -\end{scala} -} - -\end{columns} - -\end{frame} - -\begin{frame}[fragile]{Using Registers} -\begin{scala} -// clock the new reg value on every cycle -val y = io.x -val z = Reg(next = y) -\end{scala} - -\begin{scala} -// clock the new reg value when the condition a > b -val x = Reg(UInt()) -when (a > b) { x := y } -.elsewhen (b > a) { x := z } -.otherwise { x := w } -\end{scala} -\end{frame} - -\begin{frame}[fragile]{Unconditional Register Update} - -\begin{columns} - -\column{0.42\textwidth} - -{\lstset{basicstyle={\scriptsize\ttfamily}} -\begin{scala} -class ShiftRegister extends Module { - val io = new Bundle { - val in = UInt(INPUT, 1) - val out = UInt(OUTPUT, 1) - } - val r0 = Reg(next = io.in) - val r1 = Reg(next = r0) - val r2 = Reg(next = r1) - val r3 = Reg(next = r2) - io.out := r3 -} -\end{scala} -} -\begin{center} -\includegraphics[width=0.9\textwidth]{figs/shift-register.pdf} -\end{center} - -\column{0.5\textwidth} - -{\lstset{basicstyle={\scriptsize\ttfamily}} -\begin{scala} -module ShiftRegister(input clk, input reset, - input io_in, - output io_out); - - reg[0:0] r3; - reg[0:0] r2; - reg[0:0] r1; - reg[0:0] r0; - - assign io_out = r3; - always @(posedge clk) begin - r3 <= r2; - r2 <= r1; - r1 <= r0; - r0 <= io_in; - end -endmodule -\end{scala} -} - -\end{columns} - -\end{frame} - -\begin{frame}[fragile]{Conditional Register Update} - -\begin{columns} - -\column{0.47\textwidth} - -\begin{scala} -class ShiftRegister extends Module { - val io = new Bundle { - val in = UInt(INPUT, 1) - val shift = Bool(INPUT) - val out = UInt(OUTPUT, 1) - } - - val r0 = Reg(UInt()) - val r1 = Reg(UInt()) - val r2 = Reg(UInt()) - val r3 = Reg(UInt()) - - when (io.shift) { - r0 := io.in - r1 := r0 - r2 := r1 - r3 := r2 - } - io.out := r3 -} -\end{scala} - -\column{0.45\textwidth} - -\begin{center} -\includegraphics[width=0.9\textwidth]{figs/enable-shift-register.pdf} -\end{center} - -\end{columns} - -\end{frame} - -\begin{frame}[fragile]{Conditional Register Update with Reset} - -\begin{scala} -class EnableShiftRegister extends Module { - val io = new Bundle { - val in = UInt(INPUT, 1) - val shift = Bool(INPUT) - val out = UInt(OUTPUT, 1) - } - // Register reset to zero - val r0 = Reg(init = UInt(0, 1)) - val r1 = Reg(init = UInt(0, 1)) - val r2 = Reg(init = UInt(0, 1)) - val r3 = Reg(init = UInt(0, 1)) - when (io.shift) { - r0 := io.in - r1 := r0 - r2 := r1 - r3 := r2 - } - io.out := r3 -} -\end{scala} - -\end{frame} - -\begin{frame}[fragile]{UInt Literals} -inferred width -\begin{scala} -UInt(1) // decimal 1-bit literal from Scala Int. -UInt("ha") // hexadecimal 4-bit literal from string. -UInt("o12") // octal 4-bit literal from string. -UInt("b1010") // binary 4-bit literal from string. -\end{scala} -specified widths -\begin{scala} -UInt("h_dead_beef") // 32-bit literal of type UInt. -UInt(1) // decimal 1-bit literal from Scala Int. -UInt("ha", 8) // hexadecimal 8-bit literal of type UInt. -UInt("o12", 6) // octal 6-bit literal of type UInt. -UInt("b1010", 12) // binary 12-bit literal of type UInt. -UInt(5, 8) // unsigned decimal 8-bit literal of type UInt. -\end{scala} -\end{frame} - - -\setbeamercolor{frametitle}{bg=\frametitleproblemcolor} -\begin{frame}[fragile]{Sequential Circuit Problem -- \tt Accumulator.scala} -\begin{itemize} -\item write sequential circuit that sums \code{in} values -\item in {\tt chisel-tutorial/problems/Accumulator.scala} -\item run {\tt make Accumulator.out} until passing -\end{itemize} -\begin{scala} -class Accumulator extends Module { - val io = new Bundle { - val in = UInt(INPUT, 1) - val out = UInt(OUTPUT, 8) - } - - // flush this out ... - - io.out := UInt(0) -} -\end{scala} -\end{frame} -\setbeamercolor{frametitle}{bg=\frametitledefaultcolor} - -\begin{frame}[fragile]{UInt Operations and Conditional Assignment} - -\begin{columns} -\column{0.5\textwidth} - -{\lstset{basicstyle={\tiny\ttfamily}} -\begin{scala} -class BasicALU extends Module { - val io = new Bundle { - val a = UInt(INPUT, 4) - val b = UInt(INPUT, 4) - val opcode = UInt(INPUT, 4) - val output = UInt(OUTPUT, 4) - } - io.output := UInt(0) - when (io.opcode === UInt(0)) { - io.output := io.a // pass A - } .elsewhen (io.opcode === UInt(1)) { - io.output := io.b // pass B - } .elsewhen (io.opcode === UInt(2)) { - io.output := io.a + UInt(1) // inc A by 1 - } .elsewhen (io.opcode === UInt(3)) { - io.output := io.a - UInt(1) // dec B by 1 - } .elsewhen (io.opcode === UInt(4)) { - io.output := io.a + UInt(4) // inc A by 4 - } .elsewhen (io.opcode === UInt(5)) { - io.output := io.a - UInt(4) // dec A by 4 - } .elsewhen (io.opcode === UInt(6)) { - io.output := io.a + io.b // add A and B - } .elsewhen (io.opcode === UInt(7)) { - io.output := io.a - io.b // sub B from A - } .elsewhen (io.opcode === UInt(8)) { - io.output := (io.a < io.b) // set on A < B - } .otherwise { - io.output := (io.a === io.b) // set on A == B - } -} -\end{scala} -} - -\column{0.4\textwidth} -\begin{itemize} -\item wire \code{io.output} defaulted to 0 and then -\item conditionally reassigned to based on opcode -\item unlike registers, wires are required to be defaulted -\item wires also allow forward declarations -\end{itemize} -\end{columns} -\end{frame} - -\begin{frame}[fragile]{UInt Operations} - -\begin{center} -\begin{tabular}{| c | c | c | } -\hline -Symbol & Operation & Output Type \\ \hline -\verb!+! & Add & UInt \\ \hline -\verb+-+ & Subtract & UInt \\ \hline -\verb+*+ & Multiply & UInt \\ \hline -\verb+/+ & UInt Divide & UInt \\ \hline -\verb+%+ & Modulo & UInt \\ \hline -\verb+~+ & Bitwise Negation & UInt \\ \hline -\verb+^+ & Bitwise XOR & UInt\\ \hline -\verb+&+ & Bitwise AND & UInt \\ \hline -\verb+|+ & Bitwise OR & Bool \\ \hline -{\color{red}\verb+===+} & Equal & Bool \\ \hline -\verb+!=+ & Not Equal & Bool \\ \hline -\verb+>+ & Greater & Bool \\ \hline -\verb+<+ & Less & Bool \\ \hline -\verb+>=+ & Greater or Equal & Bool \\ \hline -\verb+<=+ & Less or Equal & Bool \\ \hline -\end{tabular} -\end{center} - -\end{frame} - -\begin{frame}[fragile]{Bit Extraction} -\begin{scala} -// extracts the x through y bits of value -val x_to_y = value(x, y) -\end{scala} - -\begin{scala} -// extract the x-th bit from value -val x_of_value = value(x) -\end{scala} -\end{frame} - -\begin{frame}[fragile]{ByteSelector} - -\begin{scala} -class ByteSelector extends Module { - val io = new Bundle { - val in = UInt(INPUT, 32) - val offset = UInt(INPUT, 2) - val out = UInt(OUTPUT, 8) - } - io.out := UInt(0, width = 8) - when (io.offset === UInt(0)) { - io.out := io.in(7,0) // pull out lowest byte - } .elsewhen (io.offset === UInt(1)) { - io.out := io.in(15,8) // pull out second byte - } .elsewhen (io.offset === UInt(2)) { - io.out := io.in(23,16) // pull out third byte - } .otherwise { - io.out := io.in(31,24) // pull out highest byte - } -} -\end{scala} - -\end{frame} - -% \setbeamercolor{frametitle}{bg=\frametitleproblemcolor} -% \begin{frame}[fragile]{Instruction Decoder} -% -% {\lstset{basicstyle={\scriptsize\ttfamily}} -% \begin{scala} -% class LoadShiftRegister extends Module { -% val io = new Bundle { -% val inst = UInt(INPUT, 32) -% val rs0 = UInt(OUTPUT, 8) -% val rs1 = UInt(OUTPUT, 8) -% val rs2 = UInt(OUTPUT, 8) -% val isAdd = Bool(OUTPUT) -% val isSub = Bool(OUTPUT) -% val isMul = Bool(OUTPUT) -% val isDiv = Bool(OUTPUT) -% } -% io.isAdd := ... -% io.isSub := ... -% io.isMul := ... -% io.isDiv := ... -% io.rs0 := ... -% io.rs1 := ... -% io.rs2 := ... -% } -% \end{scala} -% } -% -% \end{frame} -% \setbeamercolor{frametitle}{bg=\frametitledefaultcolor} - -\begin{frame}[fragile]{Bit Concatenation and Filling} -You concatenating bits using \verb+Cat+: -\begin{scala} -val A = UInt(width = 32) -val B = UInt(width = 32) -val bus = Cat(A, B) // concatenate A and B -\end{scala} - -and replicate bits using \verb+Fill+: -\begin{scala} -// Replicate a bit string multiple times. -val usDebt = Fill(3, UInt("hA")) -\end{scala} - -\end{frame} - -\setbeamercolor{frametitle}{bg=\frametitleproblemcolor} -\begin{frame}[fragile]{LFSR16 -- \tt problems/lfsr16.scala} - -\begin{scala} -class LFSR16 extends Module { - val io = new Bundle { - val inc = Bool(INPUT) - val out = UInt(OUTPUT, 16) - } - // ... - io.out := UInt(0) -} -\end{scala} -\begin{itemize} -\item \verb+reg+, \verb+cat+, \verb+extract+, \verb+^+ -\item init reg to 1 -\item updates when \verb+inc+ asserted -\end{itemize} - -\begin{center} -\includegraphics[width=0.9\textwidth]{figs/LFSR16.pdf} -\end{center} - -\end{frame} -\setbeamercolor{frametitle}{bg=\frametitledefaultcolor} - -\begin{frame}[fragile]{UInt Bit Inference} -\begin{columns} -\column{0.4\textwidth} -\begin{scala} -class HiLoMultiplier() - extends Module { - val io = new Bundle { - val A = UInt(INPUT, 16) - val B = UInt(INPUT, 16) - val Hi = UInt(OUTPUT, 16) - val Lo = UInt(OUTPUT, 16) - } - val mult = io.A * io.B - io.Lo := mult(15, 0) - io.Hi := mult(31, 16) -} -\end{scala} - -\column{0.5\textwidth} - -{\lstset{basicstyle={\scriptsize\ttfamily}} -\begin{scala} -module HiLoMultiplier( - input [15:0] io_A, - input [15:0] io_B, - output[15:0] io_Hi, - output[15:0] io_Lo); - - wire[15:0] T0; - wire[31:0] mult; // inferred as 32 bits - wire[15:0] T1; - - assign io_Lo = T0; - assign T0 = mult[4'hf:1'h0]; - assign mult = io_A * io_B; - assign io_Hi = T1; - assign T1 = mult[5'h1f:5'h10]; -endmodule -\end{scala} -} - -\end{columns} - -\end{frame} - -\begin{frame}[fragile]{Bit Inference Rules} - -\begin{center} -\begin{tabular}{| l | l | l | } -\hline -Operation & Result Bit Width \\ \hline -\verb!Z = X + Y! & max(Width(X), Width(Y)) \\ \hline -\verb+Z = X - Y+ & max(Width(X), Width(Y)) \\ \hline -\verb+Z = X & Y+ & min(Width(X), Width(Y)) \\ \hline -\verb+Z = X | Y+ & max(Width(X), Width(Y)) \\ \hline -\verb+Z = X ^ Y+ & max(Width(X), Width(Y)) \\ \hline -\verb+Z = ~X+ & Width(X) \\ \hline -\verb+Z = Mux(C, X, Y)+ & max(Width(X), Width (Y)) \\ \hline -\verb+Z = X * Y+ & Width(X) + Width(Y) \\ \hline -\verb+Z = X << n+ & Width(X) + n \\ \hline -\verb+Z = X >> n+ & Width(X) - n \\ \hline -\verb+Z = Cat(X, Y)+ & Width(X) + Width(Y) \\ \hline -\verb+Z = Fill(n, x)+ & Width(X) + n \\ \hline -\end{tabular} -\end{center} - -\end{frame} - -\begin{frame}[fragile]{Bool Type} -The Chisel Bool is used to represent the result of logical expressions: -\begin{scala} -val change = io.a === io.b // change gets Bool type -when (change) { // execute if change is true - ... -} -\end{scala} - -You can instantiate a Bool value like this: -\begin{scala} -val true_value = Bool(true) -val false_value = Bool(false) -\end{scala} - -You can cast an UInt to a Bool as follows: -\begin{scala} -val bit = UInt(width = 1) ... -when (bit.toBool) { ... } -\end{scala} - -You can use a Bool as an UInt: -\begin{scala} -val bit = UInt(width = 1) ... -bit := a > b -\end{scala} - -\end{frame} - -\begin{frame}[fragile]{Bits Subtype Hierarchy} -\begin{itemize} -\item \verb+SInt+ is a signed integer type -\end{itemize} -\begin{center} -\includegraphics[height=0.7\textheight]{figs/bits-hierarchy.pdf} -\end{center} -\end{frame} - -\begin{frame}[fragile]{Bundles} - -\begin{columns} -\column{0.55\textwidth} -\begin{scala} -class MyFloat extends Bundle { - val sign = Bool() - val exponent = UInt(width = 8) - val significand = UInt(width = 23) -} - -val x = new MyFloat() -val xs = x.sign -\end{scala} - -\column{0.35\textwidth} - -\begin{center} -\includegraphics[height=0.9\textheight]{../cs250/figs/myfloat.pdf} -\end{center} - -\end{columns} -\end{frame} - -\begin{frame}[fragile]{Ports} - -\begin{columns} -\column{0.55\textwidth} - -\textbf{Data object with directions assigned to its members} - -\begin{scala} -class Decoupled extends Bundle { - val data = UInt(INPUT, 32) - val valid = Bool(OUTPUT) - val ready = Bool(INPUT) -} -\end{scala} - -\textbf{Direction assigned at instantiation time} - -\begin{scala} -class ScaleIO extends Bundle { - val in = new MyFloat().asInput - val scale = new MyFloat().asInput - val out = new MyFloat().asOutput -} -\end{scala} - -\column{0.35\textwidth} - -\begin{center} -\includegraphics[height=0.9\textheight]{../cs250/figs/fifoio.pdf} -\end{center} - -\end{columns} - -\end{frame} - -\begin{frame}[fragile]{Instantiating Modules} - -\begin{columns} - -\column{0.4\textwidth} - -{\lstset{basicstyle={\tiny\ttfamily}} -\begin{scala} -// A 4-bit adder with carry in and carry out -class Adder4 extends Module { - val io = new Bundle { - val A = UInt(INPUT, 4) - val B = UInt(INPUT, 4) - val Cin = UInt(INPUT, 1) - val Sum = UInt(OUTPUT, 4) - val Cout = UInt(OUTPUT, 1) - } - // Adder for bit 0 - val Adder0 = Module(new FullAdder()) - Adder0.io.a := io.A(0) - Adder0.io.b := io.B(0) - Adder0.io.cin := io.Cin - val s0 = Adder0.io.sum - // Adder for bit 1 - val Adder1 = Module(new FullAdder()) - Adder1.io.a := io.A(1) - Adder1.io.b := io.B(1) - Adder1.io.cin := Adder0.io.cout - val s1 = Cat(Adder1.io.sum, s0) - ... - // Adder for bit 3 - val Adder3 = Module(new FullAdder()) - Adder3.io.a := io.A(3) - Adder3.io.b := io.B(3) - Adder3.io.cin := Adder2.io.cout - io.Sum := Cat(Adder3.io.sum, s2) - io.Cout := Adder3.io.cout -} -\end{scala} -} - -\column{0.5\textwidth} - -\begin{center} -\includegraphics[width=0.9\textwidth]{../getting-started/figs/4_Bit_Adder.jpg} -\end{center} - -\begin{itemize} -\item inherits from \verb+Module+ class, -\item contains an interface stored in a port field named \verb+io+, and -\item wires together subcircuits in its constructor. -\end{itemize} - -\end{columns} - -\end{frame} - -\begin{frame}[fragile]{Vecs} -constructing vecs -\begin{scala} -val myVec1 = Vec.fill( ) { } -val myVec2 = Vec(, , ...) -\end{scala} - -creating a vec of wires -\begin{scala} -val ufix5_vec10 = Vec.fill(10) { UInt(width = 5) } -\end{scala} - - -creating a vec of regs -\begin{scala} -val reg_vec32 = Vec.fill(32){ Reg() } -\end{scala} - -writing -\begin{scala} -reg_vec32(1) := UInt(0) -\end{scala} - -reading -\begin{scala} -val reg5 = reg_vec(5) -\end{scala} - -\end{frame} - -\setbeamercolor{frametitle}{bg=\frametitleproblemcolor} -\begin{frame}[fragile]{Vec Shift Reg -- problems/VecShiftRegister.scala} - -\begin{itemize} -\item add loadability to shift register -\item change interface to use vec's -\end{itemize} - -{\lstset{basicstyle={\scriptsize\ttfamily}} -\begin{scala} -class VecShiftRegister extends Module { - val io = new Bundle { - val ins = Vec.fill(4){ UInt(INPUT, 1) } - val load = Bool(INPUT) - val shift = Bool(INPUT) - val out = UInt(OUTPUT, 4) - } - val delays = Vec.fill(4){ Reg(UInt(width = 4)) } - when ( ... ) { - // fill in here ... - } .elsewhen (io.shift) { - ... - } - io.out := delays(3) -} -\end{scala} -} - -\end{frame} -\setbeamercolor{frametitle}{bg=\frametitledefaultcolor} - -% \begin{frame}[fragile]{Scala Console} -% \begin{FramedVerb} -% \end{FramedVerb} -% \end{frame} - -\begin{frame}[fragile]{Defining a Tester} - -\begin{columns} -\column{0.45\textwidth} -{\lstset{basicstyle={\tiny\ttfamily}} -\begin{scala} -package Tutorial -import Chisel._ - -class ByteSelector extends Module { - val io = new Bundle { - val in = UInt(INPUT, 32) - val offset = UInt(INPUT, 2) - val out = UInt(OUTPUT, 8) - } - io.out := UInt(0, width=8) - ... -} - -class BSTests(c: ByteSelector) extends Tester(c) { - val test_in = 12345678 - for (t <- 0 until 4) { - poke(c.io.in, test_in) - poke(c.io.offset, t) - step(1) - val ref_out = (test_in >> (t * 8)) & 0xFF - expect(c.io.out, ref_out) - } -} -\end{scala} -} -\begin{center} -\includegraphics[width=0.8\textwidth]{../tutorial/figs/DUT.pdf} -\end{center} - -\column{0.45\textwidth} -{\lstset{basicstyle={\tiny\ttfamily}} -\begin{scala} -class Tester[T <: Module] - (val c: T, val isTrace: Boolean = true) { - var t: Int - var ok: Boolean - val rnd: Random - def reset(n: Int = 1) - def step(n: Int): Int - def peek(data: Aggregate): Array[BigInt] - def peekAt(data: Mem[T], index: Int) - def peek(data: Bits): BigInt - def int(x: Boolean): BigInt - def int(x: Int): BigInt - def int(x: Bits): BigInt - def poke(data: Aggregate, x: Array[BigInt]) - def pokeAt(data: Mem[T], index: Int, x: BigInt) - def poke(data: Bits, x: BigInt) - def expect (good: Boolean, msg: String): Boolean - def expect (data: Bits, target: BigInt): Boolean -} -\end{scala} -} -\begin{tiny} -\noindent -which binds a tester to a module -and allows users to write tests using the given debug protocol. In particular, users utilize: -\begin{itemize} -\item \code{poke} to set input port and state values, -\item \code{step} to execute the circuit one time unit, -\item \code{peek} to read port and state values, and -\item \code{expect} to compare peeked circuit values to expected arguments. -\end{itemize} -\end{tiny} - -\end{columns} -\end{frame} - -\begin{frame}[fragile]{Simulation Debug Output} - -{\lstset{basicstyle={\tiny\ttfamily}} -\begin{scala} -> cd chisel-tutorial/examples -> make ByteSelector.out -STARTING ../emulator/problems/ByteSelector ---- -INPUTS - INPUT(ByteSelector__io_in.ByteSelector) = 12345678 - INPUT(ByteSelector__io_offset.ByteSelector) = 0 -OUTPUTS - READ OUTPUT(ByteSelector__io_out.ByteSelector) = 78 - EXPECTED: OUTPUT(ByteSelector__io_out.ByteSelector) = 78 - SUCCESS ---- -INPUTS - INPUT(ByteSelector__io_in.ByteSelector) = 12345678 - INPUT(ByteSelector__io_offset.ByteSelector) = 1 -OUTPUTS - READ OUTPUT(ByteSelector__io_out.ByteSelector) = 97 - EXPECTED: OUTPUT(ByteSelector__io_out.ByteSelector) = 97 - SUCCESS ---- -... ---- -INPUTS - INPUT(ByteSelector__io_in.ByteSelector) = 12345678 - INPUT(ByteSelector__io_offset.ByteSelector) = 3 -OUTPUTS - READ OUTPUT(ByteSelector__io_out.ByteSelector) = 0 - EXPECTED: OUTPUT(ByteSelector__io_out.ByteSelector) = 0 - SUCCESS -PASSED // Final pass assertion -[success] Total time: 26 s, ... -\end{scala} -} - -\end{frame} - -\begin{frame}{Testbench Ingredients} - -In particular, users utilize: -\begin{itemize} -\item \code{poke} to set input port and state values, -\item \code{step} to execute the circuit one time unit, -\item \code{peek} to read port and state values, and -\item \code{expect} to compare peeked circuit values to expected arguments. -\end{itemize} - -\end{frame} - -\setbeamercolor{frametitle}{bg=\frametitleproblemcolor} -\begin{frame}[fragile]{Testbench for MaxN -- \tt MaxN.scala} -\begin{columns} -\column{0.49\textwidth} - -\begin{itemize} -\item write a testbench for MaxN -\end{itemize} - -{\lstset{basicstyle={\scriptsize\ttfamily}} -\begin{scala} -class MaxN(val n: Int, val w: Int) - extends Module { - - def Max2(x: UInt, y: UInt) = - Mux(x > y, x, y) - - val io = new Bundle { - val ins = Vec.fill(n){ UInt(INPUT, w) } - val out = UInt(OUTPUT, w) - } - io.out := io.ins.reduceLeft(Max2) -} -\end{scala} -} -\begin{scala} -// returns random int in 0..lim-1 -val x = rnd.nextInt(lim) -\end{scala} - -\column{0.42\textwidth} - -{\lstset{basicstyle={\scriptsize\ttfamily}} -\begin{scala} -class MaxNTests(c: MaxN) extends Tester(c) { - for (i <- 0 until 10) { - for (j <- 0 until c.n) { - // FILL THIS IN HERE - poke(c.io.ins(0), 0) - } - // FILL THIS IN HERE - step(1) - expect(c.io.out, 1) - } -} -\end{scala} -} -\end{columns} -\end{frame} -\setbeamercolor{frametitle}{bg=\frametitledefaultcolor} - -\begin{frame}[fragile]{Dynamically Accessed Vec} -\begin{scala} -class MemorySearch extends Module { - val io = new Bundle { - val target = UInt(INPUT, 4) - val en = Bool(INPUT) - val address = UInt(OUTPUT, 3) - val done = Bool(OUTPUT) - } - val index = Reg(init = UInt(0, width = 3)) - val list = Vec(UInt(0), UInt(4), UInt(15), UInt(14), - UInt(2), UInt(5), UInt(13)){ UInt(width = 4) } - val memVal = list(index) - val done = !io.en && ((memVal === io.target) || (index === UInt(7))) - when (io.en) { - index := UInt(0) - } .elsewhen (done === Bool(false)) { - index := index + UInt(1) - } - io.done := done - io.address := index -} -\end{scala} -\end{frame} - -\begin{frame}[fragile]{RAM} -RAM is supported using the \code{Mem} construct - -\begin{scala} -val m = Mem(Bits(width = 32), 32) -\end{scala} - -\noindent -where -\begin{itemize} -\item writes to Mems are positive-edge-triggered -\item reads are either combinational or positive-edge-triggered -\item ports are created by applying a \code{UInt} index -\end{itemize} -\end{frame} - -\begin{frame}[fragile]{32-entry Register File} - -\begin{scala} -val regs = Mem(Bits(width = 32), 32) -when (wrEn) { - regs(wrAddr) := wrData -} -val iDat = regs(iAddr) -val mDat = regs(mAddr) -\end{scala} - -\begin{center} -\includegraphics[height=0.55\textheight]{../cs250/figs/mem.pdf} -\end{center} - -\end{frame} - -\setbeamercolor{frametitle}{bg=\frametitleproblemcolor} -\begin{frame}[fragile]{Load/Search Mem -- \tt DynamicMemorySearch.scala} -\begin{scala} -class DynamicMemorySearch extends Module { - val io = new Bundle { - val isWr = Bool(INPUT) - val wrAddr = UInt(INPUT, 3) - val data = UInt(INPUT, 4) - val en = Bool(INPUT) - val target = UInt(OUTPUT, 3) - val done = Bool(OUTPUT) - } - val index = Reg(init = UInt(0, width = 3)) - val memVal = ... - val done = !io.en && ((memVal === io.data) || (index === UInt(7))) - // ... - when (io.en) { - index := UInt(0) - } .elsewhen (done === Bool(false)) { - index := index + UInt(1) - } - io.done := done - io.target := index -} -\end{scala} -\end{frame} -\setbeamercolor{frametitle}{bg=\frametitledefaultcolor} - -\begin{frame}[fragile]{Sequential Read Ports} -Sequential read ports are inferred when: -\begin{itemize} -\item optional parameter \code{seqRead} is set and -\item read address is a reg -\end{itemize} - -\begin{scala} -val ram1r1w = Mem(UInt(width = 32), 1024, seqRead = true) -val reg_raddr = Reg(UInt()) -when (wen) { ram1r1w(waddr) := wdata } -when (ren) { reg_raddr := raddr } -val rdata = ram1r1w(reg_raddr) -\end{scala} - -\begin{center} -\includegraphics[height=0.4\textheight]{../cs250/figs/mem-seq-read.pdf} -\end{center} - -\end{frame} - -\begin{frame}[fragile]{Stack} - -{\lstset{basicstyle={\tiny\ttfamily}} -\begin{scala} -class Stack(depth: Int) extends Module { - val io = new Bundle { - val dataIn = UInt(INPUT, 32) - val dataOut = UInt(OUTPUT, 32) - val push = Bool(INPUT) - val pop = Bool(INPUT) - val en = Bool(INPUT) - } - // declare the memory for the stack - val stack_mem = Mem(UInt(width = 32), depth, seqRead = false) - val sp = Reg(init = UInt(0, width = log2Up(depth))) - val dataOut = Reg(init = UInt(0, width = 32)) - // Push condition - make sure stack isn't full - when(io.en && io.push && (sp != UInt(depth-1))) { - stack_mem(sp + UInt(1)) := io.dataIn - sp := sp + UInt(1) - } - // Pop condition - make sure the stack isn't empty - .elsewhen(io.en && io.pop && (sp > UInt(0))) { - sp := sp - UInt(1) - } - when(io.en) { - dataOut := stack_mem(sp) - } - io.dataOut := dataOut -} -\end{scala} -} - -\end{frame} - -\begin{frame}[fragile]{Scripting Hardware Generation} - -\begin{columns} -\column{0.5\textwidth} - -{\lstset{basicstyle={\tiny\ttfamily}} -\begin{scala} -// A n-bit adder with carry in and carry out -class Adder(n: Int) extends Module { - val io = new Bundle { - val A = UInt(INPUT, n) - val B = UInt(INPUT, n) - val Cin = UInt(INPUT, 1) - val Sum = UInt(OUTPUT, n) - val Cout = UInt(OUTPUT, 1) - } - // create a vector of FullAdders - val FAs = Vec.fill(n){ Module(new FullAdder()).io } - val carry = Vec.fill(n+1){ UInt(width = 1) } - val sum = Vec.fill(n){ Bool() } - - // first carry is the top level carry in - carry(0) := io.Cin - - // wire up the ports of the full adders - for(i <- 0 until n) { - FAs(i).a := io.A(i) - FAs(i).b := io.B(i) - FAs(i).cin := carry(i) - carry(i+1) := FAs(i).cout - sum(i) := FAs(i).sum.toBool() - } - io.Sum := sum.toBits().toUInt() - io.Cout := carry(n) -} -\end{scala} -} - -\column{0.4\textwidth} - -\begin{center} -\includegraphics[width=0.9\textwidth]{../getting-started/figs/4_Bit_Adder.jpg} -\end{center} -\end{columns} - -\end{frame} - -\input{../talks/microsoft/libs-to-langs-guts-in-scala.tex} - -\setbeamercolor{frametitle}{bg=\frametitleproblemcolor} -\begin{frame}[fragile]{Mul Lookup Table Problem -- \tt Mul.scala} -\begin{itemize} -\item write 16x16 multiplication table using \code{Vec} -\end{itemize} -\begin{scala} -class Mul extends Module { - val io = new Bundle { - val x = UInt(INPUT, 4) - val y = UInt(INPUT, 4) - val z = UInt(OUTPUT, 8) - } - val muls = new ArrayBuffer[UInt]() - - // flush this out ... - - io.z := UInt(0) -} -\end{scala} - -hint: -\begin{scala} -val tab = Vec(muls) -io.z := tab(Cat(io.x, io.y)) -\end{scala} - -\end{frame} -\setbeamercolor{frametitle}{bg=\frametitledefaultcolor} - -\begin{frame}[fragile] -\frametitle{Valid Wrapper} - -\begin{columns} - -\column{0.65\textwidth} - -\begin{footnotesize} -\begin{scala} -class Valid[T <: Data](dtype: T) extends Bundle { - val data = dtype.clone.asOutput - val valid = Bool(OUTPUT) - override def clone = new Valid(dtype) -} - -class GCD extends Module { - val io = new Bundle { - val a = UInt(INPUT, 16) - val b = UInt(INPUT, 16) - val out = new Valid(UInt(OUTPUT, 16)) - } } - ... - io.out.data := x - io.out.valid := y === UInt(0) -} - -\end{scala} -\end{footnotesize} - -\column{0.3\textwidth} - -\begin{center} -\includegraphics[width=0.9\textwidth]{../talks/retreat-1/figs/valid.pdf} -\end{center} - -\end{columns} -\note{now gcd had a valid signal on its output. \\[1cm] -we can generalize this idea by defining a wrapper class that bundles a valid with a data signal. \\[1cm] -now we can rewrite GCD using an interface using this valid wrapper for its output. } - -\end{frame} - -\begin{frame}[fragile] -\frametitle{Function Filters} - -\begin{footnotesize} -\begin{scala} -abstract class Filter[T <: Data](dtype: T) extends Module { - val io = new Bundle { - val in = Valid(dtype).asInput - val out = Valid(dtype).asOutput -} } - -class FunctionFilter[T <: Data](dtype: T, f: T => T) extends Filter(dtype) { - io.out.valid := io.in.valid - io.out.bits := f(io.in) -} -\end{scala} -\end{footnotesize} - -\begin{center} -\includegraphics[height=0.4\textheight]{../talks/sketching13/figs/function-filter.pdf} -\end{center} - -\note{suppose we want to write hardware filters. \\[1cm] -one way to create a reusable filter would be \\[1cm] -to create a filter class that takes a function as argument that definines its filter operation.} - -\end{frame} - -\begin{frame}[fragile] -\frametitle{Clipping Filter} - -\begin{footnotesize} -\begin{scala} -def clippingFilter[T <: Bits](limit: Int, dtype: T) = - new FunctionFilter(dtype, x => min(limit, max(-limit, x))) -\end{scala} -\end{footnotesize} - -\begin{center} -\includegraphics[height=0.4\textheight]{../talks/retreat-1/figs/clipping-filter.pdf} -\end{center} -\note{using this reusable substrate then it is easy to create an instance of a filter.} -\end{frame} - - -\begin{frame}[fragile] -\frametitle{Shifting Filter} - -\begin{footnotesize} -\begin{scala} -def shiftingFilter[T <: Bits](shift: Int, dtype: T) = - new FunctionFilter(dtype, x => x >> shift) -\end{scala} -\end{footnotesize} - -\begin{center} -\includegraphics[height=0.4\textheight]{../talks/retreat-1/figs/shifting-filter.pdf} -\end{center} -\note{and reuse it for shift filter} -\end{frame} - -\begin{frame}[fragile]{Testing Decoupled Circuits} - -\begin{itemize} -\item using ovars for outputs -\item need to check outputs directly using \verb+litValue+ -\end{itemize} -\begin{scala} -class GCDTests(c: GCD) extends Tester(c) { - val (a, b, z) = (64, 48, 16) - do { - poke(c.io.a, a) - poke(c.io.b, b) - step(1) - } while (t <= 1 || peek(c.io.v) == 0) - expect(c.io.z, z) -} -\end{scala} - -\end{frame} - -\begin{frame}[fragile] -\frametitle{Chained Filter} - -\begin{footnotesize} -\begin{scala} -class ChainedFilter[T <: Num](dtype: T) extends Filter(dtype) = { - val shift = Module(new ShiftFilter(2, dtype)) - val clipper = Module(new ClippingFilter(1 << 7, dtype)) - io.in <> shift.io.in - shift.io.out <> clipper.io.in - clipper.io.out <> io.out -} -\end{scala} -% \begin{scala} -% class ChainedFilter[T <: Num](dtype: T) extends Filter(dtype) = { -% val fir = new TstFIR(dtype) -% val shift = new ShiftFilter(2, dtype) -% val clipper = new ClippingFilter(1 << 7, dtype) -% io.in <> fir.io.in -% fir.io.out <> shift.io.in -% shift.io.out <> clipper.io.in -% clipper.io.out <> io.out -% } -% \end{scala} -\end{footnotesize} - -\begin{center} -\includegraphics[height=0.4\textheight]{../talks/sketching13/figs/chained-filter2.pdf} -\end{center} -\note{and chain together...} -\end{frame} - -\begin{frame}[fragile]{Predicate Filter} -\begin{scala} -class PredicateFilter[T <: Data](dtype: T, f: T => Bool) - extends Filter(dtype) { - io.out.valid := io.in.valid && f(io.in.bits) - io.out.bits := io.in.bits -} -\end{scala} - -\begin{center} -\includegraphics[height=0.4\textheight]{figs/predicate-filter.pdf} -\end{center} -\end{frame} - -\setbeamercolor{frametitle}{bg=\frametitleproblemcolor} -\begin{frame}[fragile]{Predicate Filtering -- \tt SingleEvenFilter.scala} -\begin{itemize} -\item write filter that lets only even single digit numbers through -\end{itemize} -\begin{scala} -object SingleFilter { - def apply[T <: UInt](dtype: T) = // FILL IN FUNCTION BELOW - Module(new PredicateFilter(dtype, (x: T) => Bool(false))) -} - -object EvenFilter { - def apply[T <: UInt](dtype: T) = // FILL IN FUNCTION BELOW - Module(new PredicateFilter(dtype, (x: T) => Bool(false))) -} - -class SingleEvenFilter[T <: UInt](dtype: T) extends Filter(dtype) { - // FILL IN CONSTRUCTION AND WIRING - io.out := UInt(0) -} -\end{scala} -\end{frame} -\setbeamercolor{frametitle}{bg=\frametitledefaultcolor} - -\begin{frame}[fragile, shrink] -\frametitle{Functional Composition} - -% \begin{itemize} -% \item natural -% \item reusable -% \item composable -% \end{itemize} -% \vskip1cm - -\begin{Large} -\begin{columns} - -\column{0.45\textwidth} -\verb+Map(ins, x => x * y)+ \\ -\begin{center} -\includegraphics[height=0.6\textheight]{../bootcamp/figs/map.pdf} \\[2cm] -\end{center} - -\column{0.45\textwidth} -\vskip2mm -\verb+Chain(n, in, x => f(x))+ \\ -\begin{center} -\includegraphics[width=0.9\textwidth]{../bootcamp/figs/chain.pdf} \\ -\end{center} - -\verb+Reduce(ins, Max)+ \\ -\begin{center} -\includegraphics[width=0.9\textwidth]{../bootcamp/figs/reduce.pdf} \\ -\end{center} - -\end{columns} - -\end{Large} -\note{the previous example showed a simple use of functional programming. \\[1cm] -Scala provides strong support for functional programming and -it turns out that functional programming is a powerful way to define hardware. \\[1cm] -for example, you can create a parallel set of blocks using map and reduce to creation reduction trees and chain to create a pipeline.} -\end{frame} - -\begin{frame}[fragile]{Flo Map / Reduce Generator} - -{\lstset{basicstyle={\scriptsize\ttfamily}} -\begin{scala} -object FloDelays { - def apply(x: Flo, n: Int): List[Flo] = - if (n <= 1) List(x) else x :: FloDelays(RegNext(x), n-1) -} -object FloFIR { - def apply(ws: Seq[Flo], x: T): T = - (ws, FloDelays(x, ws.length)).zipped.map( _ * _ ).reduce( _ + _ ) -} -class FIR extends Module { - val io = new Bundle { val x = Flo(INPUT); val z = Flo(OUTPUT) } - val ws = Array(Flo(0.25), Flo(0.75)) - io.z := FloFIR(ws, io.x) -} -\end{scala} -} -\begin{center} -\includegraphics[height=0.35\textheight]{../cs294-88/lectures/advanced-chisel/figs/inner-product-fir.png} -\end{center} -\note{as an advanced example, consider writing an FIR filter which is defined by the equation below. \\[1cm] -essentially it's a sum of products of coefficients and delayed versions of input.\\[1cm] -we can write this quite simply using map and reduce as above.} -\end{frame} - -\begin{frame}[fragile]{Generic Map / Reduce Generator} - -{\lstset{basicstyle={\scriptsize\ttfamily}} -\begin{scala} -object Delays { - def apply[U <: Data](x: U, n: Int): List[U] = - if (n <= 1) List(x) else x :: Delays(RegNext(x), n-1) -} -object GenFIR { - def apply[T <: Data with Num[T]](ws: Seq[T], x: T): T = - (ws, Delays(x, ws.length)).zipped.map( _ * _ ).reduce( _ + _ ) -} -class FIR extends Module { - val io = new Bundle { val x = Flo(INPUT); val z = Flo(OUTPUT) } - val ws = Array(Flo(0.25), Flo(0.75)) - io.z := GenFIR(ws, io.x) -} -\end{scala} -} -\begin{center} -\includegraphics[height=0.35\textheight]{../cs294-88/lectures/advanced-chisel/figs/inner-product-fir.png} -\end{center} -\note{as an advanced example, consider writing an FIR filter which is defined by the equation below. \\[1cm] -essentially it's a sum of products of coefficients and delayed versions of input.\\[1cm] -we can write this quite simply using map and reduce as above.} -\end{frame} - -\begin{frame}[fragile]{Chisel Standard Library -- \tt ChiselUtil.scala} -\begin{center} -\begin{tabular}{rl} -{\bf Bits Properities} & \code{log2Up}, \code{log2Down}, \code{isPow2}, \code{PopCount}\\ -{\bf Numeric Utilities} & \code{LFSR16}, \code{Reverse}, \code{FillInterleaved} \\ -{\bf Stateful Functions} & \code{ShiftRegister}, \code{Counter} \\ -{\bf Priority Encoding Functions} & \code{UIntToOH}, \code{OHToUInt}, \code{Mux1H} \\ -{\bf Priority Encoders} & \code{PriorityEncoder}, \code{PriorityEncoderOH} \\ -{\bf Vec Construction} & \code{Vec.fill}, \code{Vec.tabulate} \\ -{\bf Vec Functional} & \code{forall}, \code{exists}, \code{contains}, ... \\ -{\bf Queues and Pipes} & \code{Decoupled}, \code{Queue}, \code{Valid}, \code{Pipe} \\ -{\bf Arbiters} & \code{ArbiterIO}, \code{Arbiter}, \code{RRArbiter} \\ -\end{tabular} -\end{center} -\end{frame} - -\begin{frame}[fragile] -\frametitle{Queues} -\begin{itemize} -\item Required parameter \verb+entries+ controls depth -\item The width is determined from the inputs. -\end{itemize} -\begin{scala} -class QueueIO[T <: Data](type: T, entries: Int) extends Bundle { - val enq = Decoupled(data.clone).flip - val deq = Decoupled(data.clone) - val count = UFix(OUTPUT, log2Up(entries+1)) -} - -class Queue[T <: Data] - (type: T, entries: Int, - pipe: Boolean = false, - flow: Boolean = false - flushable: Boolean = false) - extends Module -\end{scala} -\begin{scala} -val q = new Queue(UInt(), 16) -q.io.enq <> producer.io.out -consumer.io.in <> q.io.deq -\end{scala} -\end{frame} - -\begin{frame}[fragile]{Multiple Clock Domains} -Clocks are first class and take a name argument: -\begin{scala} -class Clock (val name: String) extends Node { -} -\end{scala} -\noindent -and when constructed define a clock at top-level with the given name: -\begin{scala} -val clkA = new Clock("A") -\end{scala} - -There is a builtin implicit clock that state elements use by default: -\begin{scala} -class Module { - def clock(): Clock - def reset(): Bool - ... -} -\end{scala} - -% Clocks can be defined from other clocks: -% \begin{scala} -% val clock2 = clock1 * 2 -% val clock3 = clock1 / 2 -% \end{scala} - -\end{frame} - -\begin{frame}[fragile]{Specifying a Clock Domain} -The clock for state elements and modules can be specified: -\begin{scala} -Reg(... explClock: Clock = clock()) -Mem(... explClock: Clock = clock()) -Module(... explClock: Clock = clock()) -\end{scala} - -For example, a register can be created in a different clock domain as follows: -\begin{scala} -val reg = Reg(UInt(), explClock = clock2) -\end{scala} - -\end{frame} - -\begin{frame}[fragile]{Crossing Clock Domains} -The most general technique to send data between domains is using an asynchronous queue: - -\begin{scala} -class AsyncQueue[T <: Data] - (dataType: T, depth: Int, enq_clk: Clock, deq_clock: Clock) extends Module -\end{scala} - -Using these queues, we can then move a signalA from clock domains clockA to signalB in clockB: - -\begin{scala} -val queue = new AsyncQueue(Uint(width = 32), 2, clockA, clockB) -fifo.enq.bits := signalA -signalB := fifo.deq.bits -fifo.valid := condA -fifo.ready := condB -... -\end{scala} - -\end{frame} - -\begin{frame}[fragile]{Multiple Clocks -- \tt MultipleClockDomains.scala} -\begin{scala} -class MultiClockDomain extends Module { - val io = new Bundle { - val start = Bool(INPUT) - val sum = Decoupled(UInt(OUTPUT)) - } - val fastClock = new Clock() - val slowClock = new Clock() - ... -} - -class MultiClockDomainTests(c: MultiClockDomain) - extends Tester(c, Array(c.io)) { - val clocks = new HashMap[Clock, Int] - clocks(Module.implicitClock) = 2 - clocks(c.fastClock) = 4 - clocks(c.slowClock) = 6 - setClocks(clocks) - ... -} -\end{scala} -\end{frame} - -\begin{frame}[fragile]{Creating Your Own Project} -directory structure -\begin{bash} -Hello/ - build.sbt # scala configuration file - Hello.scala # your source file -\end{bash} - -\end{frame} - -\begin{frame}[fragile]{Writing Your Source File} - -{\lstset{basicstyle={\scriptsize\ttfamily}} -\begin{scala} -package Hello -import Chisel._ - -class Hello extends Module { - val io = new Bundle { - val out = UInt(OUTPUT, 8) } - io.out := UInt(33) -} - -class HelloTests(c: Hello) extends Tester(c) { - step(1) - expect(c.io.out, 33) -} - -object Hello { - def main(args: Array[String]): Unit = { - val args = Array("--backend", "c", "--genHarness", "--compile", "--test") - chiselMainTest(args, () => Module(new Hello())) { - c => new HelloTests(c) } -} } -\end{scala} -} - -\end{frame} - -\begin{frame}[fragile]{Setting Up Your SBT Configuration File} -\begin{scala} -scalaVersion := "2.10.2" - -addSbtPlugin("com.github.scct" % "sbt-scct" % "0.2") - -libraryDependencies += - "edu.berkeley.cs" %% "chisel" % "latest.release" -\end{scala} -\end{frame} - -\begin{frame}[fragile]{Compiling and Running} -Producing C++ -\begin{bash} -sbt run "--backend c" -\end{bash} - -Producing Verilog -\begin{bash} -sbt run "--backend v" -\end{bash} - -Running the Chisel Tests -\begin{bash} -sbt run "--backend c --compile --test --genHarness" -\end{bash} - -\end{frame} - -\begin{frame}[fragile]{chiselMain(Test) Command Line Arguments} -\begin{scala} -sbt -sbt> compile // compiles Chisel Scala code -sbt> run // compile and run Chisel Scala Code -sbt> run --backend c // produces C++ files -sbt> exit -\end{scala} - -with a complete set of command line arguments being:\\[2mm] - -\begin{tabular}{lll} -\verb+--backend v+ & generate verilog \\ -\verb+--backend c+ & generate C++ (default)\\ -\verb+--vcd+ & enable vcd dumping \\ -\verb+--targetDir+ & target pathname prefix \\ -\verb+--genHarness+ & generate harness file for C++ \\ -\verb+--debug+ & put all wires in C++ class file \\ -\verb+--compile+ & compiles generated C++ \\ -\verb+--test+ & runs tests using C++ app \\ -\end{tabular} -\end{frame} - -\setbeamercolor{frametitle}{bg=\frametitleproblemcolor} -\begin{frame}[fragile]{Make Your Own Project} -set hello project up -\begin{bash} -cd ~ -mkdir hello -cp -r ~/chisel-tutorial/hello/* hello -cd hello -sbt run -\end{bash} -make a change -\begin{itemize} -\item make output a function of an new input -\end{itemize} -\end{frame} -\setbeamercolor{frametitle}{bg=\frametitledefaultcolor} - -\begin{frame}{Chisel Workflow} -\begin{center} -\includegraphics[height=0.9\textheight]{../bootcamp/figs/chisel-workflow.pdf} -\end{center} -\end{frame} - -\begin{frame}[fragile]{printf / sprintf} -\begin{itemize} -\item during simulation -\begin{itemize} -\item \verb+printf+ prings the formatted string to the console on rising clock edges -\item \verb+sprintf+ returns the formatted string as a bit vector -\end{itemize} -\item format specifiers are -\begin{itemize} -\item \verb+%b+ -- binary number -\item \verb+%d+ -- decimal number -\item \verb+%x+ -- hexidecimal number -\item \verb+%e+ -- floating point number in scientific notation -\item \verb+%s+ -- string consisting of a sequence of 8-bit extended ASCII chars -\item \verb+%%+ -- specifies a literal %. -\end{itemize} -\end{itemize} -the following prints the line \verb+"0x4142 16706 AB"+ on cycles when \verb+c+ is true: -\begin{scala} -val x = Bits(0x4142) -val s1 = sprintf("%x %s", x, x); -when (c) { printf("%d %s\n", x, s1); } -\end{scala} -\end{frame} - -\begin{frame}[fragile]{assert} -\begin{itemize} -\item simulation time assertions are provided by \verb+assert+ construct -\item if assert arguments false on rising edge then -\begin{itemize} -\item an error is printed and -\item simulation terminates -\end{itemize} -\end{itemize} -the following will terminate after 10 clock cycles: -\begin{scala} -val x = Reg(init = UInt(0, 4)) -x := x + UInt(1) -assert(x < UInt(10)) -\end{scala} -\end{frame} - -\begin{frame}[fragile]{Installation} -\begin{itemize} -\item on mac install: -\begin{itemize} -\item XCODE console tools -\end{itemize} -\item on windows install: -\begin{itemize} -\item cygwin -\end{itemize} -\item everywhere install: -\begin{itemize} -\item git -\item g++ version 4.0 or later -\item java -\end{itemize} -\item everywhere -\begin{itemize} -\item git clone https://github.com/ucb-bar/chisel-tutorial.git -\end{itemize} -\end{itemize} - -\end{frame} - -\begin{frame}[fragile]{Chisel Resources} -\begin{center} -\url{https://chisel.eecs.berkeley.edu/documentation.html} \\[0.25cm] -\begin{tabular}{rl} -\textbf{getting started} & \code{getting-started.pdf} \\ -\textbf{tutorial} & \code{tutorial.pdf} \\ -\textbf{manual} & \code{manual.pdf} \\ -% \textbf{bootcamp} & \code{bootcamp.pdf} \\ -\end{tabular} -\url{https://github.com/ucb-bar/chisel/} \\[0.25cm] -\begin{tabular}{rl} -\textbf{setup} & \code{readme.md} \\ -\textbf{utils} & \code{src/main/scala/ChiselUtils.scala} \\[0.5cm] -\end{tabular} -\url{https://chisel.eecs.berkeley.edu/download.html} \\[0.25cm] -\begin{tabular}{rl} -\textbf{sodor} & \url{https://github.com/ucb-bar/riscv-sodor/} \\ -% \textbf{virtualbox} & \url{https://chisel.eecs.berkeley.edu/chisel-riscv.box} \\ -\end{tabular} -\end{center} -\end{frame} - -\begin{frame}{Scala Resources} - -\begin{center} -\includegraphics[height=0.4\textheight]{../bootcamp/figs/programming-scala.pdf} \\ -\includegraphics[height=0.4\textheight]{../bootcamp/figs/programming-in-scala.pdf} -\end{center} - -\end{frame} - -\begin{frame}[fragile]{Projects Ideas} - -\begin{center} -\begin{tabular}{rl} -\textbf{audio processing} & \code{Echo.scala} \\ -\textbf{image processing} & \code{Darken.scala} \\ -\textbf{risc processor} & \code{Risc.scala} \\ -\textbf{game of life} & \code{Life.scala} \\ -\textbf{router} & \code{Router.scala} \\ -\textbf{map/reduce} & \code{FIR.scala}\\ -\textbf{network} & \\ -\textbf{decoupled filter} & \\ -\textbf{cryptography} & \\ -\textbf{serial multiplier} & \\ -\textbf{pong} & \\ -\end{tabular} -\end{center} - -\end{frame} - -\begin{frame}[fragile]{Keep in Touch} -\begin{center} -\begin{tabular}{rl} -\textbf{website} & \url{chisel.eecs.berkeley.edu} \\ -\textbf{mailing list} & \url{groups.google.com/group/chisel-users} \\ -\textbf{github} & \url{https://github.com/ucb-bar/chisel/} \\ -\textbf{features + bugs} & \url{https://github.com/ucb-bar/chisel/issues} \\ -\textbf{more questions} & \url{stackoverflow.com/quesions/tagged/chisel} \\ -\textbf{twitter} & {\tt \#chiselhdl} \\ -\textbf{me} & \url{jrb@eecs.berkeley.edu} \\ -\end{tabular} -\end{center} -\end{frame} - -\begin{frame}{Thanks} -\begin{itemize} -\item \textbf{Arrangements} -- HPCA folks -\item \textbf{USB Sticks} -- Albert Magyar + Jim Lawson -\item \textbf{Bootcamp Materials} -- JB, Vincent Lee, Stephen Twigg, Huy Vo -\item \textbf{Funding} -- Department of Energy, Department of Defense, StarNet, C-Far, LBNL, Intel, Google, LG, Nvidia, Samsung, Oracle, Huawei -\end{itemize} -\end{frame} - -\end{document} diff --git a/doc/bootcamp/figs/LFSR16.graffle b/doc/bootcamp/figs/LFSR16.graffle deleted file mode 100644 index 56a82fdb..00000000 Binary files a/doc/bootcamp/figs/LFSR16.graffle and /dev/null differ diff --git a/doc/bootcamp/figs/LFSR16.pdf b/doc/bootcamp/figs/LFSR16.pdf deleted file mode 100644 index 5da4c908..00000000 Binary files a/doc/bootcamp/figs/LFSR16.pdf and /dev/null differ diff --git a/doc/bootcamp/figs/bits-hierarchy.graffle b/doc/bootcamp/figs/bits-hierarchy.graffle deleted file mode 100644 index 844b0031..00000000 Binary files a/doc/bootcamp/figs/bits-hierarchy.graffle and /dev/null differ diff --git a/doc/bootcamp/figs/bits-hierarchy.pdf b/doc/bootcamp/figs/bits-hierarchy.pdf deleted file mode 100644 index 27cc2191..00000000 Binary files a/doc/bootcamp/figs/bits-hierarchy.pdf and /dev/null differ diff --git a/doc/bootcamp/figs/chain.graffle b/doc/bootcamp/figs/chain.graffle deleted file mode 100644 index 242c1684..00000000 --- a/doc/bootcamp/figs/chain.graffle +++ /dev/null @@ -1,533 +0,0 @@ - - - - - ActiveLayerIndex - 0 - ApplicationVersion - - com.omnigroup.OmniGrafflePro - 139.16.0.171715 - - AutoAdjust - - BackgroundGraphic - - Bounds - {{0, 0}, {576, 733}} - Class - SolidGraphic - ID - 2 - Style - - shadow - - Draws - NO - - stroke - - Draws - NO - - - - BaseZoom - 0 - CanvasOrigin - {0, 0} - ColumnAlign - 1 - ColumnSpacing - 36 - CreationDate - 2012-05-29 16:36:31 +0000 - Creator - Jonathan Bachrach - DisplayScale - 1 0/72 in = 1.0000 in - GraphDocumentVersion - 8 - GraphicsList - - - Bounds - {{80, 162}, {19, 29}} - Class - ShapedGraphic - FitText - YES - Flow - Resize - FontInfo - - Font - Helvetica - Size - 24 - - ID - 12 - Shape - Rectangle - Style - - fill - - Draws - NO - - shadow - - Draws - NO - - stroke - - Draws - NO - - - Text - - Pad - 0 - Text - {\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf340 -\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc - -\f0\fs48 \cf0 in} - VerticalPad - 0 - - Wrap - NO - - - Class - LineGraphic - FontInfo - - Font - Helvetica - Size - 49 - - ID - 10 - Points - - {415, 180} - {450, 180} - - Style - - stroke - - HeadArrow - StickArrow - Legacy - - TailArrow - 0 - Width - 2 - - - Tail - - ID - 5 - - - - Class - LineGraphic - FontInfo - - Font - Helvetica - Size - 49 - - Head - - ID - 5 - - ID - 8 - Points - - {316, 180} - {341, 180} - - Style - - stroke - - HeadArrow - StickArrow - Legacy - - TailArrow - 0 - Width - 2 - - - Tail - - ID - 4 - - - - Class - LineGraphic - FontInfo - - Font - Helvetica - Size - 49 - - Head - - ID - 4 - - ID - 7 - Points - - {217, 180} - {242, 180} - - Style - - stroke - - HeadArrow - StickArrow - Legacy - - TailArrow - 0 - Width - 2 - - - Tail - - ID - 3 - - - - Class - LineGraphic - FontInfo - - Font - Helvetica - Size - 49 - - Head - - ID - 3 - - ID - 6 - Points - - {108, 180} - {143, 180} - - Style - - stroke - - HeadArrow - StickArrow - Legacy - - TailArrow - 0 - Width - 2 - - - - - Bounds - {{342, 144}, {72, 72}} - Class - ShapedGraphic - FontInfo - - Font - Helvetica - Size - 49 - - ID - 5 - Shape - Rectangle - Style - - stroke - - Width - 2 - - - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf340 -\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc - -\f0\fs100 \cf0 f} - - - - Bounds - {{243, 144}, {72, 72}} - Class - ShapedGraphic - FontInfo - - Font - Helvetica - Size - 49 - - ID - 4 - Shape - Rectangle - Style - - stroke - - Width - 2 - - - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf340 -\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc - -\f0\fs100 \cf0 f} - - - - Bounds - {{144, 144}, {72, 72}} - Class - ShapedGraphic - FontInfo - - Font - Helvetica - Size - 49 - - ID - 3 - Shape - Rectangle - Style - - stroke - - Width - 2 - - - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf340 -\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc - -\f0\fs100 \cf0 f} - - - - GridInfo - - ShowsGrid - YES - SnapsToGrid - YES - - GuidesLocked - NO - GuidesVisible - YES - HPages - 1 - ImageCounter - 1 - KeepToScale - - Layers - - - Lock - NO - Name - Layer 1 - Print - YES - View - YES - - - LayoutInfo - - Animate - NO - circoMinDist - 18 - circoSeparation - 0.0 - layoutEngine - dot - neatoSeparation - 0.0 - twopiSeparation - 0.0 - - LinksVisible - NO - MagnetsVisible - NO - MasterSheets - - ModificationDate - 2012-10-30 15:36:12 +0000 - Modifier - Jonathan Bachrach - NotesVisible - NO - Orientation - 2 - OriginVisible - NO - PageBreaks - YES - PrintInfo - - NSBottomMargin - - float - 41 - - NSHorizonalPagination - - coded - BAtzdHJlYW10eXBlZIHoA4QBQISEhAhOU051bWJlcgCEhAdOU1ZhbHVlAISECE5TT2JqZWN0AIWEASqEhAFxlwCG - - NSLeftMargin - - float - 18 - - NSPaperSize - - size - {612, 792} - - NSPrintReverseOrientation - - int - 0 - - NSRightMargin - - float - 18 - - NSTopMargin - - float - 18 - - - PrintOnePage - - ReadOnly - NO - RowAlign - 1 - RowSpacing - 36 - SheetTitle - Canvas 1 - SmartAlignmentGuidesActive - YES - SmartDistanceGuidesActive - YES - UniqueID - 1 - UseEntirePage - - VPages - 1 - WindowInfo - - CurrentSheet - 0 - ExpandedCanvases - - - name - Canvas 1 - - - Frame - {{48, 116}, {710, 874}} - ListView - - OutlineWidth - 142 - RightSidebar - - ShowRuler - - Sidebar - - SidebarWidth - 120 - VisibleRegion - {{0, -1}, {575, 735}} - Zoom - 1 - ZoomValues - - - Canvas 1 - 1 - 1 - - - - - diff --git a/doc/bootcamp/figs/chain.pdf b/doc/bootcamp/figs/chain.pdf deleted file mode 100644 index f9a35a2f..00000000 Binary files a/doc/bootcamp/figs/chain.pdf and /dev/null differ diff --git a/doc/bootcamp/figs/chisel-workflow.graffle b/doc/bootcamp/figs/chisel-workflow.graffle deleted file mode 100644 index 7c9c5c07..00000000 Binary files a/doc/bootcamp/figs/chisel-workflow.graffle and /dev/null differ diff --git a/doc/bootcamp/figs/chisel-workflow.pdf b/doc/bootcamp/figs/chisel-workflow.pdf deleted file mode 100644 index d35e7982..00000000 Binary files a/doc/bootcamp/figs/chisel-workflow.pdf and /dev/null differ diff --git a/doc/bootcamp/figs/condupdates.graffle b/doc/bootcamp/figs/condupdates.graffle deleted file mode 100644 index 71d93992..00000000 --- a/doc/bootcamp/figs/condupdates.graffle +++ /dev/null @@ -1,2822 +0,0 @@ - - - - - ActiveLayerIndex - 0 - ApplicationVersion - - com.omnigroup.OmniGrafflePro - 138.33.0.157554 - - AutoAdjust - - BackgroundGraphic - - Bounds - {{0, 0}, {576, 733}} - Class - SolidGraphic - ID - 2 - Style - - shadow - - Draws - NO - - stroke - - Draws - NO - - - - CanvasOrigin - {0, 0} - ColumnAlign - 1 - ColumnSpacing - 36 - CreationDate - 2011-09-12 23:56:23 -0700 - Creator - Krste Asanovic - DisplayScale - 1 0/72 in = 1.0000 in - GraphDocumentVersion - 8 - GraphicsList - - - Bounds - {{302, 209}, {100, 22}} - Class - ShapedGraphic - FitText - YES - Flow - Resize - FontInfo - - Font - CourierNewPS-BoldMT - Size - 18 - - ID - 155 - Shape - Rectangle - Style - - fill - - Draws - NO - - shadow - - Draws - NO - - stroke - - Draws - NO - - - Text - - Pad - 0 - Text - {\rtf1\ansi\ansicpg1252\cocoartf1038\cocoasubrtf360 -{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural - -\f0\fs36 \cf0 Initial values} - VerticalPad - 0 - - Wrap - NO - - - Bounds - {{394, 237}, {11, 21}} - Class - ShapedGraphic - FitText - YES - Flow - Resize - FontInfo - - Font - CourierNewPS-BoldMT - Size - 18 - - ID - 296 - Shape - Rectangle - Style - - fill - - Draws - NO - - shadow - - Draws - NO - - stroke - - Draws - NO - - - Text - - Pad - 0 - Text - {\rtf1\ansi\ansicpg1252\cocoartf1038\cocoasubrtf360 -{\fonttbl\f0\fmodern\fcharset0 CourierNewPS-BoldMT;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural - -\f0\b\fs36 \cf0 0} - VerticalPad - 0 - - VFlip - YES - Wrap - NO - - - Bounds - {{313, 237}, {11, 21}} - Class - ShapedGraphic - FitText - YES - Flow - Resize - FontInfo - - Font - CourierNewPS-BoldMT - Size - 18 - - ID - 295 - Shape - Rectangle - Style - - fill - - Draws - NO - - shadow - - Draws - NO - - stroke - - Draws - NO - - - Text - - Pad - 0 - Text - {\rtf1\ansi\ansicpg1252\cocoartf1038\cocoasubrtf360 -{\fonttbl\f0\fmodern\fcharset0 CourierNewPS-BoldMT;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural - -\f0\b\fs36 \cf0 0} - VerticalPad - 0 - - VFlip - YES - Wrap - NO - - - Class - LineGraphic - FontInfo - - Font - CourierNewPS-BoldMT - Size - 18 - - ID - 294 - Points - - {432, 318} - {432, 369} - {396, 369} - - Style - - stroke - - HeadArrow - 0 - TailArrow - 0 - Width - 2 - - - Tail - - ID - 290 - Info - 1 - - - - Class - LineGraphic - FontInfo - - Font - CourierNewPS-BoldMT - Size - 18 - - Head - - ID - 274 - Info - 1 - - ID - 293 - Points - - {324, 381} - {324, 387} - {315, 387} - - Style - - stroke - - HeadArrow - 0 - TailArrow - 0 - Width - 2 - - - Tail - - ID - 288 - Info - 1 - - - - Class - Group - Graphics - - - Bounds - {{387, 286}, {11, 21}} - Class - ShapedGraphic - FitText - YES - Flow - Resize - FontInfo - - Font - CourierNewPS-BoldMT - Size - 18 - - ID - 278 - Shape - Rectangle - Style - - fill - - Draws - NO - - shadow - - Draws - NO - - stroke - - Draws - NO - - - Text - - Pad - 0 - Text - {\rtf1\ansi\ansicpg1252\cocoartf1038\cocoasubrtf360 -{\fonttbl\f0\fmodern\fcharset0 CourierNewPS-BoldMT;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural - -\f0\b\fs36 \cf0 f} - VerticalPad - 0 - - VFlip - YES - Wrap - NO - - - Bounds - {{459, 286}, {11, 21}} - Class - ShapedGraphic - FitText - YES - Flow - Resize - FontInfo - - Font - CourierNewPS-BoldMT - Size - 18 - - ID - 279 - Shape - Rectangle - Style - - fill - - Draws - NO - - shadow - - Draws - NO - - stroke - - Draws - NO - - - Text - - Pad - 0 - Text - {\rtf1\ansi\ansicpg1252\cocoartf1038\cocoasubrtf360 -{\fonttbl\f0\fmodern\fcharset0 CourierNewPS-BoldMT;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural - -\f0\b\fs36 \cf0 t} - VerticalPad - 0 - - VFlip - YES - Wrap - NO - - - Class - LineGraphic - FontInfo - - Font - CourierNewPS-BoldMT - Size - 18 - - ID - 280 - Points - - {468, 282} - {468, 255} - - Style - - stroke - - HeadArrow - 0 - TailArrow - 0 - Width - 2 - - - - - Class - LineGraphic - FontInfo - - Font - CourierNewPS-BoldMT - Size - 18 - - ID - 281 - Points - - {396, 282} - {396, 261} - - Style - - stroke - - HeadArrow - 0 - TailArrow - 0 - Width - 2 - - - - - Bounds - {{462, 234}, {22, 21}} - Class - ShapedGraphic - FitText - YES - Flow - Resize - FontInfo - - Font - CourierNewPS-BoldMT - Size - 18 - - ID - 282 - Shape - Rectangle - Style - - fill - - Draws - NO - - shadow - - Draws - NO - - stroke - - Draws - NO - - - Text - - Pad - 0 - Text - {\rtf1\ansi\ansicpg1252\cocoartf1038\cocoasubrtf360 -{\fonttbl\f0\fmodern\fcharset0 CourierNewPS-BoldMT;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural - -\f0\b\fs36 \cf0 e1} - VerticalPad - 0 - - VFlip - YES - Wrap - NO - - - Bounds - {{257, 286}, {22, 21}} - Class - ShapedGraphic - FitText - YES - Flow - Resize - FontInfo - - Font - CourierNewPS-BoldMT - Size - 18 - - ID - 283 - Shape - Rectangle - Style - - fill - - Draws - NO - - shadow - - Draws - NO - - stroke - - Draws - NO - - - Text - - Pad - 0 - Text - {\rtf1\ansi\ansicpg1252\cocoartf1038\cocoasubrtf360 -{\fonttbl\f0\fmodern\fcharset0 CourierNewPS-BoldMT;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural - -\f0\b\fs36 \cf0 c1} - VerticalPad - 0 - - VFlip - YES - Wrap - NO - - - Bounds - {{330.639, 295.502}, {8.99658, 8.99658}} - Class - ShapedGraphic - FontInfo - - Font - CourierNewPS-BoldMT - Size - 18 - - ID - 284 - Line - - ID - 292 - Position - 0.4762515127658844 - RotationType - 0 - - Shape - Circle - Style - - fill - - Color - - b - 0 - g - 0 - r - 0 - - - shadow - - Draws - NO - - stroke - - Width - 2 - - - - - Class - LineGraphic - FontInfo - - Font - CourierNewPS-BoldMT - Size - 18 - - ID - 285 - Points - - {432, 380} - {432, 381} - - Style - - stroke - - HeadArrow - 0 - HeadScale - 1.5000001192092896 - LineType - 1 - TailArrow - 0 - Width - 2 - - - - - Class - Group - Graphics - - - AllowLabelDrop - - Class - LineGraphic - FontInfo - - Font - CourierNewPS-BoldMT - Size - 18 - - Head - - ID - 289 - - ID - 287 - Points - - {333, 300} - {333.154, 320.917} - - Style - - stroke - - Cap - 0 - HeadArrow - 0 - Join - 0 - LineType - 1 - TailArrow - 0 - Width - 2 - - - - - AllowLabelDrop - - Class - LineGraphic - FontInfo - - Font - CourierNewPS-BoldMT - Size - 18 - - ID - 288 - Points - - {324, 363} - {324, 381} - - Style - - stroke - - Cap - 0 - HeadArrow - 0 - Join - 0 - LineType - 1 - TailArrow - 0 - TailScale - 1.8571430444717407 - Width - 2 - - - Tail - - ID - 289 - - - - AllowConnections - NO - Bounds - {{301.5, 322.5}, {45, 36}} - Class - ShapedGraphic - FontInfo - - Font - CourierNewPS-BoldMT - Size - 18 - - ID - 289 - Magnets - - {1, 0} - {-0.460092, -0.26062} - {-0.475541, 0.277852} - - Rotation - 90 - Shape - OrGate - Style - - shadow - - Draws - NO - - stroke - - Width - 2 - - - Text - - VerticalPad - 0 - - VFlip - YES - - - ID - 286 - Rotation - 90 - VFlip - YES - - - Bounds - {{360, 282}, {144, 36}} - Class - ShapedGraphic - FontInfo - - Font - CourierNewPS-BoldMT - Size - 18 - - ID - 290 - Magnets - - {0, 1} - {0, -1} - - Shape - Trapazoid - Style - - shadow - - Draws - NO - - stroke - - Width - 2 - - - - - Class - LineGraphic - FontInfo - - Font - CourierNewPS-BoldMT - Size - 18 - - ID - 291 - Points - - {315, 327.101} - {315, 261} - - Style - - stroke - - HeadArrow - 0 - TailArrow - 0 - Width - 2 - - - - - AllowConnections - NO - AllowLabelDrop - - AllowToConnect - - Class - LineGraphic - FontInfo - - Font - CourierNewPS-BoldMT - Size - 18 - - ID - 292 - Points - - {378, 300} - {333, 300} - {288, 300} - - Style - - stroke - - HeadArrow - 0 - TailArrow - 0 - Width - 2 - - - - - ID - 277 - VFlip - YES - - - Bounds - {{389, 507}, {11, 21}} - Class - ShapedGraphic - FitText - YES - Flow - Resize - FontInfo - - Font - CourierNewPS-BoldMT - Size - 18 - - ID - 276 - Shape - Rectangle - Style - - fill - - Draws - NO - - shadow - - Draws - NO - - stroke - - Draws - NO - - - Text - - Pad - 0 - Text - {\rtf1\ansi\ansicpg1252\cocoartf1038\cocoasubrtf360 -{\fonttbl\f0\fmodern\fcharset0 CourierNewPS-BoldMT;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural - -\f0\b\fs36 \cf0 r} - VerticalPad - 0 - - VFlip - YES - Wrap - NO - - - Bounds - {{401, 471}, {22, 21}} - Class - ShapedGraphic - FitText - YES - Flow - Resize - FontInfo - - Font - CourierNewPS-BoldMT - Size - 18 - - ID - 259 - Shape - Rectangle - Style - - fill - - Draws - NO - - shadow - - Draws - NO - - stroke - - Draws - NO - - - Text - - Pad - 0 - Text - {\rtf1\ansi\ansicpg1252\cocoartf1038\cocoasubrtf360 -{\fonttbl\f0\fmodern\fcharset0 CourierNewPS-BoldMT;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural - -\f0\b\fs36 \cf0 in} - VerticalPad - 0 - - VFlip - YES - Wrap - NO - - - Bounds - {{252, 471}, {65, 21}} - Class - ShapedGraphic - FitText - YES - Flow - Resize - FontInfo - - Font - CourierNewPS-BoldMT - Size - 18 - - ID - 260 - Shape - Rectangle - Style - - fill - - Draws - NO - - shadow - - Draws - NO - - stroke - - Draws - NO - - - Text - - Pad - 0 - Text - {\rtf1\ansi\ansicpg1252\cocoartf1038\cocoasubrtf360 -{\fonttbl\f0\fmodern\fcharset0 CourierNewPS-BoldMT;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural - -\f0\b\fs36 \cf0 enable} - VerticalPad - 0 - - VFlip - YES - Wrap - NO - - - Bounds - {{387, 400}, {11, 21}} - Class - ShapedGraphic - FitText - YES - Flow - Resize - FontInfo - - Font - CourierNewPS-BoldMT - Size - 18 - - ID - 261 - Shape - Rectangle - Style - - fill - - Draws - NO - - shadow - - Draws - NO - - stroke - - Draws - NO - - - Text - - Pad - 0 - Text - {\rtf1\ansi\ansicpg1252\cocoartf1038\cocoasubrtf360 -{\fonttbl\f0\fmodern\fcharset0 CourierNewPS-BoldMT;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural - -\f0\b\fs36 \cf0 f} - VerticalPad - 0 - - VFlip - YES - Wrap - NO - - - Bounds - {{459, 400}, {11, 21}} - Class - ShapedGraphic - FitText - YES - Flow - Resize - FontInfo - - Font - CourierNewPS-BoldMT - Size - 18 - - ID - 262 - Shape - Rectangle - Style - - fill - - Draws - NO - - shadow - - Draws - NO - - stroke - - Draws - NO - - - Text - - Pad - 0 - Text - {\rtf1\ansi\ansicpg1252\cocoartf1038\cocoasubrtf360 -{\fonttbl\f0\fmodern\fcharset0 CourierNewPS-BoldMT;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural - -\f0\b\fs36 \cf0 t} - VerticalPad - 0 - - VFlip - YES - Wrap - NO - - - Class - LineGraphic - FontInfo - - Font - CourierNewPS-BoldMT - Size - 18 - - ID - 263 - Points - - {468, 396} - {468, 369} - - Style - - stroke - - HeadArrow - 0 - TailArrow - 0 - Width - 2 - - - - - Class - LineGraphic - FontInfo - - Font - CourierNewPS-BoldMT - Size - 18 - - ID - 264 - Points - - {396, 396} - {396, 369} - - Style - - stroke - - HeadArrow - 0 - TailArrow - 0 - Width - 2 - - - - - Bounds - {{462, 348}, {22, 21}} - Class - ShapedGraphic - FitText - YES - Flow - Resize - FontInfo - - Font - CourierNewPS-BoldMT - Size - 18 - - ID - 265 - Shape - Rectangle - Style - - fill - - Draws - NO - - shadow - - Draws - NO - - stroke - - Draws - NO - - - Text - - Pad - 0 - Text - {\rtf1\ansi\ansicpg1252\cocoartf1038\cocoasubrtf360 -{\fonttbl\f0\fmodern\fcharset0 CourierNewPS-BoldMT;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural - -\f0\b\fs36 \cf0 e2} - VerticalPad - 0 - - VFlip - YES - Wrap - NO - - - Bounds - {{257, 400}, {22, 21}} - Class - ShapedGraphic - FitText - YES - Flow - Resize - FontInfo - - Font - CourierNewPS-BoldMT - Size - 18 - - ID - 266 - Shape - Rectangle - Style - - fill - - Draws - NO - - shadow - - Draws - NO - - stroke - - Draws - NO - - - Text - - Pad - 0 - Text - {\rtf1\ansi\ansicpg1252\cocoartf1038\cocoasubrtf360 -{\fonttbl\f0\fmodern\fcharset0 CourierNewPS-BoldMT;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural - -\f0\b\fs36 \cf0 c2} - VerticalPad - 0 - - VFlip - YES - Wrap - NO - - - Bounds - {{330.639, 409.502}, {8.99658, 8.99658}} - Class - ShapedGraphic - FontInfo - - Font - CourierNewPS-BoldMT - Size - 18 - - ID - 267 - Line - - ID - 275 - Position - 0.4762515127658844 - RotationType - 0 - - Shape - Circle - Style - - fill - - Color - - b - 0 - g - 0 - r - 0 - - - shadow - - Draws - NO - - stroke - - Width - 2 - - - - - Class - LineGraphic - FontInfo - - Font - CourierNewPS-BoldMT - Size - 18 - - ID - 268 - Points - - {432, 433} - {432, 495} - - Style - - stroke - - HeadArrow - FilledArrow - HeadScale - 1.5000001192092896 - LineType - 1 - TailArrow - 0 - Width - 2 - - - Tail - - ID - 273 - Info - 1 - - - - Class - Group - Graphics - - - AllowLabelDrop - - Class - LineGraphic - FontInfo - - Font - CourierNewPS-BoldMT - Size - 18 - - Head - - ID - 272 - - ID - 270 - Points - - {333, 414} - {333.154, 434.917} - - Style - - stroke - - Cap - 0 - HeadArrow - 0 - Join - 0 - LineType - 1 - TailArrow - 0 - Width - 2 - - - - - AllowLabelDrop - - Class - LineGraphic - FontInfo - - Font - CourierNewPS-BoldMT - Size - 18 - - ID - 271 - Points - - {324, 477} - {324, 495} - - Style - - stroke - - Cap - 0 - HeadArrow - FilledArrow - Join - 0 - LineType - 1 - TailArrow - 0 - TailScale - 1.8571430444717407 - Width - 2 - - - Tail - - ID - 272 - - - - AllowConnections - NO - Bounds - {{301.5, 436.5}, {45, 36}} - Class - ShapedGraphic - FontInfo - - Font - CourierNewPS-BoldMT - Size - 18 - - ID - 272 - Magnets - - {1, 0} - {-0.460092, -0.26062} - {-0.475541, 0.277852} - - Rotation - 90 - Shape - OrGate - Style - - shadow - - Draws - NO - - stroke - - Width - 2 - - - Text - - VerticalPad - 0 - - VFlip - YES - - - ID - 269 - Rotation - 90 - VFlip - YES - - - Bounds - {{360, 396}, {144, 36}} - Class - ShapedGraphic - FontInfo - - Font - CourierNewPS-BoldMT - Size - 18 - - ID - 273 - Magnets - - {0, 1} - {0, -1} - - Shape - Trapazoid - Style - - shadow - - Draws - NO - - stroke - - Width - 2 - - - - - Class - LineGraphic - FontInfo - - Font - CourierNewPS-BoldMT - Size - 18 - - ID - 274 - Points - - {315, 441} - {315, 387} - - Style - - stroke - - HeadArrow - 0 - TailArrow - 0 - Width - 2 - - - - - AllowConnections - NO - AllowLabelDrop - - AllowToConnect - - Class - LineGraphic - FontInfo - - Font - CourierNewPS-BoldMT - Size - 18 - - ID - 275 - Points - - {378, 414} - {333, 414} - {288, 414} - - Style - - stroke - - HeadArrow - 0 - TailArrow - 0 - Width - 2 - - - - - Bounds - {{351, 534}, {33, 21}} - Class - ShapedGraphic - FitText - YES - Flow - Resize - FontInfo - - Font - CourierNewPS-BoldMT - Size - 18 - - ID - 257 - Shape - Rectangle - Style - - fill - - Draws - NO - - shadow - - Draws - NO - - stroke - - Draws - NO - - - Text - - Pad - 0 - Text - {\rtf1\ansi\ansicpg1252\cocoartf1038\cocoasubrtf360 -{\fonttbl\f0\fmodern\fcharset0 CourierNewPS-BoldMT;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural - -\f0\b\fs36 \cf0 out} - VerticalPad - 0 - - VFlip - YES - Wrap - NO - - - Class - LineGraphic - FontInfo - - Font - CourierNewPS-BoldMT - Size - 18 - - ID - 256 - Points - - {396, 531} - {396, 558} - - Style - - stroke - - HeadArrow - FilledArrow - HeadScale - 1.5000001192092896 - LineType - 1 - TailArrow - 0 - Width - 2 - - - - - Bounds - {{210, 507}, {55, 21}} - Class - ShapedGraphic - FitText - YES - Flow - Resize - FontInfo - - Font - CourierNewPS-BoldMT - Size - 18 - - ID - 255 - Shape - Rectangle - Style - - fill - - Draws - NO - - shadow - - Draws - NO - - stroke - - Draws - NO - - - Text - - Pad - 0 - Text - {\rtf1\ansi\ansicpg1252\cocoartf1038\cocoasubrtf360 -{\fonttbl\f0\fmodern\fcharset0 CourierNewPS-BoldMT;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural - -\f0\b\fs36 \cf0 clock} - VerticalPad - 0 - - VFlip - YES - Wrap - NO - - - Class - Group - Graphics - - - Class - LineGraphic - FontInfo - - Font - CourierNewPS-BoldMT - Size - 18 - - ID - 252 - Points - - {288, 513} - {270, 513} - - Style - - stroke - - HeadArrow - 0 - TailArrow - 0 - Width - 2 - - - - - Class - LineGraphic - FontInfo - - Font - CourierNewPS-BoldMT - Size - 18 - - ID - 253 - Points - - {288, 495} - {306, 513} - {288, 531} - - Style - - stroke - - HeadArrow - 0 - TailArrow - 0 - Width - 2 - - - - - AllowConnections - NO - Bounds - {{288, 495}, {216, 36}} - Class - ShapedGraphic - FontInfo - - Font - CourierNewPS-BoldMT - Size - 18 - - ID - 254 - Shape - Rectangle - Style - - shadow - - Draws - NO - - stroke - - Width - 2 - - - VFlip - YES - - - ID - 251 - VFlip - YES - - - Bounds - {{100.5, 423}, {141, 40}} - Class - ShapedGraphic - FitText - YES - Flow - Resize - FontInfo - - Font - CourierNewPS-BoldMT - Size - 18 - - ID - 88 - Shape - Rectangle - Style - - fill - - Draws - NO - - shadow - - Draws - NO - - stroke - - Draws - NO - - - Text - - Align - 0 - Pad - 0 - Text - {\rtf1\ansi\ansicpg1252\cocoartf1038\cocoasubrtf360 -{\fonttbl\f0\fmodern\fcharset0 CourierNewPS-BoldMT;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural\pardirnatural - -\f0\b\fs36 \cf0 when (c2)\ - \{ r := e2 \}} - VerticalPad - 0 - - Wrap - NO - - - Bounds - {{100.5, 318}, {141, 40}} - Class - ShapedGraphic - FitText - YES - Flow - Resize - FontInfo - - Font - CourierNewPS-BoldMT - Size - 18 - - ID - 68 - Shape - Rectangle - Style - - fill - - Draws - NO - - shadow - - Draws - NO - - stroke - - Draws - NO - - - Text - - Align - 0 - Pad - 0 - Text - {\rtf1\ansi\ansicpg1252\cocoartf1038\cocoasubrtf360 -{\fonttbl\f0\fmodern\fcharset0 CourierNewPS-BoldMT;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural\pardirnatural - -\f0\b\fs36 \cf0 when (c1)\ - \{ r := e1 \}} - VerticalPad - 0 - - Wrap - NO - - - GridInfo - - ShowsGrid - YES - SnapsToGrid - YES - - GuidesLocked - NO - GuidesVisible - YES - HPages - 1 - ImageCounter - 1 - KeepToScale - - Layers - - - Lock - NO - Name - Layer 1 - Print - YES - View - YES - - - LayoutInfo - - Animate - NO - circoMinDist - 18 - circoSeparation - 0.0 - layoutEngine - dot - neatoSeparation - 0.0 - twopiSeparation - 0.0 - - LinksVisible - NO - MagnetsVisible - NO - MasterSheets - - ModificationDate - 2012-05-30 10:27:26 -0700 - Modifier - Jonathan Bachrach - NotesVisible - NO - Orientation - 2 - OriginVisible - NO - PageBreaks - YES - PrintInfo - - NSBottomMargin - - float - 41 - - NSLeftMargin - - float - 18 - - NSPaperSize - - coded - BAtzdHJlYW10eXBlZIHoA4QBQISEhAdOU1ZhbHVlAISECE5TT2JqZWN0AIWEASqEhAx7X05TU2l6ZT1mZn2WgWQCgRgDhg== - - NSRightMargin - - float - 18 - - NSTopMargin - - float - 18 - - - PrintOnePage - - QuickLookPreview - - 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 - 4/NDyqTL1e+Uv+qLny/xZdPpC5APfB3F4n1dfLpUhxvv6pu7utDl8J+nrz5XGZAlAquL - 50v9m968zt9C3/wDhSFj7AplbmRzdHJlYW0KZW5kb2JqCjYgMCBvYmoKMTcyMwplbmRv - YmoKMyAwIG9iago8PCAvVHlwZSAvUGFnZSAvUGFyZW50IDQgMCBSIC9SZXNvdXJjZXMg - NyAwIFIgL0NvbnRlbnRzIDUgMCBSIC9NZWRpYUJveCBbMCAwIDU3NiA3MzNdCj4+CmVu - ZG9iago3IDAgb2JqCjw8IC9Qcm9jU2V0IFsgL1BERiAvVGV4dCBdIC9Db2xvclNwYWNl - IDw8IC9DczIgOSAwIFIgL0NzMSA4IDAgUiA+PiAvRm9udCA8PAovRjIuMCAxMSAwIFIg - L0YxLjAgMTAgMCBSID4+ID4+CmVuZG9iagoxMiAwIG9iago8PCAvTGVuZ3RoIDEzIDAg - UiAvTiAxIC9BbHRlcm5hdGUgL0RldmljZUdyYXkgL0ZpbHRlciAvRmxhdGVEZWNvZGUg - Pj4Kc3RyZWFtCngBhVJPSBRRHP7NNhKEiEGFeIh3CgmVKaysoNp2dVmVbVuV0qIYZ9+6 - o7Mz05vZNcWTBF2iPHUPomN07NChm5eiwKxL1yCpIAg8dej7zezqKIRveTvf+/39ft97 - RG2dpu87KUFUc0OVK6Wnbk5Ni4MfKUUd1E5YphX46WJxjLHruZK/u9fWZ9LYst7HtXb7 - 9j21lWVgIeottrcQ+iGRZgAfmZ8oZYCzwB2Wr9g+ATxYDqwa8COiAw+auTDT0Zx0pbIt - kVPmoigqr2I7Sa77+bnGvou1iYP+XI9m1o69s+qq0UzUtPdEobwPrkQZz19U9mw1FKcN - 45xIQxop8q7V3ytMxxGRKxBKBlI1ZLmfak6ddeB1GLtdupPj+PYQpT7JYKiJtemymR2F - fQB2KsvsEPAF6PGyYg/ngXth/1tRw5PAJ2E/ZId51q0f9heuU+B7hD014M4UrsXx2oof - Xi0BQ/dUI2iMc03E09c5c6SI7zHUGZj3RjmmCzF3lqoTN4A7YR9ZqmYKsV37ruol7nsC - d9PjO9GbOQtcoBxJcrEV2RTQPAlYFH2LsEkOPD7OHlXgd6iYwBy5idzNKPce1REbZ6NS - gVZ6jVfGT+O58cX4ZWwYz4B+rHbXe3z/6eMVdde2Pjz5jXrcOa69nRtVYVZxZQvd/8cy - hI/ZJzmmwdOhWVhr2HbkD5rMTLAMKMR/BT6X+pITVdzV7u24RRLMUD4sbCW6S1RuKdTq - PYNKrBwr2AB2cJLELFocuFNrujl4d9giem35TVey64b++vZ6+9ryHm3KqCkoE82zRGaU - sVuj5N142/1mkRGfODq+572KWsn+SUUQP4U5WiryFFX0VlDWxG9nDn4btn5cP6Xn9UH9 - PAk9rZ/Rr+ijEb4MdEnPwnNRH6NJ8LBpIeISoIqDM9ROVGONA+Ip8fK0W2SR/Q9AGf1m - CmVuZHN0cmVhbQplbmRvYmoKMTMgMCBvYmoKNzA0CmVuZG9iago5IDAgb2JqClsgL0lD - Q0Jhc2VkIDEyIDAgUiBdCmVuZG9iagoxNCAwIG9iago8PCAvTGVuZ3RoIDE1IDAgUiAv - TiAzIC9BbHRlcm5hdGUgL0RldmljZVJHQiAvRmlsdGVyIC9GbGF0ZURlY29kZSA+Pgpz - dHJlYW0KeAGFVM9rE0EU/jZuqdAiCFprDrJ4kCJJWatoRdQ2/RFiawzbH7ZFkGQzSdZu - NuvuJrWliOTi0SreRe2hB/+AHnrwZC9KhVpFKN6rKGKhFy3xzW5MtqXqwM5+8943731v - dt8ADXLSNPWABOQNx1KiEWlsfEJq/IgAjqIJQTQlVdvsTiQGQYNz+Xvn2HoPgVtWw3v7 - d7J3rZrStpoHhP1A4Eea2Sqw7xdxClkSAog836Epx3QI3+PY8uyPOU55eMG1Dys9xFki - fEA1Lc5/TbhTzSXTQINIOJT1cVI+nNeLlNcdB2luZsbIEL1PkKa7zO6rYqGcTvYOkL2d - 9H5Os94+wiHCCxmtP0a4jZ71jNU/4mHhpObEhj0cGDX0+GAVtxqp+DXCFF8QTSeiVHHZ - Lg3xmK79VvJKgnCQOMpkYYBzWkhP10xu+LqHBX0m1xOv4ndWUeF5jxNn3tTd70XaAq8w - Dh0MGgyaDUhQEEUEYZiwUECGPBoxNLJyPyOrBhuTezJ1JGq7dGJEsUF7Ntw9t1Gk3Tz+ - KCJxlEO1CJL8Qf4qr8lP5Xn5y1yw2Fb3lK2bmrry4DvF5Zm5Gh7X08jjc01efJXUdpNX - R5aseXq8muwaP+xXlzHmgjWPxHOw+/EtX5XMlymMFMXjVfPqS4R1WjE3359sfzs94i7P - LrXWc62JizdWm5dn/WpI++6qvJPmVflPXvXx/GfNxGPiKTEmdornIYmXxS7xkthLqwvi - YG3HCJ2VhinSbZH6JNVgYJq89S9dP1t4vUZ/DPVRlBnM0lSJ93/CKmQ0nbkOb/qP28f8 - F+T3iuefKAIvbODImbptU3HvEKFlpW5zrgIXv9F98LZua6N+OPwEWDyrFq1SNZ8gvAEc - dod6HugpmNOWls05Uocsn5O66cpiUsxQ20NSUtcl12VLFrOZVWLpdtiZ0x1uHKE5QvfE - p0plk/qv8RGw/bBS+fmsUtl+ThrWgZf6b8C8/UUKZW5kc3RyZWFtCmVuZG9iagoxNSAw - IG9iago3MzcKZW5kb2JqCjggMCBvYmoKWyAvSUNDQmFzZWQgMTQgMCBSIF0KZW5kb2Jq - CjQgMCBvYmoKPDwgL1R5cGUgL1BhZ2VzIC9NZWRpYUJveCBbMCAwIDYxMiA3OTJdIC9D - b3VudCAxIC9LaWRzIFsgMyAwIFIgXSA+PgplbmRvYmoKMTYgMCBvYmoKPDwgL1R5cGUg - L0NhdGFsb2cgL091dGxpbmVzIDIgMCBSIC9QYWdlcyA0IDAgUiA+PgplbmRvYmoKMiAw - IG9iago8PCAvTGFzdCAxNyAwIFIgL0ZpcnN0IDE4IDAgUiA+PgplbmRvYmoKMTggMCBv - YmoKPDwgL1BhcmVudCAxOSAwIFIgL0NvdW50IDAgL0Rlc3QgWyAzIDAgUiAvWFlaIDAg - NzMzIDAgXSAvVGl0bGUgKENhbnZhcyAxKQo+PgplbmRvYmoKMTkgMCBvYmoKPDwgPj4K - ZW5kb2JqCjE3IDAgb2JqCjw8IC9QYXJlbnQgMTkgMCBSIC9Db3VudCAwIC9EZXN0IFsg - MyAwIFIgL1hZWiAwIDczMyAwIF0gL1RpdGxlIChDYW52YXMgMSkKPj4KZW5kb2JqCjIw - IDAgb2JqCjw8IC9MZW5ndGggMjEgMCBSIC9MZW5ndGgxIDc3OTYgL0ZpbHRlciAvRmxh - dGVEZWNvZGUgPj4Kc3RyZWFtCngBvVkLVJNXtt7nfyaERxIS8iAhCT9JCG98IBGUiAmi - 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 - 1GaTw1zukLdmUuP++n9l4q+988y0jPl7ajYxH5rpMxzfidivuVzAuOLLKSVnCQPLoY1p - Y5cLP+Me41+G/YwCT2mZADeHf5TbxJ/jzvOK2emr00VFmCj7HcvXIbT4t0A40jmAgdjO - hckjx1i2Q8sQBv8recSXIggdWpyJFziWEJ5hBRbwzC5GQY11mDlBaLTb0E8OCyZT1VVj - 5dCnnw6ZZPsYAYOZoVjrpY9krVeszMlUV12uFKNF5tx5a31OxqNlWQ48WkHA58A44QzH - HubhO7le75DXe5NkXlRn4i8/j4b8hvsSlWQixuRPSArJPDu88vTwGi73+m627do7iNDI - O12kFc+i/9kVi40snqb78Uy7Au7AE/WF+G5ZB0G5M8GT9uh7poD/PYK/tmZRzYLM8taV - 3a1d7UubsE+USzsXYvJjmo+pBRP9bxNRgqcwvYQJ/2bCU2OA9zBdjoxcSMMYTcB+Ux0D - 4Dg+nfHG/vKabhjffhOfntPe2P+em+qrb6pTnW/sv+amejet/x9hv9JhCmVuZHN0cmVh - bQplbmRvYmoKMjEgMCBvYmoKNDc2NgplbmRvYmoKMjIgMCBvYmoKPDwgL1R5cGUgL0Zv - bnREZXNjcmlwdG9yIC9Bc2NlbnQgNzcwIC9DYXBIZWlnaHQgNjg0IC9EZXNjZW50IC0y - MzAgL0ZsYWdzIDMyCi9Gb250QkJveCBbLTk1MSAtNDgxIDE0NDUgMTEyMl0gL0ZvbnRO - YW1lIC9EU1JXUlUrSGVsdmV0aWNhIC9JdGFsaWNBbmdsZSAwCi9TdGVtViAwIC9NYXhX - aWR0aCAxNTAwIC9YSGVpZ2h0IDUxMyAvRm9udEZpbGUyIDIwIDAgUiA+PgplbmRvYmoK - MjMgMCBvYmoKWyAyNzggMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAg - MCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMAowIDAgMCAwIDAgMCAyNzggMCAw - IDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDU1NiAwIDAg - MCA1NTYKMCAwIDAgMjIyIDAgMCAyMjIgMCA1NTYgMCAwIDAgMCA1MDAgMjc4IDU1NiA1 - MDAgXQplbmRvYmoKMTEgMCBvYmoKPDwgL1R5cGUgL0ZvbnQgL1N1YnR5cGUgL1RydWVU - eXBlIC9CYXNlRm9udCAvRFNSV1JVK0hlbHZldGljYSAvRm9udERlc2NyaXB0b3IKMjIg - MCBSIC9XaWR0aHMgMjMgMCBSIC9GaXJzdENoYXIgMzIgL0xhc3RDaGFyIDExOCAvRW5j - b2RpbmcgL01hY1JvbWFuRW5jb2RpbmcKPj4KZW5kb2JqCjI0IDAgb2JqCjw8IC9MZW5n - dGggMjUgMCBSIC9MZW5ndGgxIDIwMjQwIC9GaWx0ZXIgL0ZsYXRlRGVjb2RlID4+CnN0 - cmVhbQp4Aa18C1xUx/X/zNy7Txa4+4QF2Se7PBbYRQEF0b2ISAQVfEUwEvBB1NQEXzFv - Jc3bpJUkNc/2J2nzbNJkAZOgTStt0jRJa+OvsUlM22D6S/O2mvzUNlF2/9+ZXXw0/T0+ - n/9vlzNnZu7cc2bOnDNz5ty7bN54RTcxkV4iEXXlZcvXE/EJqkAHV27Z7BFF4lhHiD7j - kvWrL0uWXdcRomtfve7qS5LlgjmEFKhrupevSpbJaeCqNahIlmkFcP6ayzZflSwH3gFe - s65nZep6gQ3lqsuWX5XiT/6Esufy5Zd1J9vP+wC4ZH3Pps2p8p3Abes3dqfa0zZC7Jbz - yxmEULTKIV+SWnIT0RBGFBIm7RjJOs2bREaZX9cQwn7y4eLOzNoTeoNekP/R4p46nvlV - 2p6V8Su/nq/5geFXaGsQ7fkF3Kd9cuwBQuT98SsTEc0PzlzhV/knZ2CJu26aTEkYEAFI - IhdFrgXQCegCvAEYBRwF6IkHKW+7A7ALwK9oiFtKkDAgApBIFGknYPRMaQdyuwD9gGMA - DVGl+FBaxkR3XaMUx61xsh6wCyDj1rOlo6JmR+paP7BEMmUNxhJGGgXsABwFyMQjnUa9 - Ip0iPYB+lA4DZFD/Gl3icIq0AHcJOAV8muxD3QHAMYAxMSL9Y2j+womkrlb6CoS+Qi+/ - Iq2A9YBeQAxwGAA5IA1LYxjxVyA8Jlp1Id8H2IfyCPABAG+dBjq8xRhYjpFnAZzOeCve - 4hjAAPZfDU69d+IekUk3i8yJoZraiQfqbNIJjK1PpJlIw4AooAWwA/AsQAs2xwcNJnHf - 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 - BPMdhGXemNLqbqy1j6MkYa4s2AGikPgczMkynKwkWoCd9mXydOJhaTFoDAiTeZy9QT3x - H5ECrDKXY39qJv9Bp5NP8d1Ndo89CG5PaB8H1z3aJ8kJ7Q/wxG8nSnewBo1ZDkPnx1gP - /U7iovhFWNOuJXvkv+JRD1HntC25cPGihQvmt7bMa5odnT6tdmpN9ZTJlRWTJpZHwmWl - JaHiosKCYCDf7/N63K68Cbk5zuwsh91mtZiVzIx0U5rRoNdpNbLEKClp8M/q8sSCXTE5 - 6L/gglJe9i9HxfJzKrpiHlTNOr9NzMPvW45L57VU0fKSf2qpJluqZ1pSxVNLaktLPA1+ - T2z/TL9nmC6d34b8d2b62z2xIyI/V+TloCiko+D14g5PQ/aamZ4Y7fI0xGZtWbO9oWtm - aQkdSDPW++u7jaUlZMCYhmwacrEs//oBmjWdigzLaqgZYESfjjHGcvwzG2JOP24FGSnQ - sHxVrHV+W8PMXK+3vbQkRutX+lfECHekQ6IJqRdsYtr6mE6w8ayNYTjkDs9Aycj2O4cV - sqIrZFrlX7V8WVtMWg4aDTFzCHxnxrKu+SD7bBHE4bLfeu7VXGl7Q/ZaD2+8ffutnlj/ - /LZz7s31cgrt7aCBe1lgVtf2WWB9J6aKZofROd59PpTkoJJHoUDXpZ6YwT/Dv2b7pV2Y - kJztMbLgau9gTo66J3GY5DR4ti9q83tj0Vx/+/KZEwZsZPuCq4ecqsd5/pXSkgHFnJTm - QEZmKmNKPzfTDUknr4mcaM5zzQvOiJPyPvpnx1To0UoPetLmx0Cm8KR7Ctm+cgqkjk87 - xV2xVZiGtTFDfdd2pYbXQ5Q0pgkofs/2EwTT7j/y+fk1y1M12oACS8ZFrhxnFCxGl4/n - YzglFBdzvdDVYyLRx+miXFlasmWY7fevVzxAOEmS1jbc1l4Thsy9Xj6rdwyrZAUKsd75 - bcmyh6zIHSRqGOct1sWvjIxfsS/mV3rHr5y5vcsP9d2NXRMvXcT0wTN/mYrD2rCmJkYd - /83l7uT15oX+ZgRhPA3bu1Kq2rzovFLyOhco5IZrqVzMWt8m5TKu2sixXElchSYuW3qm - CQptppgcwJ9WaPKqYZ0eqihqqGdWTOm6IJm2G73elKH8TzcNJ47xuwQ6e1tqGLGaUKqj - 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 - M5JUM29eDWCsIJXBSlFEPfLjUg92kFwy9Xl9KdGVEjrMjqgOe0apI7PUYU8jTurMyZMt - zglXDycXdK6+JFw7l6vwSa7IkFtKW718mdVK55Vk1+nvcY2V1vH0nDz74bjixrdOKSuD - CpdNQZ/aE+/J90uPIxI5mU5TK4s1NFJGNVWOKn9VtDgaipZMK70s47oMg8Zj99ynf0n7 - mueg9gPtySrsq2fO0uP2aoO9WiPFk32E3lJEi4onV5gsRq7FYZenQjG2Gplq7DUyo7ez - hLaU0JKSIptaCovutihel67I2FtBK7xyWjqUb8lub6eP+vjNBkta1JdTnXVrZJgtVi06 - NSsj6tZ5dBGdpHNOiT6f3IVCc8e4OoY6+A6I+doQjR7hjzQyFbV0aVRRM108sUWhpe1H - Qpbq8IaNR6CbaCIMdgiNeFeH0E5gJTeF7QIPJm/FzdWW6mpztfI5NSODP76UdGyAKnsr - U9tLPjaVlBon1WV8SxxfbKTk0itW3qrJknvu3jmP/o7qPu64pqXnoruqXEXVtvzqOf+m - 7nvTzyfx2LVrrl86JXfikqafzo4UFT176Q1/tpWX1eSnTy3LCWYpduejO+JL+eTSnuxp - BYV5Fm/NRLzz+FliVL5XY8a+Xkz71HINMxiMJul5/Sv6j/RfG2Q3U0zufCUYZh5TON8T - /Cz4WfFp7WlPIj89XzVkRoNC9sjkq8a0ClHKRiZXlX25aqExqCd8AbdYbXZH1rgC8GWc - nImrjNc6XbPTPemFmb0I2ssu4vPKukxjodeY5uYTaiM6RcymqmvVaWM6elhHdYK32RjV - 5ZSQQAbUQbVlEYfHEXG84Rh1HHUkHLpdDuoYb+ZwhlZeJ/QAizpXAO4DhTo2dMwVmyms - 11y9AfM1ZXwtei5dTVMqKO4fBMZuidWo/mo1p6jY49UYvBq3mxYZkHi0Pjct1he6Cdpg - P73hhhvI7EVXq0qwIM0UNBX65YK0gJ+Y0nHwwaY7ftWfz6R85vNr/DjeY+k5cxXaF+qg - WPWoma9sxG4jUJECe2pZmWROZShfBbV2G7bmKrqq+aGWP9DC+IcfLbi/8VhTVJ3tF3oh - LR68oXew/+67H9aY4xXl5fF3D/w6fqK4aKLYna7k6ekHt8Vi12246y6sbBth6XfA0kPk - qDr3kPlN29v5hwo+sXxo+zD/k4JTtlN+o95m8LMqS7d5taXbfknhKZM2zUQtsy1zC9ot - f7Ydyv/M9km+LseZbiIardWZ6zClKwYll+YOU+9uH7mmCBP19W7FW6TDiyVNqoFpHV5f - mnaei0+T4qxc7zrsYq2uAy7myim1CmNeH6Qk6AlGguuDctBZ8rvkJHZsmAtbjm/sCM3F - po2lNzr2gfKBcqSDmxwAppdVzc2OG7iiV9MdUSNPDDzJ5ZOKJYKLuj25w9Dk/pL0Q+GG - jov2rKfqhYNaWUHgDEiPBQpKsDgW59mzy+ZvvevZJ17qnR+50F88rWN7/OTRm3fT/M8W - 3y2t9kdn39Q0PdvSkxv58bevuiNHmTu9eOa0i1be/NEfqdvD/cIZsL9LIe88kk8fUo3D - lmHbC7m/zpWxrx9WZ09wVaxi62y/1r6tfcf2jvMj7ce2j53/yU5o/9Ny2vYP91f+zCpt - o5ZZ1trWZl+ac6n7Ev/32C53n/9p9yP+r51peTqNlGbNd1E9hjtUXFPBsWpy+ip69Qf0 - 7JgeF6jjOYtLzasU8s/MwxLsoqqr18V2uKhrmGarlUS1+KNExcarTqh0E5qJ0O4bBD/6 - oEQ1ZeJHNrKXL5xIbFGv16GTvUqaa5h1DZIr03D0HPLPigrcHOQY/P35FYfTaFpOMP9K - bGxdqs2q+ivd1vVWZlXTMyuszsDsdUk7xdyOfcD9B0yTcCEwyaGQuToMs4XLEDoiECb4 - OZcKb5KPYchWmMTotCj7LQIPFoplHdP9t44NoRBCBSkFoVxB9mApPAjXMCvqLkHiH04c - HATm2gHng8IcvQ6Y2WShIzgkyH4fSaoCPxfYC4JcXXTy2tMveH50x8afzXMVTXEVxl/f - cTJ+iEYPXP/vky4Ie/4jfP/aNfdH6MWtK8ptNSWFEwL11PGbd2hm26Smy+as2tK2ZEkb - ZLoTAr0HK/IkOlf16nKzcgtyJ+fKDwQpy1Qsk4iapprY2YD0+PIJL1g1qgZ+VT7rOdeZ - kq4zlvfZiRHuc/JfpZA0PgsmuaS0LBwpnziJ0H3nNUteZt90tetcs/PVhsaKfHXuQiSV - NUiwNed3F3rziGVV6SSyqrSkRMmOZKvZrdld2b3Z2mxt5iqDga3SG0kockIzTD9VTR5v - xMu8OZVwrDH/S1RPjmK/yhRXVJsp2qPsUp5V9ikyUVqB3lBkBScCSgfGjR568IFSewTz - J/zKD1CA9dcqR6IbUDfGM0e44yk+iO/wmBBWgY0d1Jz0hM568ePrqTjhOcaPoNzu7amm - rJvm88016d9fs4LnV7y2b/FodEqRNbhtxSVzaS2vY/viGeOOE/2S5+bdMuCeUhKeqnNO - K53HKzCzOZjZpzGzU8jnqnPUQLVah7ZAK2HWjCy5SWZlZzv34jX38dNOYVFxqKQ0HImU - /+zcGeLHo+SzCDjf+nEV4Ptq0tvyeb2ec8mQKdxl5s83Um13u2ZPITgCP6lm0hN52GqL - CgvNZsXozObzoehbDHS94VnDYYNkyKkhXl6ZEYn0llN3OS13VresTrpTG0QEgc8DciKU - oEDc0SPHj4iFVTg9OO6LXQzyNeMYzc/5Qu6Tq7LM4nip1X2jfnx/u0e9sf7Sxy6blx2Z - 3vTp7GjEOTc/vGzm2vaWrPJo0ydN0fLseWKPw87WHAxc8NCW+LZMdzU/eE1xK5RuavGE - KtvivefUSWLDw7rbi7loxlxIeNfhJbwYh4UjLX064+uTHZlWA1XT1QyWPIBy/+V8E0nn - FuRgZx8GnTsJ8plHRuO1RtfsMN52a8Gj1r1sCdbOETU9ozqKFyTIBG26yaj5KWpt+G3E - kkF6lczFnWm3e2wRW5dNsjnzlj6SlDcX93E49/yMGt2A1Q9KzgMq3O2w+yu/eU5NCZLF - jlPlpFDkRp6efHS2Gm3SmA8dil87Vne+4kJPGyCbByCbcs2b6sPEeqF1hfUKa691e9Yt - pb8qfS38pvWPWb8vPVT+V+sn5Zk/Dsese7N2l+4N/9L6K/trWXrZ+mDWztJ+6yP2H2c9 - WqrrxrK+g2z37Si/y6pVrKHymvJOsti61NdZrjts/bT8hFUy+OxYEKp83d5bfK/5Pvd9 - 6v97xGjz9/kZXi2NLPR+y3ZL+Wv+VyNvek94DcT7kO0h3/2Rn9j2+vdE3rDp4f0fHmys - 5IeAwaZKbxKJI0H2nLkVtsULKy2ZJKPcTSaU4+RtPWnVWfkuEaqvAO4dal3A8chgc6Wo - ntnCi7PVqoWVPk9jpcdb55npnRdp9XZGduTumLAjb4drhzvNpuL2XNuEbIaf6+RRyiRZ - o9Vh2a3LPtdMiQdrrRcAbSGm5LpLMoDxUyWSB5iQ6MVubHTm5E7Ic+GFYd+4vmRiNc+j - Z583jtdnuWaXIc6hlHnK+stiZcfKNKRstIyVYQSqb0blaBktK4v0OHbB/ZX6HTGgww7Z - 7djheBbOsAxPuFd1BCsdqgFQXFLhUKsrHb3OSofDVsf7yPs13ufx/qKfgxNULhzVZDac - fTY63qUM12wvISoER9SFlfxQphqsNpvVavP7fLwEH8xWXh7xeSPqBB6d4ckFzkpTOXXa - tti2RCQrKffZvP6ySLlxUjKPrIE6I/sof9P7XlJOlxNETtnO3RaLlZ+FsRoZDXy3IIYu - w3osUnxGM51RgY1mgVWjSYkanBN9Pmv5XvY1gmt/V51WD97Idua7/Ksi74cMq5hxldmm - 4uRo20s/JVb2mGq2IEqUo3Vqi40hI8Up9M099E845CNymfwc/yDEw3DKkSMcYI5wRihC - qrDEjpA4VNQqHyonj3xOuPtJzVnV3NsI6W8tC2muV16Wby3jr9LyLGJOk8LI48YNG5Ht - CAmXhh821fR8P7TB54fcCPHequhr9bXYy5Ta9vEoiY0vWLlJ3QVOHk6o8GSgcaoBPm45 - d3S5QXDRcKxmZGRFbSpKNhW5CVz/URAYZXhLoiwwynmpssAoF6bKAqOM055oLzDKBamy - wCjDiRKsBUZZGKUVTmIBnzo/T3wiSd2H672qDw0jvOO2ZGKyociT3jRL1MYTTmYIGGxG - hjDZgjww6t9TDchEfOOlDBxMIz4kGK9VNFQN0AqbikT0Zl0ajrC9UIBCnhTwxMWTPJ5M - 4IlPRVLOE5/qSEcOiY8HF8p54uJJHk8mJIsINefxePMEngR5UsiTAp6Iuf7/SNo3hvhK - zz/cZX2u3AcxCcM0YHQ+HwblgUxeQG8IF55o2Z6M727YsLGDdGzcuGEDDpXjfs/ZzORk - XFNEivx+HU3FO5MbdQH9+TnnyWP9TmzGfBep/oq2CO/n86ao7xBdHH+K7yTJHXZs7g2h - XB4+Kq1+Pf5OcocpCI7wGP0N2F3mYHfJJlvVNHLWVx1fUP51lFcEDc68hjHe1uCanY2Q - sDG5KOSYFT5Rwo/0KBGlC1FeuI/O8e0TXn/SS+Giwb45Hmk5E9Yd3y73/4u98tSL4/tk - yoegZBJGwqNildSu5nJn7r48adQw6mbCoxuPe/DAx1mPLljAfbrSsrLwNzy68ZdLDPpv - XEq+juJxu13n0sIJRLyzEi5LyWPQNRtHtidVMz2RC6euUotziaJkGrMcWDOf0xtwzONL - pGrBMTvp3mUaqCFnsosgyIJFtaysN0zdYRp2Vp3v4nFfGzHYcfkJL4+7eULFxpck+FCD - YiniQVs4JR3UzsMX8PnMKcVKhkX/C7dvkjl5md435daW5y9dVDc92rSnKTq9Lj98ceO3 - Foz7fJHsFn5FurMhEtmw9O74jePTQm+sdxdObo/fmOmqSbqAmfTLmlJ43oxciFP2tZip - THh7v1QvfoENa98yHsp41/IH+1vZf3C+m/vOhI8y/s6+0qa/4nwll1mOWD+wf+j8LFd+ - N/utCZ+wj7QfGj/L+MSiW5V96YRHNY8bHkv7cfoTmbq17BJtt/FbGZdaVjm0Nq9Jl4PA - pMJjFkb+3M9DDuNR00/xC2EXyWKLX3DrI/r1ekm/BzV5cJoRqu0Yf45DO/DhS39ari/T - ELXwxI4VbQjYCTwIzKXdDrF2IMSMA2g+N1oIWHYkn9OkIkHytTfGx75zZ4Lcclvijjup - dNP+xuX/dsfeF2/f/iJ9bsufb7zhvauvPXLbHZ9dv3Lh+sEruh5/HDaJ/7Qh74R8iuhV - L3govV9LLTzspQZyKo1Kk8KeVZ41M7cqZ3DN5mdMNV1z1mv5p1Mmjo/C20n6yPLZt6fG - rVbY8jfiwggAmtL1FrOnNFxhVusakXgDFeaMHN6TochEEYgbcgUFft7mrKBFGWnDNE/1 - ZvADjDbHaSR6D0Tcqu+CmLV9iG7khCjBRsyV2+wjXn7wbPV2edd7tV5n8TmnSrFx8xPl - h1gmuXM9F88oLHgCFEqmIoyL0nmqbsWuC1UXoT5LpsIkhWX4NZmS2U8UM+PhvPFwH1wA - PrU2hW8DZp6INcrMd7/UpG44YyzikQGPJvxX51VWe8POulUXq9NCwUXe0FO95x1Rm/jK - LN3Z2zG9aWJFybQ569bFf3PGQsTJlK/B34M97JV/h/dpnx506r3DdFB1B/AidDAQyNMa - Tmi85rT1eMbgtJUWFdH1psMmZuLqYKipNOWUBfKTy20wz2UnNn5KacU5Zb0tZhuxHbYd - sxkVVPKKXpvG5izdi4BuZfI5CcKutUkfaZ7yt1AHXCeINwyJI8oThbRwev9AhFgVi5XJ - UlC20DzCrJo8kgyrUnPqOaTYn0QUJlh5ZhdLHuPPnt0rcovX/eDmSXmFUz3l8dGV+/YJ - 2TRxadBruZhwau+eYffW59SGCvPCLY9eRV/iF7HoYOXhOUjKBUk9IN0Jy9CrPqMPG62B - +xLGjJyMtca1npMeTVHGlIytwVH6TubHmVouJf7sMvV+ICXjOp/06M/awvlLvC9ddah2 - 1aZaVYtqVrPUbHWCmqdmms59fJLcRHCU9LqKnFqdEdP2JJ6+nXB5TWl6nw+n9C41k6zH - S86HqdQLqeeE8HTZgLBDLvQ/w2zutVC3hVqcxecv7h+KxZ3Piwil4PAerRW6n9T23Qgq - IconHsVhUcdRc3w5Tz7KQEz0zBSYRSx68nhZzuFL9Utt/Rd0fy/kTj6miNZN37E2paVj - dXx9DhcWLm6umk+FyMf+rW5auUrFYyhoKt5+J/K/Q/5B6S/qt/osfXZmYJmSNuBkbskR - uM96v+0Qe8fytv2twKfsY8tH9g8DyoP0Xnav9QHbA4F7g1rLiGXEPkoOWA7Yj5LDlsN2 - /L8ay5d4hNZb04kTiz9QQXrx3In0TqgkvTl4gpxTaQVg6e0dauyssKQwyiNDuANlgUXZ - mSyrNyLDg6K9lt4UK52bKBbF3klaLa32XYT321DMAoFqVhWYzWYFlpkXOr5tvdP2BsW/ - JrC8bP2t7RX7rwIjwa9owmxDYIgZAtqgk7qYOeAITqWTgk10ZvBCegXNOEBHrQdso9w0 - fHZ0FQMIIizL18gXJlQ6XM6aCvNw4i9DwAHgF4AZrxSKmU2Tz9QVs9mylz16JsyUPHz6 - 8/MD+9gjvDYVL0SsUDUZmSUVCeTBC3FZPIlPPsHJQlwnRQpBpfxAYJitU412h80OIMHg - MDukGuw2FG0SY+KixWyzWMw4yOEkd0gtRHAFx7r8QKEtaJccRGIFVguVzHhjxi4FbcSq - ICxsZQY80b9UVVyuvDyj0aDFQoWX6I2OvexdYmbvql4VP5ldj6hODHvuMTwswubbimIf - KvDKT2HB7/bgJfDskJMvOBs6PviAZPMFB8EqkSofiPpacWRDgufT/PgGhHPbrde/zE9t - OLJxdLYkfhOZtJHniGrIqxBKAcyVZBCYO+vcF+JLPP+I7d2RjROONTvdHMVPT1/HMzRX - 1FqFBKX31IxSXPMhcfDjBCZyZAgYE/neC5bsKMtGkiTF0/aNeDK+kZ8uz37E0449xA7t - BRuhvcCiY1i1hPYCizJ6IMrAooy4uSgDizL6JMrAKPcOoVcoCyzKODmKMrBobxXlkSFg - UUZfxf3AvDyYVs2LA2l8V/3Gp51i491I+U8tzh5F8JaF1TrJahWPXfDahfAidZKfrfnu - L56eUh1t2tcUzc9tmbft+d7WOdmRaNMvmqKTq574Ob0mfgvbJ1WHuBtY5smO/5TOjQ/R - hlQcsKhaHqvD2kLb8E7TlZpMvOd/vVocNoTzv02+IHJRBn3MdtLJdM4gkqBBJlnBJV5F - V2+y5P/Gm3CRYfrsYFYxonRLnzcbfmNKmF176RpipmtUgycrksWynGUf7cGPF5Ixu7mI - UI8hUIDANLB4UOUM82cP1QiM8GcL+OOxUZsLL0JpcQLh62lFGeO+HaK2Zv72EY+a4uUG - NNKyvvwc96KqaeH668ryJiwrL+8wmvvXRqZVXZhmyaVfFM29ML63yK+rKS6pbWytaKBr - Q560qpLSqrR0WzG98PKHa0uKavQZ9qL43oZmLoP5kMF6IYOtavixnBN2prUH7EVuyWfw - 5t+JF/+/ztDogsUGuxM+LOSgW2JSvP+TIIaycsJnRHDynyUQReSEiyD5mA5S4I86Oygm - PjVuDJgfGpISSY07eTRLSYRN8ef+V0JwciHU01lFfn1NkRDCzPiPQ15jVWmJEEL8vp4z - QqCzLpyD04H4xP34nQL3jf75g6g9osRpeKfPihCtHU/qPGQmYqSz8HuP2fgdxBz8+qSF - zMfvXhaTJfhlxFK8idgliFCsYUl6Wh77b25dMHtea6i+54qNa7s3zuu+snVh6Yyedavm - Lvp/6hp0XgplbmRzdHJlYW0KZW5kb2JqCjI1IDAgb2JqCjEzNDY2CmVuZG9iagoyNiAw - IG9iago8PCAvVHlwZSAvRm9udERlc2NyaXB0b3IgL0FzY2VudCA4MzMgL0NhcEhlaWdo - dCA2MjUgL0Rlc2NlbnQgLTMwMCAvRmxhZ3MgMzIKL0ZvbnRCQm94IFstMTkyIC03MTAg - NzAyIDEyMjJdIC9Gb250TmFtZSAvS1BSSU5QK0NvdXJpZXJOZXdQUy1Cb2xkTVQgL0l0 - YWxpY0FuZ2xlCjAgL1N0ZW1WIDAgL01heFdpZHRoIDYwMCAvWEhlaWdodCA1NDkgL0Zv - bnRGaWxlMiAyNCAwIFIgPj4KZW5kb2JqCjI3IDAgb2JqClsgNjAwIDAgMCAwIDAgMCAw - IDAgNjAwIDYwMCAwIDAgMCAwIDAgMCA2MDAgNjAwIDYwMCAwIDAgMCAwIDAgMCAwIDYw - MCAwIDAKNjAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAw - IDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMAo2MDAgNjAwIDYwMCAwIDYwMCA2MDAg - MCA2MDAgNjAwIDAgNjAwIDYwMCAwIDYwMCA2MDAgMCAwIDYwMCAwIDYwMCA2MDAgMCA2 - MDAKMCAwIDAgNjAwIDAgNjAwIF0KZW5kb2JqCjEwIDAgb2JqCjw8IC9UeXBlIC9Gb250 - IC9TdWJ0eXBlIC9UcnVlVHlwZSAvQmFzZUZvbnQgL0tQUklOUCtDb3VyaWVyTmV3UFMt - Qm9sZE1UIC9Gb250RGVzY3JpcHRvcgoyNiAwIFIgL1dpZHRocyAyNyAwIFIgL0ZpcnN0 - Q2hhciAzMiAvTGFzdENoYXIgMTI1IC9FbmNvZGluZyAvTWFjUm9tYW5FbmNvZGluZwo+ - PgplbmRvYmoKMjggMCBvYmoKKE1hYyBPUyBYIDEwLjYuOCBRdWFydHogUERGQ29udGV4 - dCkKZW5kb2JqCjI5IDAgb2JqCihEOjIwMTIwNTMwMTcyNzQ0WjAwJzAwJykKZW5kb2Jq - CjEgMCBvYmoKPDwgL1Byb2R1Y2VyIDI4IDAgUiAvQ3JlYXRpb25EYXRlIDI5IDAgUiAv - TW9kRGF0ZSAyOSAwIFIgPj4KZW5kb2JqCnhyZWYKMCAzMAowMDAwMDAwMDAwIDY1NTM1 - IGYgCjAwMDAwMjQwNzMgMDAwMDAgbiAKMDAwMDAwMzk3NSAwMDAwMCBuIAowMDAwMDAx - ODM5IDAwMDAwIG4gCjAwMDAwMDM4MjYgMDAwMDAgbiAKMDAwMDAwMDAyMiAwMDAwMCBu - IAowMDAwMDAxODE5IDAwMDAwIG4gCjAwMDAwMDE5NDMgMDAwMDAgbiAKMDAwMDAwMzc5 - MCAwMDAwMCBuIAowMDAwMDAyODk0IDAwMDAwIG4gCjAwMDAwMjM3OTQgMDAwMDAgbiAK - MDAwMDAwOTU0OSAwMDAwMCBuIAowMDAwMDAyMDY2IDAwMDAwIG4gCjAwMDAwMDI4NzQg - MDAwMDAgbiAKMDAwMDAwMjkzMCAwMDAwMCBuIAowMDAwMDAzNzcwIDAwMDAwIG4gCjAw - MDAwMDM5MDkgMDAwMDAgbiAKMDAwMDAwNDEzOCAwMDAwMCBuIAowMDAwMDA0MDIzIDAw - MDAwIG4gCjAwMDAwMDQxMTYgMDAwMDAgbiAKMDAwMDAwNDIzMSAwMDAwMCBuIAowMDAw - MDA5MDg3IDAwMDAwIG4gCjAwMDAwMDkxMDggMDAwMDAgbiAKMDAwMDAwOTMzMyAwMDAw - MCBuIAowMDAwMDA5NzI0IDAwMDAwIG4gCjAwMDAwMjMyODEgMDAwMDAgbiAKMDAwMDAy - MzMwMyAwMDAwMCBuIAowMDAwMDIzNTM2IDAwMDAwIG4gCjAwMDAwMjM5NzkgMDAwMDAg - biAKMDAwMDAyNDAzMSAwMDAwMCBuIAp0cmFpbGVyCjw8IC9TaXplIDMwIC9Sb290IDE2 - IDAgUiAvSW5mbyAxIDAgUiAvSUQgWyA8ZWFkZDM3NTdlMzUyZGMyMDc3NjU1NDZhMzVj - N2E2NmY+CjxlYWRkMzc1N2UzNTJkYzIwNzc2NTU0NmEzNWM3YTY2Zj4gXSA+PgpzdGFy - dHhyZWYKMjQxNDgKJSVFT0YKMSAwIG9iago8PC9BdXRob3IgKEtyc3RlIEFzYW5vdmlj - XG5Kb25hdGhhbiBCYWNocmFjaCkvQ3JlYXRpb25EYXRlIChEOjIwMTEwOTEzMDY1NjAw - WikvQ3JlYXRvciAoT21uaUdyYWZmbGUgUHJvZmVzc2lvbmFsIDUuMy42KS9Nb2REYXRl - IChEOjIwMTIwNTMwMTcyNzAwWikvUHJvZHVjZXIgMjggMCBSIC9UaXRsZSAoY29uZHVw - ZGF0ZXMuZ3JhZmZsZSk+PgplbmRvYmoKeHJlZgoxIDEKMDAwMDAyNDkwNiAwMDAwMCBu - IAp0cmFpbGVyCjw8L0lEIFs8ZWFkZDM3NTdlMzUyZGMyMDc3NjU1NDZhMzVjN2E2NmY+ - IDxlYWRkMzc1N2UzNTJkYzIwNzc2NTU0NmEzNWM3YTY2Zj5dIC9JbmZvIDEgMCBSIC9Q - cmV2IDI0MTQ4IC9Sb290IDE2IDAgUiAvU2l6ZSAzMD4+CnN0YXJ0eHJlZgoyNTExNgol - JUVPRgo= - - QuickLookThumbnail - - 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 - AAEAAQ== - - ReadOnly - NO - RowAlign - 1 - RowSpacing - 36 - SheetTitle - Canvas 1 - SmartAlignmentGuidesActive - YES - SmartDistanceGuidesActive - YES - UniqueID - 1 - UseEntirePage - - VPages - 1 - WindowInfo - - CurrentSheet - 0 - ExpandedCanvases - - - name - Canvas 1 - - - Frame - {{72, 4}, {1368, 874}} - ListView - - OutlineWidth - 142 - RightSidebar - - ShowRuler - - Sidebar - - SidebarWidth - 120 - VisibleRegion - {{-16, 224.5}, {609.5, 360}} - Zoom - 2 - ZoomValues - - - Canvas 1 - 2 - 1 - - - - saveQuickLookFiles - YES - - diff --git a/doc/bootcamp/figs/condupdates.pdf b/doc/bootcamp/figs/condupdates.pdf deleted file mode 100644 index 8ba9abb9..00000000 Binary files a/doc/bootcamp/figs/condupdates.pdf and /dev/null differ diff --git a/doc/bootcamp/figs/enable-shift-register.graffle b/doc/bootcamp/figs/enable-shift-register.graffle deleted file mode 100644 index 7423c4f1..00000000 Binary files a/doc/bootcamp/figs/enable-shift-register.graffle and /dev/null differ diff --git a/doc/bootcamp/figs/enable-shift-register.pdf b/doc/bootcamp/figs/enable-shift-register.pdf deleted file mode 100644 index d38dc0d8..00000000 Binary files a/doc/bootcamp/figs/enable-shift-register.pdf and /dev/null differ diff --git a/doc/bootcamp/figs/gcd.graffle b/doc/bootcamp/figs/gcd.graffle deleted file mode 100644 index d4262f11..00000000 --- a/doc/bootcamp/figs/gcd.graffle +++ /dev/null @@ -1,783 +0,0 @@ - - - - - ActiveLayerIndex - 0 - ApplicationVersion - - com.omnigroup.OmniGrafflePro - 139.18.0.187838 - - AutoAdjust - - BackgroundGraphic - - Bounds - {{0, 0}, {576, 733}} - Class - SolidGraphic - ID - 2 - Style - - shadow - - Draws - NO - - stroke - - Draws - NO - - - - BaseZoom - 0 - CanvasOrigin - {0, 0} - ColumnAlign - 1 - ColumnSpacing - 36 - CreationDate - 2012-05-29 20:39:35 +0000 - Creator - Jonathan Bachrach - DisplayScale - 1 0/72 in = 1.0000 in - GraphDocumentVersion - 8 - GraphicsList - - - Class - LineGraphic - Head - - ID - 25 - - ID - 27 - Points - - {439.99998203088444, 441.00000952613516} - {388.0000179691142, 441.00000952613516} - - Style - - stroke - - HeadArrow - 0 - Legacy - - TailArrow - StickArrow - Width - 2 - - - - - Class - LineGraphic - Head - - ID - 16 - - ID - 22 - Points - - {439.99998203088728, 557.99998657131084} - {388.00001796911465, 557.99998657131084} - - Style - - stroke - - HeadArrow - 0 - Legacy - - TailArrow - StickArrow - Width - 2 - - - - - Bounds - {{155.5, 369}, {15, 29}} - Class - ShapedGraphic - FitText - YES - Flow - Resize - ID - 49 - Shape - Rectangle - Style - - fill - - Draws - NO - - shadow - - Draws - NO - - stroke - - Draws - NO - - - Text - - Pad - 0 - Text - {\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf390 -\cocoascreenfonts1{\fonttbl\f0\fnil\fcharset0 Menlo-Italic;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc - -\f0\i\fs48 \cf0 a} - VerticalPad - 0 - - Wrap - NO - - - Bounds - {{155.5, 486}, {15, 29}} - Class - ShapedGraphic - FitText - YES - Flow - Resize - ID - 48 - Shape - Rectangle - Style - - fill - - Draws - NO - - shadow - - Draws - NO - - stroke - - Draws - NO - - - Text - - Pad - 0 - Text - {\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf390 -\cocoascreenfonts1{\fonttbl\f0\fnil\fcharset0 Menlo-Italic;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc - -\f0\i\fs48 \cf0 b} - VerticalPad - 0 - - Wrap - NO - - - Class - LineGraphic - Head - - ID - 45 - - ID - 46 - Points - - {72, 441} - {124.99998198012071, 441} - - Style - - stroke - - HeadArrow - StickArrow - Legacy - - TailArrow - 0 - Width - 2 - - - - - Bounds - {{126, 405}, {72, 72}} - Class - ShapedGraphic - FontInfo - - Font - Menlo-Regular - Size - 24 - - ID - 45 - Shape - Circle - Style - - stroke - - Width - 2 - - - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf390 -\cocoascreenfonts1{\fonttbl\f0\fnil\fcharset0 Menlo-Regular;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc - -\f0\fs36 \cf0 UFix} - - - - Class - LineGraphic - Head - - ID - 42 - - ID - 43 - Points - - {72, 558} - {124.99998198012071, 558} - - Style - - stroke - - HeadArrow - StickArrow - Legacy - - TailArrow - 0 - Width - 2 - - - - - Bounds - {{126, 522}, {72, 72}} - Class - ShapedGraphic - FontInfo - - Font - Menlo-Regular - Size - 24 - - ID - 42 - Shape - Circle - Style - - stroke - - Width - 2 - - - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf390 -\cocoascreenfonts1{\fonttbl\f0\fnil\fcharset0 Menlo-Regular;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc - -\f0\fs36 \cf0 UFix} - - - - Bounds - {{108, 360}, {108, 252}} - Class - ShapedGraphic - ID - 41 - Shape - Rectangle - Style - - fill - - FillType - 2 - GradientAngle - 90 - GradientColor - - w - 0.666667 - - - stroke - - Width - 2 - - - - - Bounds - {{344.5, 369}, {15, 29}} - Class - ShapedGraphic - FitText - YES - Flow - Resize - ID - 40 - Shape - Rectangle - Style - - fill - - Draws - NO - - shadow - - Draws - NO - - stroke - - Draws - NO - - - Text - - Pad - 0 - Text - {\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf390 -\cocoascreenfonts1{\fonttbl\f0\fnil\fcharset0 Menlo-Italic;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc - -\f0\i\fs48 \cf0 z} - VerticalPad - 0 - - Wrap - NO - - - Bounds - {{315.5, 486}, {73, 29}} - Class - ShapedGraphic - FitText - YES - Flow - Resize - ID - 39 - Shape - Rectangle - Style - - fill - - Draws - NO - - shadow - - Draws - NO - - stroke - - Draws - NO - - - Text - - Pad - 0 - Text - {\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf390 -\cocoascreenfonts1{\fonttbl\f0\fnil\fcharset0 Menlo-Italic;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc - -\f0\i\fs48 \cf0 valid} - VerticalPad - 0 - - Wrap - NO - - - Bounds - {{315, 405}, {72, 72}} - Class - ShapedGraphic - FontInfo - - Font - Menlo-Regular - Size - 24 - - ID - 25 - Shape - Circle - Style - - stroke - - Width - 2 - - - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf390 -\cocoascreenfonts1{\fonttbl\f0\fnil\fcharset0 Menlo-Regular;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc - -\f0\fs36 \cf0 UFix} - - - - Bounds - {{315, 522}, {72, 72}} - Class - ShapedGraphic - FontInfo - - Font - Menlo-Regular - Size - 24 - - ID - 16 - Shape - Circle - Style - - stroke - - Width - 2 - - - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf390 -\cocoascreenfonts1{\fonttbl\f0\fnil\fcharset0 Menlo-Regular;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc - -\f0\fs36 \cf0 Bool} - - - - Bounds - {{297, 360}, {108, 252}} - Class - ShapedGraphic - ID - 14 - Shape - Rectangle - Style - - fill - - FillType - 2 - GradientAngle - 90 - GradientColor - - w - 0.666667 - - - stroke - - Width - 2 - - - - - Bounds - {{162, 324}, {189, 324}} - Class - ShapedGraphic - ID - 13 - Shape - Rectangle - Style - - fill - - FillType - 2 - GradientAngle - 90 - GradientColor - - w - 0.666667 - - MiddleColor - - b - 0.588235 - g - 0.917647 - r - 0.568627 - - TrippleBlend - YES - - - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf390 -\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc - -\f0\fs48 \cf0 GCD} - - - - GridInfo - - ShowsGrid - YES - SnapsToGrid - YES - - GuidesLocked - NO - GuidesVisible - YES - HPages - 1 - ImageCounter - 1 - KeepToScale - - Layers - - - Lock - NO - Name - Layer 1 - Print - YES - View - YES - - - LayoutInfo - - Animate - NO - circoMinDist - 18 - circoSeparation - 0.0 - layoutEngine - dot - neatoSeparation - 0.0 - twopiSeparation - 0.0 - - LinksVisible - NO - MagnetsVisible - NO - MasterSheets - - ModificationDate - 2013-09-30 17:46:58 +0000 - Modifier - Jonathan Bachrach - NotesVisible - NO - Orientation - 2 - OriginVisible - NO - PageBreaks - YES - PrintInfo - - NSBottomMargin - - float - 41 - - NSHorizonalPagination - - coded - BAtzdHJlYW10eXBlZIHoA4QBQISEhAhOU051bWJlcgCEhAdOU1ZhbHVlAISECE5TT2JqZWN0AIWEASqEhAFxlwCG - - NSLeftMargin - - float - 18 - - NSPaperSize - - size - {612, 792} - - NSPrintReverseOrientation - - int - 0 - - NSPrinter - - coded - BAtzdHJlYW10eXBlZIHoA4QBQISEhAlOU1ByaW50ZXIAhIQITlNPYmplY3QAhZKEhIQITlNTdHJpbmcBlIQBKxdFUFNPTiBTdHlsdXMgUGhvdG8gUjIwMIaG - - NSPrinterName - - string - EPSON Stylus Photo R200 - - NSRightMargin - - float - 18 - - NSTopMargin - - float - 18 - - - PrintOnePage - - ReadOnly - NO - RowAlign - 1 - RowSpacing - 36 - SheetTitle - Canvas 1 - SmartAlignmentGuidesActive - YES - SmartDistanceGuidesActive - YES - UniqueID - 1 - UseEntirePage - - VPages - 1 - WindowInfo - - CurrentSheet - 0 - ExpandedCanvases - - - name - Canvas 1 - - - Frame - {{526, 4}, {710, 874}} - ListView - - OutlineWidth - 142 - RightSidebar - - ShowRuler - - Sidebar - - SidebarWidth - 120 - VisibleRegion - {{0, -1}, {575, 735}} - Zoom - 1 - ZoomValues - - - Canvas 1 - 1 - 1 - - - - - diff --git a/doc/bootcamp/figs/gcd.pdf b/doc/bootcamp/figs/gcd.pdf deleted file mode 100644 index 7eb7e390..00000000 Binary files a/doc/bootcamp/figs/gcd.pdf and /dev/null differ diff --git a/doc/bootcamp/figs/hdls.pdf b/doc/bootcamp/figs/hdls.pdf deleted file mode 100644 index eaf8a454..00000000 Binary files a/doc/bootcamp/figs/hdls.pdf and /dev/null differ diff --git a/doc/bootcamp/figs/map.graffle b/doc/bootcamp/figs/map.graffle deleted file mode 100644 index 71d6ece3..00000000 --- a/doc/bootcamp/figs/map.graffle +++ /dev/null @@ -1,705 +0,0 @@ - - - - - ActiveLayerIndex - 0 - ApplicationVersion - - com.omnigroup.OmniGrafflePro - 139.16.0.171715 - - AutoAdjust - - BackgroundGraphic - - Bounds - {{0, 0}, {576, 733}} - Class - SolidGraphic - ID - 2 - Style - - shadow - - Draws - NO - - stroke - - Draws - NO - - - - BaseZoom - 0 - CanvasOrigin - {0, 0} - ColumnAlign - 1 - ColumnSpacing - 36 - CreationDate - 2012-05-29 16:34:49 +0000 - Creator - Jonathan Bachrach - DisplayScale - 1 0/72 in = 1.0000 in - GraphDocumentVersion - 8 - GraphicsList - - - Bounds - {{116, 291.5}, {58, 29}} - Class - ShapedGraphic - FitText - YES - Flow - Resize - FontInfo - - Font - Helvetica - Size - 24 - - ID - 14 - Shape - Rectangle - Style - - fill - - Draws - NO - - shadow - - Draws - NO - - stroke - - Draws - NO - - - Text - - Pad - 0 - Text - {\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf340 -\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc - -\f0\fs48 \cf0 ins[2]} - VerticalPad - 0 - - Wrap - NO - - - Bounds - {{116, 192.5}, {58, 29}} - Class - ShapedGraphic - FitText - YES - Flow - Resize - FontInfo - - Font - Helvetica - Size - 24 - - ID - 13 - Shape - Rectangle - Style - - fill - - Draws - NO - - shadow - - Draws - NO - - stroke - - Draws - NO - - - Text - - Pad - 0 - Text - {\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf340 -\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc - -\f0\fs48 \cf0 ins[1]} - VerticalPad - 0 - - Wrap - NO - - - Bounds - {{116, 93.5}, {58, 29}} - Class - ShapedGraphic - FitText - YES - Flow - Resize - FontInfo - - Font - Helvetica - Size - 24 - - ID - 12 - Shape - Rectangle - Style - - fill - - Draws - NO - - shadow - - Draws - NO - - stroke - - Draws - NO - - - Text - - Pad - 0 - Text - {\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf340 -\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc - -\f0\fs48 \cf0 ins[0]} - VerticalPad - 0 - - Wrap - NO - - - Class - LineGraphic - FontInfo - - Font - Helvetica - Size - 35 - - ID - 11 - Points - - {289, 306} - {324, 306} - - Style - - stroke - - HeadArrow - StickArrow - Legacy - - TailArrow - 0 - Width - 2 - - - Tail - - ID - 9 - - - - Class - LineGraphic - FontInfo - - Font - Helvetica - Size - 35 - - Head - - ID - 9 - - ID - 10 - Points - - {180, 306} - {215, 306} - - Style - - stroke - - HeadArrow - StickArrow - Legacy - - TailArrow - 0 - Width - 2 - - - - - Bounds - {{216, 270}, {72, 72}} - Class - ShapedGraphic - FontInfo - - Font - Helvetica - Size - 35 - - ID - 9 - Shape - Rectangle - Style - - stroke - - Width - 2 - - - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf340 -\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc - -\f0\fs72 \cf0 * y} - - - - Class - LineGraphic - FontInfo - - Font - Helvetica - Size - 35 - - ID - 8 - Points - - {289, 207} - {324, 207} - - Style - - stroke - - HeadArrow - StickArrow - Legacy - - TailArrow - 0 - Width - 2 - - - Tail - - ID - 6 - - - - Class - LineGraphic - FontInfo - - Font - Helvetica - Size - 35 - - Head - - ID - 6 - - ID - 7 - Points - - {180, 207} - {215, 207} - - Style - - stroke - - HeadArrow - StickArrow - Legacy - - TailArrow - 0 - Width - 2 - - - - - Bounds - {{216, 171}, {72, 72}} - Class - ShapedGraphic - FontInfo - - Font - Helvetica - Size - 35 - - ID - 6 - Shape - Rectangle - Style - - stroke - - Width - 2 - - - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf340 -\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc - -\f0\fs72 \cf0 * y} - - - - Class - LineGraphic - FontInfo - - Font - Helvetica - Size - 35 - - ID - 5 - Points - - {289, 108} - {324, 108} - - Style - - stroke - - HeadArrow - StickArrow - Legacy - - TailArrow - 0 - Width - 2 - - - Tail - - ID - 3 - - - - Class - LineGraphic - FontInfo - - Font - Helvetica - Size - 35 - - Head - - ID - 3 - - ID - 4 - Points - - {180, 108} - {215, 108} - - Style - - stroke - - HeadArrow - StickArrow - Legacy - - TailArrow - 0 - Width - 2 - - - - - Bounds - {{216, 72}, {72, 72}} - Class - ShapedGraphic - FontInfo - - Font - Helvetica - Size - 35 - - ID - 3 - Shape - Rectangle - Style - - stroke - - Width - 2 - - - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf340 -\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc - -\f0\fs72 \cf0 * y} - - - - GridInfo - - ShowsGrid - YES - - GuidesLocked - NO - GuidesVisible - YES - HPages - 1 - ImageCounter - 1 - KeepToScale - - Layers - - - Lock - NO - Name - Layer 1 - Print - YES - View - YES - - - LayoutInfo - - Animate - NO - circoMinDist - 18 - circoSeparation - 0.0 - layoutEngine - dot - neatoSeparation - 0.0 - twopiSeparation - 0.0 - - LinksVisible - NO - MagnetsVisible - NO - MasterSheets - - ModificationDate - 2012-10-30 15:33:04 +0000 - Modifier - Jonathan Bachrach - NotesVisible - NO - Orientation - 2 - OriginVisible - NO - PageBreaks - YES - PrintInfo - - NSBottomMargin - - float - 41 - - NSHorizonalPagination - - coded - BAtzdHJlYW10eXBlZIHoA4QBQISEhAhOU051bWJlcgCEhAdOU1ZhbHVlAISECE5TT2JqZWN0AIWEASqEhAFxlwCG - - NSLeftMargin - - float - 18 - - NSPaperSize - - size - {612, 792} - - NSPrintReverseOrientation - - int - 0 - - NSRightMargin - - float - 18 - - NSTopMargin - - float - 18 - - - PrintOnePage - - ReadOnly - NO - RowAlign - 1 - RowSpacing - 36 - SheetTitle - Canvas 1 - SmartAlignmentGuidesActive - YES - SmartDistanceGuidesActive - YES - UniqueID - 1 - UseEntirePage - - VPages - 1 - WindowInfo - - CurrentSheet - 0 - ExpandedCanvases - - - name - Canvas 1 - - - Frame - {{485, 154}, {710, 874}} - ListView - - OutlineWidth - 142 - RightSidebar - - ShowRuler - - Sidebar - - SidebarWidth - 120 - VisibleRegion - {{0, -1}, {575, 735}} - Zoom - 1 - ZoomValues - - - Canvas 1 - 1 - 1 - - - - - diff --git a/doc/bootcamp/figs/map.pdf b/doc/bootcamp/figs/map.pdf deleted file mode 100644 index da498099..00000000 Binary files a/doc/bootcamp/figs/map.pdf and /dev/null differ diff --git a/doc/bootcamp/figs/max2.graffle b/doc/bootcamp/figs/max2.graffle deleted file mode 100644 index 6598f707..00000000 --- a/doc/bootcamp/figs/max2.graffle +++ /dev/null @@ -1,614 +0,0 @@ - - - - - ActiveLayerIndex - 0 - ApplicationVersion - - com.omnigroup.OmniGrafflePro - 139.18.0.187838 - - AutoAdjust - - BackgroundGraphic - - Bounds - {{0, 0}, {576, 733}} - Class - SolidGraphic - ID - 2 - Style - - shadow - - Draws - NO - - stroke - - Draws - NO - - - - BaseZoom - 0 - CanvasOrigin - {0, 0} - ColumnAlign - 1 - ColumnSpacing - 36 - CreationDate - 2012-05-30 02:58:18 +0000 - Creator - Jonathan Bachrach - DisplayScale - 1 0/72 in = 1.0000 in - GraphDocumentVersion - 8 - GraphicsList - - - Class - LineGraphic - FontInfo - - Font - Helvetica - Size - 31 - - Head - - ID - 5 - - ID - 15 - Points - - {145.00001797461832, 324} - {252, 324} - {362.89746405004939, 268.5512679749753} - - Style - - stroke - - HeadArrow - StickArrow - Legacy - - TailArrow - 0 - Width - 2 - - - Tail - - ID - 7 - - - - Class - LineGraphic - FontInfo - - Font - Helvetica - Size - 31 - - Head - - ID - 5 - - ID - 14 - Points - - {145.00001797461832, 180} - {252, 180} - {362.89746652335219, 235.4487332616761} - - Style - - stroke - - HeadArrow - StickArrow - Legacy - - TailArrow - 0 - Width - 2 - - - Tail - - ID - 6 - - - - Class - LineGraphic - FontInfo - - Font - Helvetica - Size - 31 - - ID - 12 - Points - - {433.00001796192754, 252} - {504, 252} - - Style - - stroke - - HeadArrow - StickArrow - Legacy - - TailArrow - 0 - Width - 2 - - - Tail - - ID - 5 - - - - Class - LineGraphic - FontInfo - - Font - Helvetica - Size - 31 - - Head - - ID - 5 - - ID - 11 - Points - - {289.00001802980552, 252} - {358.99998196922479, 252} - - Style - - stroke - - HeadArrow - StickArrow - Legacy - - TailArrow - 0 - Width - 2 - - - Tail - - ID - 3 - - - - Class - LineGraphic - FontInfo - - Font - Helvetica - Size - 31 - - Head - - ID - 3 - - ID - 9 - Points - - {141.10253666727107, 307.44873334626055} - {218.89746625667584, 268.55127249951522} - - Style - - stroke - - HeadArrow - StickArrow - Legacy - - TailArrow - 0 - Width - 2 - - - Tail - - ID - 7 - - - - Class - LineGraphic - FontInfo - - Font - Helvetica - Size - 31 - - Head - - ID - 3 - - ID - 8 - Points - - {141.10253354110631, 196.55126662087338} - {218.89746671941913, 235.44873285826435} - - Style - - stroke - - HeadArrow - StickArrow - Legacy - - TailArrow - 0 - Width - 2 - - - Tail - - ID - 6 - - - - Bounds - {{72, 288}, {72, 72}} - Class - ShapedGraphic - FontInfo - - Font - Helvetica - Size - 31 - - ID - 7 - Shape - Circle - Style - - stroke - - Width - 2 - - - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf390 -\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc - -\f0\fs64 \cf0 y} - - - - Bounds - {{72, 144}, {72, 72}} - Class - ShapedGraphic - FontInfo - - Font - Helvetica - Size - 31 - - ID - 6 - Shape - Circle - Style - - stroke - - Width - 2 - - - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf390 -\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc - -\f0\fs64 \cf0 x} - - - - Bounds - {{360, 216}, {72, 72}} - Class - ShapedGraphic - FontInfo - - Font - Helvetica - Size - 24 - - ID - 5 - Shape - Circle - Style - - stroke - - Width - 2 - - - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf390 -\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc - -\f0\fs50 \cf0 Mux} - - - - Bounds - {{216, 216}, {72, 72}} - Class - ShapedGraphic - FontInfo - - Font - Helvetica - Size - 31 - - ID - 3 - Shape - Circle - Style - - stroke - - Width - 2 - - - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf390 -\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc - -\f0\fs64 \cf0 >} - - - - GridInfo - - ShowsGrid - YES - SnapsToGrid - YES - - GuidesLocked - NO - GuidesVisible - YES - HPages - 1 - ImageCounter - 1 - KeepToScale - - Layers - - - Lock - NO - Name - Layer 1 - Print - YES - View - YES - - - LayoutInfo - - Animate - NO - circoMinDist - 18 - circoSeparation - 0.0 - layoutEngine - dot - neatoSeparation - 0.0 - twopiSeparation - 0.0 - - LinksVisible - NO - MagnetsVisible - NO - MasterSheets - - ModificationDate - 2013-09-28 18:15:53 +0000 - Modifier - Jonathan Bachrach - NotesVisible - NO - Orientation - 2 - OriginVisible - NO - PageBreaks - YES - PrintInfo - - NSBottomMargin - - float - 41 - - NSHorizonalPagination - - coded - BAtzdHJlYW10eXBlZIHoA4QBQISEhAhOU051bWJlcgCEhAdOU1ZhbHVlAISECE5TT2JqZWN0AIWEASqEhAFxlwCG - - NSLeftMargin - - float - 18 - - NSPaperSize - - size - {612, 792} - - NSPrintReverseOrientation - - int - 0 - - NSPrinter - - coded - BAtzdHJlYW10eXBlZIHoA4QBQISEhAlOU1ByaW50ZXIAhIQITlNPYmplY3QAhZKEhIQITlNTdHJpbmcBlIQBKx9IUCBDb2xvciBMYXNlckpldCBDUDQ1MjAgU2VyaWVzhoY= - - NSPrinterName - - string - HP Color LaserJet CP4520 Series - - NSRightMargin - - float - 18 - - NSTopMargin - - float - 18 - - - PrintOnePage - - ReadOnly - NO - RowAlign - 1 - RowSpacing - 36 - SheetTitle - Canvas 1 - SmartAlignmentGuidesActive - YES - SmartDistanceGuidesActive - YES - UniqueID - 1 - UseEntirePage - - VPages - 1 - WindowInfo - - CurrentSheet - 0 - ExpandedCanvases - - - name - Canvas 1 - - - Frame - {{610, 4}, {710, 874}} - ListView - - OutlineWidth - 142 - RightSidebar - - ShowRuler - - Sidebar - - SidebarWidth - 120 - VisibleRegion - {{0, -1}, {575, 735}} - Zoom - 1 - ZoomValues - - - Canvas 1 - 1 - 1 - - - - - diff --git a/doc/bootcamp/figs/max2.pdf b/doc/bootcamp/figs/max2.pdf deleted file mode 100644 index e54872cd..00000000 Binary files a/doc/bootcamp/figs/max2.pdf and /dev/null differ diff --git a/doc/bootcamp/figs/max2c.graffle b/doc/bootcamp/figs/max2c.graffle deleted file mode 100644 index 11b85c4e..00000000 --- a/doc/bootcamp/figs/max2c.graffle +++ /dev/null @@ -1,751 +0,0 @@ - - - - - ActiveLayerIndex - 0 - ApplicationVersion - - com.omnigroup.OmniGrafflePro - 139.18.0.187838 - - AutoAdjust - - BackgroundGraphic - - Bounds - {{0, 0}, {2556, 2101}} - Class - SolidGraphic - ID - 2 - Style - - shadow - - Draws - NO - - stroke - - Draws - NO - - - - BaseZoom - 0 - CanvasOrigin - {0, 0} - ColumnAlign - 1 - ColumnSpacing - 36 - CreationDate - 2012-05-30 02:58:18 +0000 - Creator - Jonathan Bachrach - DisplayScale - 1 0/72 in = 1.0000 in - GraphDocumentVersion - 8 - GraphicsList - - - Bounds - {{474, 348}, {59, 37}} - Class - ShapedGraphic - FitText - YES - Flow - Resize - FontInfo - - Font - Helvetica - Size - 30 - - ID - 98 - Shape - Rectangle - Style - - fill - - Draws - NO - - shadow - - Draws - NO - - stroke - - Draws - NO - - - Text - - Pad - 0 - Text - {\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf390 -\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc - -\f0\fs62 \cf0 Max} - VerticalPad - 0 - - Wrap - NO - - - Class - LineGraphic - FontInfo - - Font - Helvetica - Size - 30 - - Head - - ID - 16 - - ID - 17 - Points - - {433.0000180298054, 252} - {502.99998196921723, 252} - - Style - - stroke - - HeadArrow - StickArrow - Legacy - - TailArrow - 0 - Width - 2 - - - Tail - - ID - 5 - - - - Bounds - {{504, 216}, {72, 72}} - Class - ShapedGraphic - FontInfo - - Font - Helvetica - Size - 31 - - ID - 16 - Shape - Circle - Style - - stroke - - Width - 2 - - - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf390 -\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc - -\f0\fs64 \cf0 z} - - - - Class - LineGraphic - FontInfo - - Font - Helvetica - Size - 30 - - Head - - ID - 5 - - ID - 15 - Points - - {145.00001797461832, 324} - {252, 324} - {362.89746405004939, 268.5512679749753} - - Style - - stroke - - HeadArrow - StickArrow - Legacy - - TailArrow - 0 - Width - 2 - - - Tail - - ID - 7 - - - - Class - LineGraphic - FontInfo - - Font - Helvetica - Size - 30 - - Head - - ID - 5 - - ID - 14 - Points - - {145.00001797461832, 180} - {252, 180} - {362.89746652335219, 235.4487332616761} - - Style - - stroke - - HeadArrow - StickArrow - Legacy - - TailArrow - 0 - Width - 2 - - - Tail - - ID - 6 - - - - Class - LineGraphic - FontInfo - - Font - Helvetica - Size - 30 - - Head - - ID - 5 - - ID - 11 - Points - - {289.0000180298054, 252} - {358.99998196921723, 252} - - Style - - stroke - - HeadArrow - StickArrow - Legacy - - TailArrow - 0 - Width - 2 - - - Tail - - ID - 3 - - - - Class - LineGraphic - FontInfo - - Font - Helvetica - Size - 30 - - Head - - ID - 3 - - ID - 9 - Points - - {141.10254253215234, 307.44874507178935} - {218.8974859048902, 268.55131178136298} - - Style - - stroke - - HeadArrow - StickArrow - Legacy - - TailArrow - 0 - Width - 2 - - - Tail - - ID - 7 - - - - Class - LineGraphic - FontInfo - - Font - Helvetica - Size - 30 - - Head - - ID - 3 - - ID - 8 - Points - - {141.10254001824799, 196.55125367126297} - {218.89748841844431, 235.44868947542366} - - Style - - stroke - - HeadArrow - StickArrow - Legacy - - TailArrow - 0 - Width - 2 - - - Tail - - ID - 6 - - - - Bounds - {{72, 288}, {72, 72}} - Class - ShapedGraphic - FontInfo - - Font - Helvetica - Size - 31 - - ID - 7 - Shape - Circle - Style - - stroke - - Width - 2 - - - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf390 -\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc - -\f0\fs64 \cf0 y} - - - - Bounds - {{72, 144}, {72, 72}} - Class - ShapedGraphic - FontInfo - - Font - Helvetica - Size - 31 - - ID - 6 - Shape - Circle - Style - - stroke - - Width - 2 - - - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf390 -\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc - -\f0\fs64 \cf0 x} - - - - Bounds - {{360, 216}, {72, 72}} - Class - ShapedGraphic - FontInfo - - Font - Helvetica - Size - 24 - - ID - 5 - Shape - Circle - Style - - stroke - - Width - 2 - - - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf390 -\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc - -\f0\fs50 \cf0 Mux} - - - - Bounds - {{216, 216}, {72, 72}} - Class - ShapedGraphic - FontInfo - - Font - Helvetica - Size - 31 - - ID - 3 - Shape - Circle - Style - - stroke - - Width - 2 - - - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf390 -\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc - -\f0\fs64 \cf0 >} - - - - Bounds - {{108, 108}, {432, 288}} - Class - ShapedGraphic - FontInfo - - Font - Helvetica - Size - 30 - - ID - 18 - Shape - Rectangle - Style - - fill - - FillType - 2 - GradientAngle - 90 - GradientColor - - w - 0.666667 - - - - - - GridInfo - - ShowsGrid - YES - SnapsToGrid - YES - - GuidesLocked - NO - GuidesVisible - YES - HPages - 1 - ImageCounter - 1 - KeepToScale - - Layers - - - Lock - NO - Name - Layer 1 - Print - YES - View - YES - - - LayoutInfo - - Animate - NO - circoMinDist - 18 - circoSeparation - 0.0 - layoutEngine - dot - neatoSeparation - 0.0 - twopiSeparation - 0.0 - - LinksVisible - NO - MagnetsVisible - NO - MasterSheets - - ModificationDate - 2013-09-28 18:16:37 +0000 - Modifier - Jonathan Bachrach - NotesVisible - NO - Orientation - 2 - OriginVisible - NO - PageBreaks - YES - PrintInfo - - NSBottomMargin - - float - 41 - - NSHorizonalPagination - - coded - BAtzdHJlYW10eXBlZIHoA4QBQISEhAhOU051bWJlcgCEhAdOU1ZhbHVlAISECE5TT2JqZWN0AIWEASqEhAFxlwCG - - NSLeftMargin - - float - 18 - - NSOrientation - - coded - BAtzdHJlYW10eXBlZIHoA4QBQISEhAhOU051bWJlcgCEhAdOU1ZhbHVlAISECE5TT2JqZWN0AIWEASqEhAFxlwGG - - NSPaperName - - string - C19E5E39-BA28-49BB-B976-F8C173C8B751 - - NSPaperSize - - size - {2592, 2160} - - NSPrintReverseOrientation - - int - 0 - - NSPrinter - - coded - BAtzdHJlYW10eXBlZIHoA4QBQISEhAlOU1ByaW50ZXIAhIQITlNPYmplY3QAhZKEhIQITlNTdHJpbmcBlIQBKx9IUCBDb2xvciBMYXNlckpldCBDUDQ1MjAgU2VyaWVzhoY= - - NSPrinterName - - string - HP Color LaserJet CP4520 Series - - NSRightMargin - - float - 18 - - NSTopMargin - - float - 18 - - - PrintOnePage - - ReadOnly - NO - RowAlign - 1 - RowSpacing - 36 - SheetTitle - Canvas 1 - SmartAlignmentGuidesActive - YES - SmartDistanceGuidesActive - YES - UniqueID - 1 - UseEntirePage - - VPages - 1 - WindowInfo - - CurrentSheet - 0 - ExpandedCanvases - - - name - Canvas 1 - - - Frame - {{0, 4}, {1440, 874}} - ListView - - OutlineWidth - 142 - RightSidebar - - ShowRuler - - Sidebar - - SidebarWidth - 120 - VisibleRegion - {{0, 0}, {1305, 735}} - Zoom - 1 - ZoomValues - - - Canvas 1 - 1 - 1 - - - - - diff --git a/doc/bootcamp/figs/max2c.pdf b/doc/bootcamp/figs/max2c.pdf deleted file mode 100644 index d5c66bd0..00000000 Binary files a/doc/bootcamp/figs/max2c.pdf and /dev/null differ diff --git a/doc/bootcamp/figs/max4.graffle b/doc/bootcamp/figs/max4.graffle deleted file mode 100644 index bbeb2d1b..00000000 --- a/doc/bootcamp/figs/max4.graffle +++ /dev/null @@ -1,2253 +0,0 @@ - - - - - ActiveLayerIndex - 0 - ApplicationVersion - - com.omnigroup.OmniGrafflePro - 139.18.0.187838 - - AutoAdjust - - BackgroundGraphic - - Bounds - {{0, 0}, {2556, 2101}} - Class - SolidGraphic - ID - 2 - Style - - shadow - - Draws - NO - - stroke - - Draws - NO - - - - BaseZoom - 0 - CanvasOrigin - {0, 0} - ColumnAlign - 1 - ColumnSpacing - 36 - CreationDate - 2012-05-30 02:58:18 +0000 - Creator - Jonathan Bachrach - DisplayScale - 1 0/72 in = 1.0000 in - GraphDocumentVersion - 8 - GraphicsList - - - Bounds - {{765, 110}, {2, 12}} - Class - ShapedGraphic - FitText - YES - Flow - Resize - ID - 99 - Shape - Rectangle - Style - - fill - - Draws - NO - - shadow - - Draws - NO - - stroke - - Draws - NO - - - Text - - Pad - 0 - VerticalPad - 0 - - Wrap - NO - - - Bounds - {{1147.5, 486}, {62, 53}} - Class - ShapedGraphic - FitText - YES - Flow - Resize - FontInfo - - Font - Helvetica - Size - 44 - - ID - 98 - Shape - Rectangle - Style - - fill - - Draws - NO - - shadow - - Draws - NO - - stroke - - Draws - NO - - - Text - - Pad - 0 - Text - {\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf390 -\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc - -\f0\fs88 \cf0 m3} - VerticalPad - 0 - - Wrap - NO - - - Bounds - {{571.5, 641}, {62, 53}} - Class - ShapedGraphic - FitText - YES - Flow - Resize - FontInfo - - Font - Helvetica - Size - 44 - - ID - 97 - Shape - Rectangle - Style - - fill - - Draws - NO - - shadow - - Draws - NO - - stroke - - Draws - NO - - - Text - - Pad - 0 - Text - {\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf390 -\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc - -\f0\fs88 \cf0 m2} - VerticalPad - 0 - - Wrap - NO - - - Bounds - {{571.5, 335}, {62, 53}} - Class - ShapedGraphic - FitText - YES - Flow - Resize - FontInfo - - Font - Helvetica - Size - 44 - - ID - 96 - Shape - Rectangle - Style - - fill - - Draws - NO - - shadow - - Draws - NO - - stroke - - Draws - NO - - - Text - - Pad - 0 - Text - {\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf390 -\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc - -\f0\fs88 \cf0 m1} - VerticalPad - 0 - - Wrap - NO - - - Class - LineGraphic - FontInfo - - Font - Helvetica - Size - 31 - - ID - 94 - Points - - {1261.0000179619276, 405} - {1332, 405} - - Style - - stroke - - HeadArrow - StickArrow - Legacy - - TailArrow - 0 - Width - 2 - - - Tail - - ID - 72 - - - - Class - LineGraphic - FontInfo - - Font - Helvetica - Size - 31 - - Head - - ID - 78 - - ID - 93 - Points - - {680.25627334806234, 539.85584624025762} - {759.74372664930786, 495.1441537547156} - - Style - - stroke - - HeadArrow - StickArrow - Legacy - - TailArrow - 0 - Width - 2 - - - Tail - - ID - 59 - - - - Class - LineGraphic - FontInfo - - Font - Helvetica - Size - 31 - - Head - - ID - 79 - - ID - 92 - Points - - {680.25627055292478, 270.14415218747757} - {759.74372944409049, 314.85584781734963} - - Style - - stroke - - HeadArrow - StickArrow - Legacy - - TailArrow - 0 - Width - 2 - - - Tail - - ID - 46 - - - - Class - LineGraphic - FontInfo - - Font - Helvetica - Size - 31 - - Head - - ID - 65 - - ID - 91 - Points - - {109.00001802980542, 630} - {178.99998196921726, 630} - - Style - - stroke - - HeadArrow - StickArrow - Legacy - - TailArrow - 0 - Width - 2 - - - Tail - - ID - 85 - - - - Class - LineGraphic - FontInfo - - Font - Helvetica - Size - 31 - - Head - - ID - 66 - - ID - 90 - Points - - {109.00001802980542, 486} - {178.99998196921726, 486} - - Style - - stroke - - HeadArrow - StickArrow - Legacy - - TailArrow - 0 - Width - 2 - - - Tail - - ID - 84 - - - - Class - LineGraphic - FontInfo - - Font - Helvetica - Size - 31 - - Head - - ID - 52 - - ID - 89 - Points - - {109.00001802980542, 324} - {178.99998196921726, 324} - - Style - - stroke - - HeadArrow - StickArrow - Legacy - - TailArrow - 0 - Width - 2 - - - Tail - - ID - 86 - - - - Class - LineGraphic - FontInfo - - Font - Helvetica - Size - 31 - - Head - - ID - 53 - - ID - 88 - Points - - {109.00001802980542, 180} - {178.99998196921726, 180} - - Style - - stroke - - HeadArrow - StickArrow - Legacy - - TailArrow - 0 - Width - 2 - - - Tail - - ID - 87 - - - - Bounds - {{36, 144}, {72, 72}} - Class - ShapedGraphic - FontInfo - - Font - Helvetica - Size - 31 - - ID - 87 - Shape - Circle - Style - - stroke - - Width - 2 - - - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf390 -\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc - -\f0\fs64 \cf0 a} - - - - Bounds - {{36, 288}, {72, 72}} - Class - ShapedGraphic - FontInfo - - Font - Helvetica - Size - 31 - - ID - 86 - Shape - Circle - Style - - stroke - - Width - 2 - - - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf390 -\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc - -\f0\fs64 \cf0 b} - - - - Bounds - {{36, 594}, {72, 72}} - Class - ShapedGraphic - FontInfo - - Font - Helvetica - Size - 31 - - ID - 85 - Shape - Circle - Style - - stroke - - Width - 2 - - - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf390 -\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc - -\f0\fs64 \cf0 d} - - - - Bounds - {{36, 450}, {72, 72}} - Class - ShapedGraphic - FontInfo - - Font - Helvetica - Size - 31 - - ID - 84 - Shape - Circle - Style - - stroke - - Width - 2 - - - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf390 -\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc - -\f0\fs64 \cf0 c} - - - - Class - LineGraphic - FontInfo - - Font - Helvetica - Size - 31 - - Head - - ID - 72 - - ID - 71 - Points - - {1117.000018029805, 404.99999199527002} - {1186.9999819692187, 404.99999199527002} - - Style - - stroke - - HeadArrow - StickArrow - Legacy - - TailArrow - 0 - Width - 2 - - - Tail - - ID - 80 - - - - Bounds - {{1188, 369}, {72, 72}} - Class - ShapedGraphic - FontInfo - - Font - Helvetica - Size - 31 - - ID - 72 - Shape - Circle - Style - - stroke - - Width - 2 - - - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf390 -\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc - -\f0\fs64 \cf0 z} - - - - Class - LineGraphic - FontInfo - - Font - Helvetica - Size - 31 - - Head - - ID - 80 - - ID - 73 - Points - - {829.00001797461834, 477} - {936, 477} - {1046.8974640500494, 421.5512679749753} - - Style - - stroke - - HeadArrow - StickArrow - Legacy - - TailArrow - 0 - Width - 2 - - - Tail - - ID - 78 - - - - Class - LineGraphic - FontInfo - - Font - Helvetica - Size - 31 - - Head - - ID - 80 - - ID - 74 - Points - - {829.00001797461834, 333} - {936, 333} - {1046.8974665233523, 388.44873326167607} - - Style - - stroke - - HeadArrow - StickArrow - Legacy - - TailArrow - 0 - Width - 2 - - - Tail - - ID - 79 - - - - Class - LineGraphic - FontInfo - - Font - Helvetica - Size - 31 - - Head - - ID - 80 - - ID - 75 - Points - - {973.00001802980512, 404.99999199527002} - {1042.9999819692187, 404.99999199527002} - - Style - - stroke - - HeadArrow - StickArrow - Legacy - - TailArrow - 0 - Width - 2 - - - Tail - - ID - 81 - - - - Class - LineGraphic - FontInfo - - Font - Helvetica - Size - 31 - - Head - - ID - 81 - - ID - 76 - Points - - {825.10253596595578, 460.44873194415652} - {902.89746390650521, 421.5512678026389} - - Style - - stroke - - HeadArrow - StickArrow - Legacy - - TailArrow - 0 - Width - 2 - - - Tail - - ID - 78 - - - - Class - LineGraphic - FontInfo - - Font - Helvetica - Size - 31 - - Head - - ID - 81 - - ID - 77 - Points - - {825.10253350995174, 349.55126668314847} - {902.8974666146579, 388.44873306669837} - - Style - - stroke - - HeadArrow - StickArrow - Legacy - - TailArrow - 0 - Width - 2 - - - Tail - - ID - 79 - - - - Bounds - {{756, 441}, {72, 72}} - Class - ShapedGraphic - FontInfo - - Font - Helvetica - Size - 31 - - ID - 78 - Shape - Circle - Style - - stroke - - Width - 2 - - - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf390 -\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc - -\f0\fs64 \cf0 y} - - - - Bounds - {{756, 297}, {72, 72}} - Class - ShapedGraphic - FontInfo - - Font - Helvetica - Size - 31 - - ID - 79 - Shape - Circle - Style - - stroke - - Width - 2 - - - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf390 -\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc - -\f0\fs64 \cf0 x} - - - - Bounds - {{1044, 369}, {72, 72}} - Class - ShapedGraphic - FontInfo - - Font - Helvetica - Size - 24 - - ID - 80 - Shape - Circle - Style - - stroke - - Width - 2 - - - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf390 -\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc - -\f0\fs50 \cf0 Mux} - - - - Bounds - {{900, 369}, {72, 72}} - Class - ShapedGraphic - FontInfo - - Font - Helvetica - Size - 31 - - ID - 81 - Shape - Circle - Style - - stroke - - Width - 2 - - - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf390 -\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc - -\f0\fs64 \cf0 >} - - - - Bounds - {{792, 261}, {432, 288}} - Class - ShapedGraphic - FontInfo - - Font - Helvetica - Size - 31 - - ID - 82 - Shape - Rectangle - Style - - fill - - FillType - 2 - GradientAngle - 90 - GradientColor - - w - 0.666667 - - - - - - Class - LineGraphic - FontInfo - - Font - Helvetica - Size - 31 - - Head - - ID - 59 - - ID - 58 - Points - - {541.00001802980546, 558} - {610.99998196921717, 558} - - Style - - stroke - - HeadArrow - StickArrow - Legacy - - TailArrow - 0 - Width - 2 - - - Tail - - ID - 67 - - - - Bounds - {{612, 522}, {72, 72}} - Class - ShapedGraphic - FontInfo - - Font - Helvetica - Size - 31 - - ID - 59 - Shape - Circle - Style - - stroke - - Width - 2 - - - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf390 -\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc - -\f0\fs64 \cf0 z} - - - - Class - LineGraphic - FontInfo - - Font - Helvetica - Size - 31 - - Head - - ID - 67 - - ID - 60 - Points - - {253.00001797461834, 630} - {360, 630} - {470.89746405004945, 574.5512679749753} - - Style - - stroke - - HeadArrow - StickArrow - Legacy - - TailArrow - 0 - Width - 2 - - - Tail - - ID - 65 - - - - Class - LineGraphic - FontInfo - - Font - Helvetica - Size - 31 - - Head - - ID - 67 - - ID - 61 - Points - - {253.00001797461834, 486} - {360, 486} - {470.89746652335214, 541.44873326167613} - - Style - - stroke - - HeadArrow - StickArrow - Legacy - - TailArrow - 0 - Width - 2 - - - Tail - - ID - 66 - - - - Class - LineGraphic - FontInfo - - Font - Helvetica - Size - 31 - - Head - - ID - 67 - - ID - 62 - Points - - {397.0000180298054, 558} - {466.99998196921723, 558} - - Style - - stroke - - HeadArrow - StickArrow - Legacy - - TailArrow - 0 - Width - 2 - - - Tail - - ID - 68 - - - - Class - LineGraphic - FontInfo - - Font - Helvetica - Size - 31 - - Head - - ID - 68 - - ID - 63 - Points - - {249.10253599511935, 613.44873200244035} - {326.89746400495943, 574.55126799752031} - - Style - - stroke - - HeadArrow - StickArrow - Legacy - - TailArrow - 0 - Width - 2 - - - Tail - - ID - 65 - - - - Class - LineGraphic - FontInfo - - Font - Helvetica - Size - 31 - - Head - - ID - 68 - - ID - 64 - Points - - {249.10253348121392, 502.55126674060699} - {326.89746651850771, 541.44873325925391} - - Style - - stroke - - HeadArrow - StickArrow - Legacy - - TailArrow - 0 - Width - 2 - - - Tail - - ID - 66 - - - - Bounds - {{180, 594}, {72, 72}} - Class - ShapedGraphic - FontInfo - - Font - Helvetica - Size - 31 - - ID - 65 - Shape - Circle - Style - - stroke - - Width - 2 - - - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf390 -\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc - -\f0\fs64 \cf0 y} - - - - Bounds - {{180, 450}, {72, 72}} - Class - ShapedGraphic - FontInfo - - Font - Helvetica - Size - 31 - - ID - 66 - Shape - Circle - Style - - stroke - - Width - 2 - - - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf390 -\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc - -\f0\fs64 \cf0 x} - - - - Bounds - {{468, 522}, {72, 72}} - Class - ShapedGraphic - FontInfo - - Font - Helvetica - Size - 24 - - ID - 67 - Shape - Circle - Style - - stroke - - Width - 2 - - - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf390 -\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc - -\f0\fs50 \cf0 Mux} - - - - Bounds - {{324, 522}, {72, 72}} - Class - ShapedGraphic - FontInfo - - Font - Helvetica - Size - 31 - - ID - 68 - Shape - Circle - Style - - stroke - - Width - 2 - - - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf390 -\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc - -\f0\fs64 \cf0 >} - - - - Bounds - {{216, 414}, {432, 288}} - Class - ShapedGraphic - FontInfo - - Font - Helvetica - Size - 31 - - ID - 69 - Shape - Rectangle - Style - - fill - - FillType - 2 - GradientAngle - 90 - GradientColor - - w - 0.666667 - - - - - - Class - LineGraphic - FontInfo - - Font - Helvetica - Size - 31 - - Head - - ID - 46 - - ID - 45 - Points - - {541.00001802980546, 252} - {610.99998196921717, 252} - - Style - - stroke - - HeadArrow - StickArrow - Legacy - - TailArrow - 0 - Width - 2 - - - Tail - - ID - 54 - - - - Bounds - {{612, 216}, {72, 72}} - Class - ShapedGraphic - FontInfo - - Font - Helvetica - Size - 31 - - ID - 46 - Shape - Circle - Style - - stroke - - Width - 2 - - - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf390 -\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc - -\f0\fs64 \cf0 z} - - - - Class - LineGraphic - FontInfo - - Font - Helvetica - Size - 31 - - Head - - ID - 54 - - ID - 47 - Points - - {253.00001797461834, 324} - {360, 324} - {470.89746405004939, 268.5512679749753} - - Style - - stroke - - HeadArrow - StickArrow - Legacy - - TailArrow - 0 - Width - 2 - - - Tail - - ID - 52 - - - - Class - LineGraphic - FontInfo - - Font - Helvetica - Size - 31 - - Head - - ID - 54 - - ID - 48 - Points - - {253.00001797461834, 180} - {360, 180} - {470.89746652335214, 235.44873326167607} - - Style - - stroke - - HeadArrow - StickArrow - Legacy - - TailArrow - 0 - Width - 2 - - - Tail - - ID - 53 - - - - Class - LineGraphic - FontInfo - - Font - Helvetica - Size - 31 - - Head - - ID - 54 - - ID - 49 - Points - - {397.0000180298054, 252} - {466.99998196921723, 252} - - Style - - stroke - - HeadArrow - StickArrow - Legacy - - TailArrow - 0 - Width - 2 - - - Tail - - ID - 55 - - - - Class - LineGraphic - FontInfo - - Font - Helvetica - Size - 31 - - Head - - ID - 55 - - ID - 50 - Points - - {249.10253599511935, 307.44873200244029} - {326.89746400495949, 268.55126799752026} - - Style - - stroke - - HeadArrow - StickArrow - Legacy - - TailArrow - 0 - Width - 2 - - - Tail - - ID - 52 - - - - Class - LineGraphic - FontInfo - - Font - Helvetica - Size - 31 - - Head - - ID - 55 - - ID - 51 - Points - - {249.10253348121395, 196.55126674060699} - {326.89746651850771, 235.44873325925386} - - Style - - stroke - - HeadArrow - StickArrow - Legacy - - TailArrow - 0 - Width - 2 - - - Tail - - ID - 53 - - - - Bounds - {{180, 288}, {72, 72}} - Class - ShapedGraphic - FontInfo - - Font - Helvetica - Size - 31 - - ID - 52 - Shape - Circle - Style - - stroke - - Width - 2 - - - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf390 -\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc - -\f0\fs64 \cf0 y} - - - - Bounds - {{180, 144}, {72, 72}} - Class - ShapedGraphic - FontInfo - - Font - Helvetica - Size - 31 - - ID - 53 - Shape - Circle - Style - - stroke - - Width - 2 - - - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf390 -\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc - -\f0\fs64 \cf0 x} - - - - Bounds - {{468, 216}, {72, 72}} - Class - ShapedGraphic - FontInfo - - Font - Helvetica - Size - 24 - - ID - 54 - Shape - Circle - Style - - stroke - - Width - 2 - - - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf390 -\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc - -\f0\fs50 \cf0 Mux} - - - - Bounds - {{324, 216}, {72, 72}} - Class - ShapedGraphic - FontInfo - - Font - Helvetica - Size - 31 - - ID - 55 - Shape - Circle - Style - - stroke - - Width - 2 - - - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf390 -\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc - -\f0\fs64 \cf0 >} - - - - Bounds - {{216, 108}, {432, 288}} - Class - ShapedGraphic - FontInfo - - Font - Helvetica - Size - 31 - - ID - 56 - Shape - Rectangle - Style - - fill - - FillType - 2 - GradientAngle - 90 - GradientColor - - w - 0.666667 - - - - - - GridInfo - - ShowsGrid - YES - SnapsToGrid - YES - - GuidesLocked - NO - GuidesVisible - YES - HPages - 1 - ImageCounter - 1 - KeepToScale - - Layers - - - Lock - NO - Name - Layer 1 - Print - YES - View - YES - - - LayoutInfo - - Animate - NO - circoMinDist - 18 - circoSeparation - 0.0 - layoutEngine - dot - neatoSeparation - 0.0 - twopiSeparation - 0.0 - - LinksVisible - NO - MagnetsVisible - NO - MasterSheets - - ModificationDate - 2013-09-28 18:18:01 +0000 - Modifier - Jonathan Bachrach - NotesVisible - NO - Orientation - 2 - OriginVisible - NO - PageBreaks - YES - PrintInfo - - NSBottomMargin - - float - 41 - - NSHorizonalPagination - - coded - BAtzdHJlYW10eXBlZIHoA4QBQISEhAhOU051bWJlcgCEhAdOU1ZhbHVlAISECE5TT2JqZWN0AIWEASqEhAFxlwCG - - NSLeftMargin - - float - 18 - - NSOrientation - - coded - BAtzdHJlYW10eXBlZIHoA4QBQISEhAhOU051bWJlcgCEhAdOU1ZhbHVlAISECE5TT2JqZWN0AIWEASqEhAFxlwGG - - NSPaperName - - string - 093B99D8-5836-409F-8C84-37C9552186E7 - - NSPaperSize - - size - {2592, 2160} - - NSPrintReverseOrientation - - int - 0 - - NSPrinter - - coded - BAtzdHJlYW10eXBlZIHoA4QBQISEhAlOU1ByaW50ZXIAhIQITlNPYmplY3QAhZKEhIQITlNTdHJpbmcBlIQBKx9IUCBDb2xvciBMYXNlckpldCBDUDQ1MjAgU2VyaWVzhoY= - - NSPrinterName - - string - HP Color LaserJet CP4520 Series - - NSRightMargin - - float - 18 - - NSTopMargin - - float - 18 - - - PrintOnePage - - ReadOnly - NO - RowAlign - 1 - RowSpacing - 36 - SheetTitle - Canvas 1 - SmartAlignmentGuidesActive - YES - SmartDistanceGuidesActive - YES - UniqueID - 1 - UseEntirePage - - VPages - 1 - WindowInfo - - CurrentSheet - 0 - ExpandedCanvases - - - name - Canvas 1 - - - Frame - {{0, 4}, {1440, 874}} - ListView - - OutlineWidth - 142 - RightSidebar - - ShowRuler - - Sidebar - - SidebarWidth - 120 - VisibleRegion - {{0, 0}, {1305, 735}} - Zoom - 1 - ZoomValues - - - Canvas 1 - 1 - 1 - - - - - diff --git a/doc/bootcamp/figs/max4.pdf b/doc/bootcamp/figs/max4.pdf deleted file mode 100644 index 428c62da..00000000 Binary files a/doc/bootcamp/figs/max4.pdf and /dev/null differ diff --git a/doc/bootcamp/figs/predicate-filter.graffle b/doc/bootcamp/figs/predicate-filter.graffle deleted file mode 100644 index 76d21463..00000000 Binary files a/doc/bootcamp/figs/predicate-filter.graffle and /dev/null differ diff --git a/doc/bootcamp/figs/predicate-filter.pdf b/doc/bootcamp/figs/predicate-filter.pdf deleted file mode 100644 index bbc42e5d..00000000 Binary files a/doc/bootcamp/figs/predicate-filter.pdf and /dev/null differ diff --git a/doc/bootcamp/figs/programming-in-scala.pdf b/doc/bootcamp/figs/programming-in-scala.pdf deleted file mode 100644 index b89bad06..00000000 Binary files a/doc/bootcamp/figs/programming-in-scala.pdf and /dev/null differ diff --git a/doc/bootcamp/figs/programming-scala.pdf b/doc/bootcamp/figs/programming-scala.pdf deleted file mode 100644 index 4e7f9e7f..00000000 Binary files a/doc/bootcamp/figs/programming-scala.pdf and /dev/null differ diff --git a/doc/bootcamp/figs/reduce.graffle b/doc/bootcamp/figs/reduce.graffle deleted file mode 100644 index 519f8343..00000000 --- a/doc/bootcamp/figs/reduce.graffle +++ /dev/null @@ -1,809 +0,0 @@ - - - - - ActiveLayerIndex - 0 - ApplicationVersion - - com.omnigroup.OmniGrafflePro - 139.16.0.171715 - - AutoAdjust - - BackgroundGraphic - - Bounds - {{0, 0}, {576, 733}} - Class - SolidGraphic - ID - 2 - Style - - shadow - - Draws - NO - - stroke - - Draws - NO - - - - BaseZoom - 0 - CanvasOrigin - {0, 0} - ColumnAlign - 1 - ColumnSpacing - 36 - CreationDate - 2012-05-29 16:38:27 +0000 - Creator - Jonathan Bachrach - DisplayScale - 1 0/72 in = 1.0000 in - GraphDocumentVersion - 8 - GraphicsList - - - Bounds - {{45, 227}, {58, 29}} - Class - ShapedGraphic - FitText - YES - Flow - Resize - FontInfo - - Font - Helvetica - Size - 24 - - ID - 20 - Shape - Rectangle - Style - - fill - - Draws - NO - - shadow - - Draws - NO - - stroke - - Draws - NO - - - Text - - Pad - 0 - Text - {\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf340 -\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc - -\f0\fs48 \cf0 ins[3]} - VerticalPad - 0 - - Wrap - NO - - - Bounds - {{45, 180}, {58, 29}} - Class - ShapedGraphic - FitText - YES - Flow - Resize - FontInfo - - Font - Helvetica - Size - 24 - - ID - 19 - Shape - Rectangle - Style - - fill - - Draws - NO - - shadow - - Draws - NO - - stroke - - Draws - NO - - - Text - - Pad - 0 - Text - {\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf340 -\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc - -\f0\fs48 \cf0 ins[2]} - VerticalPad - 0 - - Wrap - NO - - - Bounds - {{45, 115}, {58, 29}} - Class - ShapedGraphic - FitText - YES - Flow - Resize - FontInfo - - Font - Helvetica - Size - 24 - - ID - 18 - Shape - Rectangle - Style - - fill - - Draws - NO - - shadow - - Draws - NO - - stroke - - Draws - NO - - - Text - - Pad - 0 - Text - {\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf340 -\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc - -\f0\fs48 \cf0 ins[1]} - VerticalPad - 0 - - Wrap - NO - - - Bounds - {{45, 72}, {58, 29}} - Class - ShapedGraphic - FitText - YES - Flow - Resize - FontInfo - - Font - Helvetica - Size - 24 - - ID - 17 - Shape - Rectangle - Style - - fill - - Draws - NO - - shadow - - Draws - NO - - stroke - - Draws - NO - - - Text - - Pad - 0 - Text - {\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf340 -\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc - -\f0\fs48 \cf0 ins[0]} - VerticalPad - 0 - - Wrap - NO - - - Class - LineGraphic - FontInfo - - Font - Helvetica - Size - 25 - - ID - 16 - Points - - {325, 162} - {360, 162} - - Style - - stroke - - HeadArrow - StickArrow - Legacy - - TailArrow - 0 - Width - 2 - - - Tail - - ID - 7 - - - - Class - LineGraphic - FontInfo - - Font - Helvetica - Size - 25 - - Head - - ID - 7 - - ID - 15 - Points - - {216.89442723080541, 197.55278638459728} - {251.10557276741244, 180.44721361629377} - - Style - - stroke - - HeadArrow - StickArrow - Legacy - - TailArrow - 0 - Width - 2 - - - Tail - - ID - 4 - - - - Class - LineGraphic - FontInfo - - Font - Helvetica - Size - 25 - - Head - - ID - 7 - - ID - 14 - Points - - {216.89442723080541, 126.4472136154027} - {251.10557276741244, 143.55278638370623} - - Style - - stroke - - HeadArrow - StickArrow - Legacy - - TailArrow - 0 - Width - 2 - - - Tail - - ID - 3 - - - - Class - LineGraphic - FontInfo - - Font - Helvetica - Size - 25 - - Head - - ID - 4 - - ID - 13 - Points - - {108, 243} - {143.06367082891941, 229.85112343915523} - - Style - - stroke - - HeadArrow - StickArrow - Legacy - - TailArrow - 0 - Width - 2 - - - - - Class - LineGraphic - FontInfo - - Font - Helvetica - Size - 25 - - Head - - ID - 4 - - ID - 12 - Points - - {108, 198} - {143.02985753873992, 206.75746438468499} - - Style - - stroke - - HeadArrow - StickArrow - Legacy - - TailArrow - 0 - Width - 2 - - - - - Class - LineGraphic - FontInfo - - Font - Helvetica - Size - 25 - - Head - - ID - 3 - - ID - 11 - Points - - {108, 126} - {143.02985753873992, 117.24253561531502} - - Style - - stroke - - HeadArrow - StickArrow - Legacy - - TailArrow - 0 - Width - 2 - - - - - Class - LineGraphic - FontInfo - - Font - Helvetica - Size - 25 - - Head - - ID - 3 - - ID - 10 - Points - - {108, 90} - {143.02985753873992, 98.75746438468498} - - Style - - stroke - - HeadArrow - StickArrow - Legacy - - TailArrow - 0 - Width - 2 - - - - - Bounds - {{252, 126}, {72, 72}} - Class - ShapedGraphic - FontInfo - - Font - Helvetica - Size - 25 - - ID - 7 - Shape - Rectangle - Style - - stroke - - Width - 2 - - - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf340 -\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc - -\f0\fs52 \cf0 Max} - - - - Bounds - {{144, 180}, {72, 72}} - Class - ShapedGraphic - FontInfo - - Font - Helvetica - Size - 25 - - ID - 4 - Shape - Rectangle - Style - - stroke - - Width - 2 - - - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf340 -\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc - -\f0\fs52 \cf0 Max} - - - - Bounds - {{144, 72}, {72, 72}} - Class - ShapedGraphic - FontInfo - - Font - Helvetica - Size - 25 - - ID - 3 - Shape - Rectangle - Style - - stroke - - Width - 2 - - - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf340 -\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc - -\f0\fs52 \cf0 Max} - - - - GridInfo - - ShowsGrid - YES - SnapsToGrid - YES - - GuidesLocked - NO - GuidesVisible - YES - HPages - 1 - ImageCounter - 1 - KeepToScale - - Layers - - - Lock - NO - Name - Layer 1 - Print - YES - View - YES - - - LayoutInfo - - Animate - NO - circoMinDist - 18 - circoSeparation - 0.0 - layoutEngine - dot - neatoSeparation - 0.0 - twopiSeparation - 0.0 - - LinksVisible - NO - MagnetsVisible - NO - MasterSheets - - ModificationDate - 2012-10-30 15:35:30 +0000 - Modifier - Jonathan Bachrach - NotesVisible - NO - Orientation - 2 - OriginVisible - NO - PageBreaks - YES - PrintInfo - - NSBottomMargin - - float - 41 - - NSHorizonalPagination - - coded - BAtzdHJlYW10eXBlZIHoA4QBQISEhAhOU051bWJlcgCEhAdOU1ZhbHVlAISECE5TT2JqZWN0AIWEASqEhAFxlwCG - - NSLeftMargin - - float - 18 - - NSPaperSize - - size - {612, 792} - - NSPrintReverseOrientation - - int - 0 - - NSRightMargin - - float - 18 - - NSTopMargin - - float - 18 - - - PrintOnePage - - ReadOnly - NO - RowAlign - 1 - RowSpacing - 36 - SheetTitle - Canvas 1 - SmartAlignmentGuidesActive - YES - SmartDistanceGuidesActive - YES - UniqueID - 1 - UseEntirePage - - VPages - 1 - WindowInfo - - CurrentSheet - 0 - ExpandedCanvases - - - name - Canvas 1 - - - Frame - {{28, 136}, {710, 874}} - ListView - - OutlineWidth - 142 - RightSidebar - - ShowRuler - - Sidebar - - SidebarWidth - 120 - VisibleRegion - {{0, -1}, {575, 735}} - Zoom - 1 - ZoomValues - - - Canvas 1 - 1 - 1 - - - - - diff --git a/doc/bootcamp/figs/reduce.pdf b/doc/bootcamp/figs/reduce.pdf deleted file mode 100644 index 56b0bd94..00000000 Binary files a/doc/bootcamp/figs/reduce.pdf and /dev/null differ diff --git a/doc/bootcamp/figs/reduceMax.graffle b/doc/bootcamp/figs/reduceMax.graffle deleted file mode 100644 index cc5078ae..00000000 --- a/doc/bootcamp/figs/reduceMax.graffle +++ /dev/null @@ -1,1259 +0,0 @@ - - - - - ActiveLayerIndex - 0 - ApplicationVersion - - com.omnigroup.OmniGrafflePro - 139.18.0.187838 - - AutoAdjust - - BackgroundGraphic - - Bounds - {{0, 0}, {2556, 2101}} - Class - SolidGraphic - ID - 2 - Style - - shadow - - Draws - NO - - stroke - - Draws - NO - - - - BaseZoom - 0 - CanvasOrigin - {0, 0} - ColumnAlign - 1 - ColumnSpacing - 36 - CreationDate - 2012-05-30 02:58:18 +0000 - Creator - Jonathan Bachrach - DisplayScale - 1 0/72 in = 1.0000 in - GraphDocumentVersion - 8 - GraphicsList - - - Class - LineGraphic - ID - 112 - Points - - {865.0000179619276, 396} - {936, 396} - - Style - - stroke - - HeadArrow - StickArrow - Legacy - - TailArrow - 0 - Width - 2 - - - Tail - - ID - 80 - - - - Class - LineGraphic - Head - - ID - 80 - - ID - 109 - Points - - {577.00001797461834, 243} - {684, 243} - {802.64131128491238, 369.05639324021945} - - Style - - stroke - - HeadArrow - StickArrow - Legacy - - TailArrow - 0 - Width - 2 - - - Tail - - ID - 54 - - - - Class - LineGraphic - Head - - ID - 80 - - ID - 108 - Points - - {577.00001797461834, 549} - {684, 549} - {802.64131548861667, 422.94360229334484} - - Style - - stroke - - HeadArrow - StickArrow - Legacy - - TailArrow - 0 - Width - 2 - - - Tail - - ID - 67 - - - - Class - LineGraphic - Head - - ID - 81 - - ID - 106 - Points - - {565.35868150189742, 522.05639476411602} - {658.6413011055273, 422.94358884866341} - - Style - - stroke - - HeadArrow - StickArrow - Legacy - - TailArrow - 0 - Width - 2 - - - Tail - - ID - 67 - - - - Class - LineGraphic - Head - - ID - 81 - - ID - 105 - Points - - {565.35869176768369, 269.9436037970541} - {658.64132581171339, 369.05637963949295} - - Style - - stroke - - HeadArrow - StickArrow - Legacy - - TailArrow - 0 - Width - 2 - - - Tail - - ID - 54 - - - - Class - LineGraphic - FontInfo - - Font - Helvetica - Size - 31 - - Head - - ID - 80 - - ID - 75 - Points - - {721.00001802980023, 395.99997527931413} - {790.99998196928038, 395.99992851049581} - - Style - - stroke - - HeadArrow - StickArrow - Legacy - - TailArrow - 0 - Width - 2 - - - Tail - - ID - 81 - - - - Bounds - {{792, 360}, {72, 72}} - Class - ShapedGraphic - FontInfo - - Font - Helvetica - Size - 24 - - ID - 80 - Shape - Circle - Style - - stroke - - Width - 2 - - - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf390 -\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc - -\f0\fs50 \cf0 Mux} - - - - Bounds - {{648, 360}, {72, 72}} - Class - ShapedGraphic - FontInfo - - Font - Helvetica - Size - 31 - - ID - 81 - Shape - Circle - Style - - stroke - - Width - 2 - - - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf390 -\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc - -\f0\fs64 \cf0 >} - - - - Class - LineGraphic - FontInfo - - Font - Helvetica - Size - 31 - - Head - - ID - 67 - - ID - 60 - Points - - {289.00001797461829, 621} - {396, 621} - {506.89746405004945, 565.5512679749753} - - Style - - stroke - - HeadArrow - StickArrow - Legacy - - TailArrow - 0 - Width - 2 - - - Tail - - ID - 65 - - - - Class - LineGraphic - FontInfo - - Font - Helvetica - Size - 31 - - Head - - ID - 67 - - ID - 61 - Points - - {289.00001797461829, 477} - {396, 477} - {506.89746652335214, 532.44873326167613} - - Style - - stroke - - HeadArrow - StickArrow - Legacy - - TailArrow - 0 - Width - 2 - - - Tail - - ID - 66 - - - - Class - LineGraphic - FontInfo - - Font - Helvetica - Size - 31 - - Head - - ID - 67 - - ID - 62 - Points - - {433.0000180298054, 549} - {502.99998196921723, 549} - - Style - - stroke - - HeadArrow - StickArrow - Legacy - - TailArrow - 0 - Width - 2 - - - Tail - - ID - 68 - - - - Class - LineGraphic - FontInfo - - Font - Helvetica - Size - 31 - - Head - - ID - 68 - - ID - 63 - Points - - {285.10253599511935, 604.44873200244035} - {362.89746400495943, 565.55126799752031} - - Style - - stroke - - HeadArrow - StickArrow - Legacy - - TailArrow - 0 - Width - 2 - - - Tail - - ID - 65 - - - - Class - LineGraphic - FontInfo - - Font - Helvetica - Size - 31 - - Head - - ID - 68 - - ID - 64 - Points - - {285.10253348121392, 493.55126674060699} - {362.89746651850771, 532.44873325925391} - - Style - - stroke - - HeadArrow - StickArrow - Legacy - - TailArrow - 0 - Width - 2 - - - Tail - - ID - 66 - - - - Bounds - {{216, 585}, {72, 72}} - Class - ShapedGraphic - FontInfo - - Font - Helvetica - Size - 31 - - ID - 65 - Shape - Circle - Style - - stroke - - Width - 2 - - - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf390 -\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc - -\f0\fs64 \cf0 c} - - - - Bounds - {{216, 441}, {72, 72}} - Class - ShapedGraphic - FontInfo - - Font - Helvetica - Size - 31 - - ID - 66 - Shape - Circle - Style - - stroke - - Width - 2 - - - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf390 -\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc - -\f0\fs64 \cf0 b} - - - - Bounds - {{504, 513}, {72, 72}} - Class - ShapedGraphic - FontInfo - - Font - Helvetica - Size - 24 - - ID - 67 - Shape - Circle - Style - - stroke - - Width - 2 - - - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf390 -\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc - -\f0\fs50 \cf0 Mux} - - - - Bounds - {{360, 513}, {72, 72}} - Class - ShapedGraphic - FontInfo - - Font - Helvetica - Size - 31 - - ID - 68 - Shape - Circle - Style - - stroke - - Width - 2 - - - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf390 -\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc - -\f0\fs64 \cf0 >} - - - - Class - LineGraphic - FontInfo - - Font - Helvetica - Size - 31 - - Head - - ID - 54 - - ID - 47 - Points - - {289.00001797461829, 315} - {396, 315} - {506.89746405004939, 259.5512679749753} - - Style - - stroke - - HeadArrow - StickArrow - Legacy - - TailArrow - 0 - Width - 2 - - - Tail - - ID - 52 - - - - Class - LineGraphic - FontInfo - - Font - Helvetica - Size - 31 - - Head - - ID - 54 - - ID - 104 - Points - - {289.00001797461829, 171} - {396, 171} - {506.89746652335214, 226.44873326167607} - - Style - - stroke - - HeadArrow - StickArrow - Legacy - - TailArrow - 0 - Width - 2 - - - Tail - - ID - 101 - - - - Class - LineGraphic - FontInfo - - Font - Helvetica - Size - 31 - - Head - - ID - 54 - - ID - 49 - Points - - {433.0000180298054, 243} - {502.99998196921723, 243} - - Style - - stroke - - HeadArrow - StickArrow - Legacy - - TailArrow - 0 - Width - 2 - - - Tail - - ID - 55 - - - - Class - LineGraphic - FontInfo - - Font - Helvetica - Size - 31 - - Head - - ID - 55 - - ID - 50 - Points - - {285.10253599511935, 298.44873200244029} - {362.89746400495943, 259.55126799752026} - - Style - - stroke - - HeadArrow - StickArrow - Legacy - - TailArrow - 0 - Width - 2 - - - Tail - - ID - 52 - - - - Class - LineGraphic - FontInfo - - Font - Helvetica - Size - 31 - - Head - - ID - 55 - - ID - 103 - Points - - {285.10253348121398, 187.55126674060699} - {362.89746651850771, 226.44873325925386} - - Style - - stroke - - HeadArrow - StickArrow - Legacy - - TailArrow - 0 - Width - 2 - - - Tail - - ID - 101 - - - - Bounds - {{216, 279}, {72, 72}} - Class - ShapedGraphic - FontInfo - - Font - Helvetica - Size - 31 - - ID - 52 - Shape - Circle - Style - - stroke - - Width - 2 - - - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf390 -\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc - -\f0\fs64 \cf0 b} - - - - Bounds - {{216, 135}, {72, 72}} - Class - ShapedGraphic - FontInfo - - Font - Helvetica - Size - 31 - - ID - 101 - Shape - Circle - Style - - stroke - - Width - 2 - - - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf390 -\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc - -\f0\fs64 \cf0 a} - - - - Bounds - {{504, 207}, {72, 72}} - Class - ShapedGraphic - FontInfo - - Font - Helvetica - Size - 24 - - ID - 54 - Shape - Circle - Style - - stroke - - Width - 2 - - - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf390 -\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc - -\f0\fs50 \cf0 Mux} - - - - Bounds - {{360, 207}, {72, 72}} - Class - ShapedGraphic - FontInfo - - Font - Helvetica - Size - 31 - - ID - 55 - Shape - Circle - Style - - stroke - - Width - 2 - - - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf390 -\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc - -\f0\fs64 \cf0 >} - - - - Bounds - {{198, 117}, {108, 558}} - Class - ShapedGraphic - ID - 110 - Shape - Rectangle - Style - - fill - - FillType - 2 - GradientAngle - 90 - GradientColor - - w - 0.666667 - - MiddleColor - - b - 0.588235 - g - 0.917647 - r - 0.568627 - - TrippleBlend - YES - - - - - GridInfo - - ShowsGrid - YES - SnapsToGrid - YES - - GuidesLocked - NO - GuidesVisible - YES - HPages - 1 - ImageCounter - 1 - KeepToScale - - Layers - - - Lock - NO - Name - Layer 1 - Print - YES - View - YES - - - LayoutInfo - - Animate - NO - circoMinDist - 18 - circoSeparation - 0.0 - layoutEngine - dot - neatoSeparation - 0.0 - twopiSeparation - 0.0 - - LinksVisible - NO - MagnetsVisible - NO - MasterSheets - - ModificationDate - 2013-09-28 18:19:08 +0000 - Modifier - Jonathan Bachrach - NotesVisible - NO - Orientation - 2 - OriginVisible - NO - PageBreaks - YES - PrintInfo - - NSBottomMargin - - float - 41 - - NSHorizonalPagination - - coded - BAtzdHJlYW10eXBlZIHoA4QBQISEhAhOU051bWJlcgCEhAdOU1ZhbHVlAISECE5TT2JqZWN0AIWEASqEhAFxlwCG - - NSLeftMargin - - float - 18 - - NSOrientation - - coded - BAtzdHJlYW10eXBlZIHoA4QBQISEhAhOU051bWJlcgCEhAdOU1ZhbHVlAISECE5TT2JqZWN0AIWEASqEhAFxlwGG - - NSPaperName - - string - 18BA442E-9CCD-43C3-85D0-3F632324736D - - NSPaperSize - - size - {2592, 2160} - - NSPrintReverseOrientation - - int - 0 - - NSPrinter - - coded - BAtzdHJlYW10eXBlZIHoA4QBQISEhAlOU1ByaW50ZXIAhIQITlNPYmplY3QAhZKEhIQITlNTdHJpbmcBlIQBKx9IUCBDb2xvciBMYXNlckpldCBDUDQ1MjAgU2VyaWVzhoY= - - NSPrinterName - - string - HP Color LaserJet CP4520 Series - - NSRightMargin - - float - 18 - - NSTopMargin - - float - 18 - - - PrintOnePage - - ReadOnly - NO - RowAlign - 1 - RowSpacing - 36 - SheetTitle - Canvas 1 - SmartAlignmentGuidesActive - YES - SmartDistanceGuidesActive - YES - UniqueID - 1 - UseEntirePage - - VPages - 1 - WindowInfo - - CurrentSheet - 0 - ExpandedCanvases - - - name - Canvas 1 - - - Frame - {{0, 4}, {1440, 874}} - ListView - - OutlineWidth - 142 - RightSidebar - - ShowRuler - - Sidebar - - SidebarWidth - 120 - VisibleRegion - {{0, 0}, {1305, 735}} - Zoom - 1 - ZoomValues - - - Canvas 1 - 1 - 1 - - - - - diff --git a/doc/bootcamp/figs/reduceMax.pdf b/doc/bootcamp/figs/reduceMax.pdf deleted file mode 100644 index 17fafa41..00000000 Binary files a/doc/bootcamp/figs/reduceMax.pdf and /dev/null differ diff --git a/doc/bootcamp/figs/shift-register.graffle b/doc/bootcamp/figs/shift-register.graffle deleted file mode 100644 index 6885978c..00000000 Binary files a/doc/bootcamp/figs/shift-register.graffle and /dev/null differ diff --git a/doc/bootcamp/figs/shift-register.pdf b/doc/bootcamp/figs/shift-register.pdf deleted file mode 100644 index 236f2433..00000000 Binary files a/doc/bootcamp/figs/shift-register.pdf and /dev/null differ diff --git a/doc/bootcamp/figs/simple-counter.pdf b/doc/bootcamp/figs/simple-counter.pdf deleted file mode 100644 index 9b0aa493..00000000 Binary files a/doc/bootcamp/figs/simple-counter.pdf and /dev/null differ diff --git a/doc/bootcamp/figs/synthesizable.pdf b/doc/bootcamp/figs/synthesizable.pdf deleted file mode 100644 index 1408886c..00000000 Binary files a/doc/bootcamp/figs/synthesizable.pdf and /dev/null differ diff --git a/doc/bootcamp/figs/trouter.graffle b/doc/bootcamp/figs/trouter.graffle deleted file mode 100644 index 1d7b8c15..00000000 --- a/doc/bootcamp/figs/trouter.graffle +++ /dev/null @@ -1,2541 +0,0 @@ - - - - - ActiveLayerIndex - 0 - ApplicationVersion - - com.omnigroup.OmniGrafflePro - 138.33.0.157554 - - AutoAdjust - - BackgroundGraphic - - Bounds - {{0, 0}, {576, 733}} - Class - SolidGraphic - ID - 2 - Style - - shadow - - Draws - NO - - stroke - - Draws - NO - - - - CanvasOrigin - {0, 0} - ColumnAlign - 1 - ColumnSpacing - 36 - CreationDate - 2012-05-29 16:31:24 -0700 - Creator - Jonathan Bachrach - DisplayScale - 1 0/72 in = 1.0000 in - GraphDocumentVersion - 8 - GraphicsList - - - Class - Group - Graphics - - - Class - LineGraphic - FontInfo - - Font - Helvetica - Size - 20 - - ID - 68 - Points - - {486, 294} - {522, 294} - - Style - - stroke - - HeadArrow - 0 - TailArrow - 0 - Width - 3 - - - - - Class - LineGraphic - FontInfo - - Font - Helvetica - Size - 20 - - ID - 69 - Points - - {486, 276} - {522, 276} - - Style - - stroke - - HeadArrow - 0 - TailArrow - 0 - Width - 3 - - - - - Class - LineGraphic - FontInfo - - Font - Helvetica - Size - 20 - - ID - 70 - Points - - {513, 276} - {513, 294} - - Style - - stroke - - HeadArrow - 0 - TailArrow - 0 - Width - 3 - - - - - Class - LineGraphic - FontInfo - - Font - Helvetica - Size - 20 - - ID - 71 - Points - - {504, 276} - {504, 294} - - Style - - stroke - - HeadArrow - 0 - TailArrow - 0 - Width - 3 - - - - - Class - LineGraphic - FontInfo - - Font - Helvetica - Size - 20 - - ID - 72 - Points - - {495, 276} - {495, 294} - - Style - - stroke - - HeadArrow - 0 - TailArrow - 0 - Width - 3 - - - - - ID - 67 - - - Class - Group - Graphics - - - Class - LineGraphic - FontInfo - - Font - Helvetica - Size - 20 - - ID - 62 - Points - - {486, 259} - {522, 259} - - Style - - stroke - - HeadArrow - 0 - TailArrow - 0 - Width - 3 - - - - - Class - LineGraphic - FontInfo - - Font - Helvetica - Size - 20 - - ID - 63 - Points - - {486, 241} - {522, 241} - - Style - - stroke - - HeadArrow - 0 - TailArrow - 0 - Width - 3 - - - - - Class - LineGraphic - FontInfo - - Font - Helvetica - Size - 20 - - ID - 64 - Points - - {513, 241} - {513, 259} - - Style - - stroke - - HeadArrow - 0 - TailArrow - 0 - Width - 3 - - - - - Class - LineGraphic - FontInfo - - Font - Helvetica - Size - 20 - - ID - 65 - Points - - {504, 241} - {504, 259} - - Style - - stroke - - HeadArrow - 0 - TailArrow - 0 - Width - 3 - - - - - Class - LineGraphic - FontInfo - - Font - Helvetica - Size - 20 - - ID - 66 - Points - - {495, 241} - {495, 259} - - Style - - stroke - - HeadArrow - 0 - TailArrow - 0 - Width - 3 - - - - - ID - 61 - - - Class - Group - Graphics - - - Class - LineGraphic - FontInfo - - Font - Helvetica - Size - 20 - - ID - 56 - Points - - {486, 224} - {522, 224} - - Style - - stroke - - HeadArrow - 0 - TailArrow - 0 - Width - 3 - - - - - Class - LineGraphic - FontInfo - - Font - Helvetica - Size - 20 - - ID - 57 - Points - - {486, 206} - {522, 206} - - Style - - stroke - - HeadArrow - 0 - TailArrow - 0 - Width - 3 - - - - - Class - LineGraphic - FontInfo - - Font - Helvetica - Size - 20 - - ID - 58 - Points - - {513, 206} - {513, 224} - - Style - - stroke - - HeadArrow - 0 - TailArrow - 0 - Width - 3 - - - - - Class - LineGraphic - FontInfo - - Font - Helvetica - Size - 20 - - ID - 59 - Points - - {504, 206} - {504, 224} - - Style - - stroke - - HeadArrow - 0 - TailArrow - 0 - Width - 3 - - - - - Class - LineGraphic - FontInfo - - Font - Helvetica - Size - 20 - - ID - 60 - Points - - {495, 206} - {495, 224} - - Style - - stroke - - HeadArrow - 0 - TailArrow - 0 - Width - 3 - - - - - ID - 55 - - - Class - Group - Graphics - - - Class - LineGraphic - FontInfo - - Font - Helvetica - Size - 20 - - ID - 50 - Points - - {486, 189} - {522, 189} - - Style - - stroke - - HeadArrow - 0 - TailArrow - 0 - Width - 3 - - - - - Class - LineGraphic - FontInfo - - Font - Helvetica - Size - 20 - - ID - 51 - Points - - {486, 171} - {522, 171} - - Style - - stroke - - HeadArrow - 0 - TailArrow - 0 - Width - 3 - - - - - Class - LineGraphic - FontInfo - - Font - Helvetica - Size - 20 - - ID - 52 - Points - - {513, 171} - {513, 189} - - Style - - stroke - - HeadArrow - 0 - TailArrow - 0 - Width - 3 - - - - - Class - LineGraphic - FontInfo - - Font - Helvetica - Size - 20 - - ID - 53 - Points - - {504, 171} - {504, 189} - - Style - - stroke - - HeadArrow - 0 - TailArrow - 0 - Width - 3 - - - - - Class - LineGraphic - FontInfo - - Font - Helvetica - Size - 20 - - ID - 54 - Points - - {495, 171} - {495, 189} - - Style - - stroke - - HeadArrow - 0 - TailArrow - 0 - Width - 3 - - - - - ID - 49 - - - Class - Group - Graphics - - - Class - LineGraphic - FontInfo - - Font - Helvetica - Size - 20 - - ID - 44 - Points - - {486, 153} - {522, 153} - - Style - - stroke - - HeadArrow - 0 - TailArrow - 0 - Width - 3 - - - - - Class - LineGraphic - FontInfo - - Font - Helvetica - Size - 20 - - ID - 45 - Points - - {486, 135} - {522, 135} - - Style - - stroke - - HeadArrow - 0 - TailArrow - 0 - Width - 3 - - - - - Class - LineGraphic - FontInfo - - Font - Helvetica - Size - 20 - - ID - 46 - Points - - {513, 135} - {513, 153} - - Style - - stroke - - HeadArrow - 0 - TailArrow - 0 - Width - 3 - - - - - Class - LineGraphic - FontInfo - - Font - Helvetica - Size - 20 - - ID - 47 - Points - - {504, 135} - {504, 153} - - Style - - stroke - - HeadArrow - 0 - TailArrow - 0 - Width - 3 - - - - - Class - LineGraphic - FontInfo - - Font - Helvetica - Size - 20 - - ID - 48 - Points - - {495, 135} - {495, 153} - - Style - - stroke - - HeadArrow - 0 - TailArrow - 0 - Width - 3 - - - - - ID - 43 - - - Class - Group - Graphics - - - Class - LineGraphic - FontInfo - - Font - Helvetica - Size - 20 - - ID - 38 - Points - - {36, 278} - {72, 278} - - Style - - stroke - - HeadArrow - 0 - TailArrow - 0 - Width - 3 - - - - - Class - LineGraphic - FontInfo - - Font - Helvetica - Size - 20 - - ID - 39 - Points - - {36, 260} - {72, 260} - - Style - - stroke - - HeadArrow - 0 - TailArrow - 0 - Width - 3 - - - - - Class - LineGraphic - FontInfo - - Font - Helvetica - Size - 20 - - ID - 40 - Points - - {63, 260} - {63, 278} - - Style - - stroke - - HeadArrow - 0 - TailArrow - 0 - Width - 3 - - - - - Class - LineGraphic - FontInfo - - Font - Helvetica - Size - 20 - - ID - 41 - Points - - {54, 260} - {54, 278} - - Style - - stroke - - HeadArrow - 0 - TailArrow - 0 - Width - 3 - - - - - Class - LineGraphic - FontInfo - - Font - Helvetica - Size - 20 - - ID - 42 - Points - - {45, 260} - {45, 278} - - Style - - stroke - - HeadArrow - 0 - TailArrow - 0 - Width - 3 - - - - - ID - 37 - - - Class - Group - Graphics - - - Class - LineGraphic - FontInfo - - Font - Helvetica - Size - 20 - - ID - 32 - Points - - {36, 224} - {72, 224} - - Style - - stroke - - HeadArrow - 0 - TailArrow - 0 - Width - 3 - - - - - Class - LineGraphic - FontInfo - - Font - Helvetica - Size - 20 - - ID - 33 - Points - - {36, 206} - {72, 206} - - Style - - stroke - - HeadArrow - 0 - TailArrow - 0 - Width - 3 - - - - - Class - LineGraphic - FontInfo - - Font - Helvetica - Size - 20 - - ID - 34 - Points - - {63, 206} - {63, 224} - - Style - - stroke - - HeadArrow - 0 - TailArrow - 0 - Width - 3 - - - - - Class - LineGraphic - FontInfo - - Font - Helvetica - Size - 20 - - ID - 35 - Points - - {54, 206} - {54, 224} - - Style - - stroke - - HeadArrow - 0 - TailArrow - 0 - Width - 3 - - - - - Class - LineGraphic - FontInfo - - Font - Helvetica - Size - 20 - - ID - 36 - Points - - {45, 206} - {45, 224} - - Style - - stroke - - HeadArrow - 0 - TailArrow - 0 - Width - 3 - - - - - ID - 31 - - - Class - Group - Graphics - - - Class - LineGraphic - FontInfo - - Font - Helvetica - Size - 20 - - ID - 26 - Points - - {36, 170} - {72, 170} - - Style - - stroke - - HeadArrow - 0 - TailArrow - 0 - Width - 3 - - - - - Class - LineGraphic - FontInfo - - Font - Helvetica - Size - 20 - - ID - 27 - Points - - {36, 152} - {72, 152} - - Style - - stroke - - HeadArrow - 0 - TailArrow - 0 - Width - 3 - - - - - Class - LineGraphic - FontInfo - - Font - Helvetica - Size - 20 - - ID - 28 - Points - - {63, 152} - {63, 170} - - Style - - stroke - - HeadArrow - 0 - TailArrow - 0 - Width - 3 - - - - - Class - LineGraphic - FontInfo - - Font - Helvetica - Size - 20 - - ID - 29 - Points - - {54, 152} - {54, 170} - - Style - - stroke - - HeadArrow - 0 - TailArrow - 0 - Width - 3 - - - - - Class - LineGraphic - FontInfo - - Font - Helvetica - Size - 20 - - ID - 30 - Points - - {45, 152} - {45, 170} - - Style - - stroke - - HeadArrow - 0 - TailArrow - 0 - Width - 3 - - - - - ID - 25 - - - Bounds - {{393, 126.5}, {72, 35}} - Class - ShapedGraphic - FitText - YES - Flow - Resize - FontInfo - - Color - - w - 0 - - Font - Helvetica - Size - 21 - - ID - 20 - Line - - ID - 19 - Position - 0.47222220897674561 - RotationType - 0 - - Shape - Rectangle - Style - - shadow - - Draws - NO - - stroke - - Draws - NO - Width - 3 - - - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1038\cocoasubrtf360 -{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural - -\f0\fs42 \cf0 replies} - - Wrap - NO - - - Class - LineGraphic - FontInfo - - Font - Helvetica - Size - 20 - - ID - 19 - Points - - {378, 144} - {486, 144} - - Style - - stroke - - HeadArrow - StickArrow - TailArrow - 0 - Width - 3 - - - - - Bounds - {{109.5, 252.5}, {27, 35}} - Class - ShapedGraphic - FitText - YES - Flow - Resize - FontInfo - - Color - - w - 0 - - Font - Helvetica - Size - 21 - - ID - 18 - Line - - ID - 17 - Position - 0.47222220897674561 - RotationType - 0 - - Shape - Rectangle - Style - - shadow - - Draws - NO - - stroke - - Draws - NO - Width - 3 - - - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1038\cocoasubrtf360 -{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural - -\f0\fs42 \cf0 in} - - Wrap - NO - - - Class - LineGraphic - FontInfo - - Font - Helvetica - Size - 20 - - ID - 17 - Points - - {72, 270} - {180, 270} - - Style - - stroke - - HeadArrow - StickArrow - TailArrow - 0 - Width - 3 - - - - - Bounds - {{91.5, 144.5}, {63, 35}} - Class - ShapedGraphic - FitText - YES - Flow - Resize - FontInfo - - Color - - w - 0 - - Font - Helvetica - Size - 21 - - ID - 16 - Line - - ID - 15 - Position - 0.47222220897674561 - RotationType - 0 - - Shape - Rectangle - Style - - shadow - - Draws - NO - - stroke - - Draws - NO - Width - 3 - - - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1038\cocoasubrtf360 -{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural - -\f0\fs42 \cf0 reads} - - Wrap - NO - - - Class - LineGraphic - FontInfo - - Font - Helvetica - Size - 20 - - ID - 15 - Points - - {72, 162} - {180, 162} - - Style - - stroke - - HeadArrow - StickArrow - TailArrow - 0 - Width - 3 - - - - - Bounds - {{394, 271.5}, {70, 33}} - Class - ShapedGraphic - FitText - YES - Flow - Resize - FontInfo - - Color - - w - 0 - - Font - Helvetica - Size - 19 - - ID - 14 - Line - - ID - 13 - Position - 0.47222220897674561 - RotationType - 0 - - Shape - Rectangle - Style - - shadow - - Draws - NO - - stroke - - Draws - NO - Width - 3 - - - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1038\cocoasubrtf360 -{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural - -\f0\fs38 \cf0 outs(3)} - - Wrap - NO - - - Class - LineGraphic - FontInfo - - Font - Helvetica - Size - 18 - - ID - 13 - Points - - {378, 288} - {486, 288} - - Style - - stroke - - HeadArrow - StickArrow - TailArrow - 0 - Width - 3 - - - - - Bounds - {{394, 235.5}, {70, 33}} - Class - ShapedGraphic - FitText - YES - Flow - Resize - FontInfo - - Color - - w - 0 - - Font - Helvetica - Size - 19 - - ID - 12 - Line - - ID - 11 - Position - 0.47222220897674561 - RotationType - 0 - - Shape - Rectangle - Style - - shadow - - Draws - NO - - stroke - - Draws - NO - Width - 3 - - - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1038\cocoasubrtf360 -{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural - -\f0\fs38 \cf0 outs(2)} - - Wrap - NO - - - Class - LineGraphic - FontInfo - - Font - Helvetica - Size - 18 - - ID - 11 - Points - - {378, 252} - {486, 252} - - Style - - stroke - - HeadArrow - StickArrow - TailArrow - 0 - Width - 3 - - - - - Bounds - {{394, 199.5}, {70, 33}} - Class - ShapedGraphic - FitText - YES - Flow - Resize - FontInfo - - Color - - w - 0 - - Font - Helvetica - Size - 19 - - ID - 10 - Line - - ID - 9 - Position - 0.47222220897674561 - RotationType - 0 - - Shape - Rectangle - Style - - shadow - - Draws - NO - - stroke - - Draws - NO - Width - 3 - - - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1038\cocoasubrtf360 -{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural - -\f0\fs38 \cf0 outs(1)} - - Wrap - NO - - - Class - LineGraphic - FontInfo - - Font - Helvetica - Size - 18 - - ID - 9 - Points - - {378, 216} - {486, 216} - - Style - - stroke - - HeadArrow - StickArrow - TailArrow - 0 - Width - 3 - - - - - Bounds - {{394, 163.5}, {70, 33}} - Class - ShapedGraphic - FitText - YES - Flow - Resize - FontInfo - - Color - - w - 0 - - Font - Helvetica - Size - 19 - - ID - 8 - Line - - ID - 7 - Position - 0.47222220897674561 - RotationType - 0 - - Shape - Rectangle - Style - - shadow - - Draws - NO - - stroke - - Draws - NO - Width - 3 - - - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1038\cocoasubrtf360 -{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural - -\f0\fs38 \cf0 outs(0)} - - Wrap - NO - - - Class - LineGraphic - FontInfo - - Font - Helvetica - Size - 18 - - ID - 7 - Points - - {378, 180} - {486, 180} - - Style - - stroke - - HeadArrow - StickArrow - TailArrow - 0 - Width - 3 - - - - - Bounds - {{90.5, 198.5}, {65, 35}} - Class - ShapedGraphic - FitText - YES - Flow - Resize - FontInfo - - Color - - w - 0 - - Font - Helvetica - Size - 21 - - ID - 6 - Line - - ID - 5 - Position - 0.47222220897674561 - RotationType - 0 - - Shape - Rectangle - Style - - shadow - - Draws - NO - - stroke - - Draws - NO - Width - 3 - - - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1038\cocoasubrtf360 -{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural - -\f0\fs42 \cf0 writes} - - Wrap - NO - - - Class - LineGraphic - FontInfo - - Font - Helvetica - Size - 20 - - ID - 5 - Points - - {72, 216} - {180, 216} - - Style - - stroke - - HeadArrow - StickArrow - TailArrow - 0 - Width - 3 - - - - - Bounds - {{180, 117}, {198, 198}} - Class - ShapedGraphic - FontInfo - - Font - Helvetica - Size - 20 - - ID - 3 - Shape - Rectangle - Style - - stroke - - Width - 2 - - - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1038\cocoasubrtf360 -{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural - -\f0\fs70 \cf0 Router} - - - - GridInfo - - ShowsGrid - YES - SnapsToGrid - YES - - GuidesLocked - NO - GuidesVisible - YES - HPages - 1 - ImageCounter - 1 - KeepToScale - - Layers - - - Lock - NO - Name - Layer 1 - Print - YES - View - YES - - - LayoutInfo - - Animate - NO - circoMinDist - 18 - circoSeparation - 0.0 - layoutEngine - dot - neatoSeparation - 0.0 - twopiSeparation - 0.0 - - LinksVisible - NO - MagnetsVisible - NO - MasterSheets - - ModificationDate - 2012-05-30 10:32:19 -0700 - Modifier - Jonathan Bachrach - NotesVisible - NO - Orientation - 2 - OriginVisible - NO - PageBreaks - YES - PrintInfo - - NSBottomMargin - - float - 41 - - NSLeftMargin - - float - 18 - - NSPaperSize - - coded - BAtzdHJlYW10eXBlZIHoA4QBQISEhAdOU1ZhbHVlAISECE5TT2JqZWN0AIWEASqEhAx7X05TU2l6ZT1mZn2WgWQCgRgDhg== - - NSRightMargin - - float - 18 - - NSTopMargin - - float - 18 - - - PrintOnePage - - QuickLookPreview - - JVBERi0xLjMKJcTl8uXrp/Og0MTGCjUgMCBvYmoKPDwgL0xlbmd0aCA2IDAgUiAvRmls - dGVyIC9GbGF0ZURlY29kZSA+PgpzdHJlYW0KeAGtWE1vGzkMvetX8GgfPNXnfFw32B56 - y8bAHto9LLIJkCJpt3GL/v0+ktJ4nI5mpkVgGKY9jxT5+CQq+ULX9IUsXqlrqQuBnu/o - b/pEb65Ojm5P5OR1uqWDbRLxewK8J9dbiq4nN8jbwPuePH2H1zu8P2qcqxtZwtLNFVZz - 8uXAH7zg7ZNEca4rUTiHG3PNvp5zsIT1J36+GygBDs8/jsjJWuvpeEsBCeJ1wOch+Sb5 - 1AZywRyf6M1b11isfLyn3V+fv329e97T8SP9eUT9AelOoo9ZdZ68awnptbFxbJtHuoGD - RW0Wtc05uS414aUfPY4xXNNzREYZjj4+8bbx+Mbxf+J+QHuspTZxiULxJTVmpNT5MKHG - 59/xefBdg0YNiTr08JKR97T7vucGe9o9P+yNWl/3oBa/3JVHpz39Q8d3Slrp7xwHoYMY - IIwnEzsL5theZy72DsyJH039xDbMGDN3Rj2OqFhnLgyBJRs66iyJus19VVfRQ1dJFAld - uUHVhM+DH5rUtv1wQR5Yh5xA3ufC0LdiFO5OH3a2/PZhv4U/A1Ezf6o85UF1sqY8ZWbi - l/VVYqjyzqjCn19SXubPOuVP9/el+M77Wfgb9+Ur8ed+k7/kWS2iPw97q/4Ym/2M+uUY - sZvo7+JJatf0F7FzRX/r/KE/+Vx7Jf78b/LXy25T/mBv5u/sZ7z4Zf76MOVv+mTwq/xh - Y27lL6bX5S/8On8YHK5lGengYHudPh0cEz+jfjlGUvmdUWVwuHZBfoPDgRYJYzCkZe3J - 4OiK9i4GB+K3KfTzZ9/zOB7+LUT9V4xNA4MPPJ606G8hjO2thE38jPrlad3qvFDCLp50 - C/PC2YFibJHOJsYimH15C5ly1zeu8wEgDN2X15CHT+cryOo0jbGcSuRi3HAPyXPy0g+s - 6m50YTjvRoOI5yexX9qNuFXhAui5Y3NXETO5Dsg0wMhUfqasBNsMwUKbs1eRoiiz+78I - 6bEYD8UYVbdZYzgXnJ7tMEaBTfId733YMIpko4pk3fL1UmKyUUUyA6HNSD4bxnH0cnUZ - /kAilGyK5ZioyFu+n7LhuYV8RZiLiUIUyUYVyXmiEEWyUUXmPBXJmxdpzK+ea+dQus0X - Y3IhLdfOBi5B9ZhciCDZqCJzjxTJFVWRJU+JyRXBmF+91I5Q+eBayjPiwu2wU1ASW7hc - 1qMmC70JVqwqlnNNjv+y4bhiVbGcbewhKcV6qA/WfA4cV7CIhriMXY7LFWFk5Nqw1etx - pSLBilXFcr5SkWK5yip2zFexnC+s+RxGHhAt17YcF7WpvLlvyzuBK1KsWFWFl75lLGpb - jsu9yFjUxtZ8bYUH3WTct5W4XFEsffNprW+Kldqq2NK3jOXaqtgxX8lB8oU1X1vpG0fT - vq3E5drwnwzVpB8WT0Xum2Cltip27JtiubYqdsxXsdwLWPO1jTwgWq5tjHv9A8F6m+wK - ZW5kc3RyZWFtCmVuZG9iago2IDAgb2JqCjEwOTQKZW5kb2JqCjMgMCBvYmoKPDwgL1R5 - cGUgL1BhZ2UgL1BhcmVudCA0IDAgUiAvUmVzb3VyY2VzIDcgMCBSIC9Db250ZW50cyA1 - IDAgUiAvTWVkaWFCb3ggWzAgMCA1NzYgNzMzXQo+PgplbmRvYmoKNyAwIG9iago8PCAv - UHJvY1NldCBbIC9QREYgL1RleHQgXSAvQ29sb3JTcGFjZSA8PCAvQ3MyIDkgMCBSIC9D - czEgOCAwIFIgPj4gL0ZvbnQgPDwKL0YxLjAgMTAgMCBSID4+ID4+CmVuZG9iagoxMSAw - IG9iago8PCAvTGVuZ3RoIDEyIDAgUiAvTiAxIC9BbHRlcm5hdGUgL0RldmljZUdyYXkg - L0ZpbHRlciAvRmxhdGVEZWNvZGUgPj4Kc3RyZWFtCngBhVJPSBRRHP7NNhKEiEGFeIh3 - CgmVKaysoNp2dVmVbVuV0qIYZ9+6o7Mz05vZNcWTBF2iPHUPomN07NChm5eiwKxL1yCp - IAg8dej7zezqKIRveTvf+/39ft97RG2dpu87KUFUc0OVK6Wnbk5Ni4MfKUUd1E5YphX4 - 6WJxjLHruZK/u9fWZ9LYst7HtXb79j21lWVgIeottrcQ+iGRZgAfmZ8oZYCzwB2Wr9g+ - ATxYDqwa8COiAw+auTDT0Zx0pbItkVPmoigqr2I7Sa77+bnGvou1iYP+XI9m1o69s+qq - 0UzUtPdEobwPrkQZz19U9mw1FKcN45xIQxop8q7V3ytMxxGRKxBKBlI1ZLmfak6ddeB1 - GLtdupPj+PYQpT7JYKiJtemymR2FfQB2KsvsEPAF6PGyYg/ngXth/1tRw5PAJ2E/ZId5 - 1q0f9heuU+B7hD014M4UrsXx2oofXi0BQ/dUI2iMc03E09c5c6SI7zHUGZj3RjmmCzF3 - lqoTN4A7YR9ZqmYKsV37ruol7nsCd9PjO9GbOQtcoBxJcrEV2RTQPAlYFH2LsEkOPD7O - HlXgd6iYwBy5idzNKPce1REbZ6NSgVZ6jVfGT+O58cX4ZWwYz4B+rHbXe3z/6eMVdde2 - Pjz5jXrcOa69nRtVYVZxZQvd/8cyhI/ZJzmmwdOhWVhr2HbkD5rMTLAMKMR/BT6X+pIT - VdzV7u24RRLMUD4sbCW6S1RuKdTqPYNKrBwr2AB2cJLELFocuFNrujl4d9giem35TVey - 64b++vZ6+9ryHm3KqCkoE82zRGaUsVuj5N142/1mkRGfODq+572KWsn+SUUQP4U5Wiry - FFX0VlDWxG9nDn4btn5cP6Xn9UH9PAk9rZ/Rr+ijEb4MdEnPwnNRH6NJ8LBpIeISoIqD - M9ROVGONA+Ip8fK0W2SR/Q9AGf1mCmVuZHN0cmVhbQplbmRvYmoKMTIgMCBvYmoKNzA0 - CmVuZG9iago5IDAgb2JqClsgL0lDQ0Jhc2VkIDExIDAgUiBdCmVuZG9iagoxMyAwIG9i - ago8PCAvTGVuZ3RoIDE0IDAgUiAvTiAzIC9BbHRlcm5hdGUgL0RldmljZVJHQiAvRmls - dGVyIC9GbGF0ZURlY29kZSA+PgpzdHJlYW0KeAGFVM9rE0EU/jZuqdAiCFprDrJ4kCJJ - WatoRdQ2/RFiawzbH7ZFkGQzSdZuNuvuJrWliOTi0SreRe2hB/+AHnrwZC9KhVpFKN6r - KGKhFy3xzW5MtqXqwM5+8943731vdt8ADXLSNPWABOQNx1KiEWlsfEJq/IgAjqIJQTQl - VdvsTiQGQYNz+Xvn2HoPgVtWw3v7d7J3rZrStpoHhP1A4Eea2Sqw7xdxClkSAog836Ep - x3QI3+PY8uyPOU55eMG1Dys9xFkifEA1Lc5/TbhTzSXTQINIOJT1cVI+nNeLlNcdB2lu - ZsbIEL1PkKa7zO6rYqGcTvYOkL2d9H5Os94+wiHCCxmtP0a4jZ71jNU/4mHhpObEhj0c - GDX0+GAVtxqp+DXCFF8QTSeiVHHZLg3xmK79VvJKgnCQOMpkYYBzWkhP10xu+LqHBX0m - 1xOv4ndWUeF5jxNn3tTd70XaAq8wDh0MGgyaDUhQEEUEYZiwUECGPBoxNLJyPyOrBhuT - ezJ1JGq7dGJEsUF7Ntw9t1Gk3Tz+KCJxlEO1CJL8Qf4qr8lP5Xn5y1yw2Fb3lK2bmrry - 4DvF5Zm5Gh7X08jjc01efJXUdpNXR5aseXq8muwaP+xXlzHmgjWPxHOw+/EtX5XMlymM - FMXjVfPqS4R1WjE3359sfzs94i7PLrXWc62JizdWm5dn/WpI++6qvJPmVflPXvXx/GfN - xGPiKTEmdornIYmXxS7xkthLqwviYG3HCJ2VhinSbZH6JNVgYJq89S9dP1t4vUZ/DPVR - lBnM0lSJ93/CKmQ0nbkOb/qP28f8F+T3iuefKAIvbODImbptU3HvEKFlpW5zrgIXv9F9 - 8LZua6N+OPwEWDyrFq1SNZ8gvAEcdod6HugpmNOWls05Uocsn5O66cpiUsxQ20NSUtcl - 12VLFrOZVWLpdtiZ0x1uHKE5QvfEp0plk/qv8RGw/bBS+fmsUtl+ThrWgZf6b8C8/UUK - ZW5kc3RyZWFtCmVuZG9iagoxNCAwIG9iago3MzcKZW5kb2JqCjggMCBvYmoKWyAvSUND - QmFzZWQgMTMgMCBSIF0KZW5kb2JqCjQgMCBvYmoKPDwgL1R5cGUgL1BhZ2VzIC9NZWRp - YUJveCBbMCAwIDYxMiA3OTJdIC9Db3VudCAxIC9LaWRzIFsgMyAwIFIgXSA+PgplbmRv - YmoKMTUgMCBvYmoKPDwgL1R5cGUgL0NhdGFsb2cgL091dGxpbmVzIDIgMCBSIC9QYWdl - cyA0IDAgUiA+PgplbmRvYmoKMiAwIG9iago8PCAvTGFzdCAxNiAwIFIgL0ZpcnN0IDE3 - IDAgUiA+PgplbmRvYmoKMTcgMCBvYmoKPDwgL1BhcmVudCAxOCAwIFIgL0NvdW50IDAg - L0Rlc3QgWyAzIDAgUiAvWFlaIDAgNzMzIDAgXSAvVGl0bGUgKENhbnZhcyAxKQo+Pgpl - bmRvYmoKMTggMCBvYmoKPDwgPj4KZW5kb2JqCjE2IDAgb2JqCjw8IC9QYXJlbnQgMTgg - MCBSIC9Db3VudCAwIC9EZXN0IFsgMyAwIFIgL1hZWiAwIDczMyAwIF0gL1RpdGxlIChD - YW52YXMgMSkKPj4KZW5kb2JqCjE5IDAgb2JqCjw8IC9MZW5ndGggMjAgMCBSIC9MZW5n - dGgxIDEwMzI0IC9GaWx0ZXIgL0ZsYXRlRGVjb2RlID4+CnN0cmVhbQp4Ab16CXhU1dn/ - e+4y986Syez7ZOZmMlv2hWwmkEvIBgQMCUKCBBMgkLDIYoiECg0tfEhUXICI2NaiLbJo - GUKUAdSP2ijaTbTu21crtH59mr/994/WKpn53nsnSSHPVx+f5+/Te+c957xnfc/vvOc9 - y53ujZs6IAn6gIaGRe3rV4D8BJ4AIEeWrW1fn+CNPPrRZT3d3gTPhgDoNSvWr1yb4Pl9 - ACr3yjW9Y+WNfwEwNHR2tC9PpMNV9Is6MSLBkynop3Wu7d6c4A1D6M9fs27ZWLrxPPKZ - a9s3j7UP7yPvvbV9bQf6+ATuRCdt/brbumUWAuXo16/f2DGWnzSjfK8AwVgzrAMlrAYO - KNDh2wrAfaJyA4OpUjo+yzPVe29JLv8M9FI3AW6Zc6/svyg88+YXHVeD6vv5f2CEcjy/ - 5CvCsTCAhmD6iPr+iRS5HDrmKDRlRGEmUgVSIVJGxnQb9JHDcB/Sj5Fo6CJ3QS/SbqSH - kJiJ0FHkzpC7BhlePEt6wUFmiWrGM99k99hUas9rUaIY+pHnHdvH54gdR+8jYh9MAuV0 - FfkxeQSWg4f8FPxkC9RBiBw8FV7jacOko7AeqQ+Jll1Cjg6m5HueI5ngZwiWCUAKQ572 - /Ckvy3M5L0qRQc/zwSiD3s9TkBOTPefdP/L8p3ul5zmk44mkY2HM8bTnqHuNZ29KlBwc - 9DzgjhIsc3/C2+TGok971oYHPMvz5PT6gSh1fNBTiukLRLWnqETwFLoveXKCUZ4gn+Wu - 96Tn/caThgUxmxcr9Yt6j8u913MDJqW4q4M3IJ0jx8jDkE4eHvTP8pzFIHb31MxwyUCU - fOdUXSjPHyVbxKK60EC4LugP13v84ZpgEMMLXuJ2cDdz07l8LoMLcQFO4JyciTfwOl7L - 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 - JvHy/+2uaX/TpPTbJf5/AO1vi8oKZW5kc3RyZWFtCmVuZG9iagoyMCAwIG9iago2NzYy - CmVuZG9iagoyMSAwIG9iago8PCAvVHlwZSAvRm9udERlc2NyaXB0b3IgL0FzY2VudCA3 - NzAgL0NhcEhlaWdodCA3MTcgL0Rlc2NlbnQgLTIzMCAvRmxhZ3MgMzIKL0ZvbnRCQm94 - IFstOTUxIC00ODEgMTQ0NSAxMTIyXSAvRm9udE5hbWUgL0VTWUxQQytIZWx2ZXRpY2Eg - L0l0YWxpY0FuZ2xlIDAKL1N0ZW1WIDAgL01heFdpZHRoIDE1MDAgL1hIZWlnaHQgNjM3 - IC9Gb250RmlsZTIgMTkgMCBSID4+CmVuZG9iagoyMiAwIG9iagpbIDMzMyAzMzMgMCAw - IDAgMCAwIDAgNTU2IDU1NiA1NTYgNTU2IDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAg - MCAwIDAgMCAwCjAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDcyMiAwIDAgMCAwIDAgMCAw - IDAgMCAwIDAgMCAwIDAgNTU2IDAgMCA1NTYgNTU2IDAKMCAwIDIyMiAwIDAgMjIyIDAg - NTU2IDU1NiA1NTYgMCAzMzMgNTAwIDI3OCA1NTYgMCA3MjIgXQplbmRvYmoKMTAgMCBv - YmoKPDwgL1R5cGUgL0ZvbnQgL1N1YnR5cGUgL1RydWVUeXBlIC9CYXNlRm9udCAvRVNZ - TFBDK0hlbHZldGljYSAvRm9udERlc2NyaXB0b3IKMjEgMCBSIC9XaWR0aHMgMjIgMCBS - IC9GaXJzdENoYXIgNDAgL0xhc3RDaGFyIDExOSAvRW5jb2RpbmcgL01hY1JvbWFuRW5j - b2RpbmcKPj4KZW5kb2JqCjIzIDAgb2JqCihNYWMgT1MgWCAxMC42LjggUXVhcnR6IFBE - RkNvbnRleHQpCmVuZG9iagoyNCAwIG9iagooRDoyMDEyMDUzMDE3MzIyN1owMCcwMCcp - CmVuZG9iagoxIDAgb2JqCjw8IC9Qcm9kdWNlciAyMyAwIFIgL0NyZWF0aW9uRGF0ZSAy - NCAwIFIgL01vZERhdGUgMjQgMCBSID4+CmVuZG9iagp4cmVmCjAgMjUKMDAwMDAwMDAw - MCA2NTUzNSBmIAowMDAwMDExMTc3IDAwMDAwIG4gCjAwMDAwMDMzMzMgMDAwMDAgbiAK - MDAwMDAwMTIxMCAwMDAwMCBuIAowMDAwMDAzMTg0IDAwMDAwIG4gCjAwMDAwMDAwMjIg - MDAwMDAgbiAKMDAwMDAwMTE5MCAwMDAwMCBuIAowMDAwMDAxMzE0IDAwMDAwIG4gCjAw - MDAwMDMxNDggMDAwMDAgbiAKMDAwMDAwMjI1MiAwMDAwMCBuIAowMDAwMDEwOTA4IDAw - MDAwIG4gCjAwMDAwMDE0MjQgMDAwMDAgbiAKMDAwMDAwMjIzMiAwMDAwMCBuIAowMDAw - MDAyMjg4IDAwMDAwIG4gCjAwMDAwMDMxMjggMDAwMDAgbiAKMDAwMDAwMzI2NyAwMDAw - MCBuIAowMDAwMDAzNDk2IDAwMDAwIG4gCjAwMDAwMDMzODEgMDAwMDAgbiAKMDAwMDAw - MzQ3NCAwMDAwMCBuIAowMDAwMDAzNTg5IDAwMDAwIG4gCjAwMDAwMTA0NDIgMDAwMDAg - biAKMDAwMDAxMDQ2MyAwMDAwMCBuIAowMDAwMDEwNjg4IDAwMDAwIG4gCjAwMDAwMTEw - ODMgMDAwMDAgbiAKMDAwMDAxMTEzNSAwMDAwMCBuIAp0cmFpbGVyCjw8IC9TaXplIDI1 - IC9Sb290IDE1IDAgUiAvSW5mbyAxIDAgUiAvSUQgWyA8MzU3YTQ4YzdlOTc3NmVhYzUz - OWZlZDJmYzQ3MjUzZjY+CjwzNTdhNDhjN2U5Nzc2ZWFjNTM5ZmVkMmZjNDcyNTNmNj4g - XSA+PgpzdGFydHhyZWYKMTEyNTIKJSVFT0YKMSAwIG9iago8PC9BdXRob3IgKEpvbmF0 - aGFuIEJhY2hyYWNoKS9DcmVhdGlvbkRhdGUgKEQ6MjAxMjA1MjkyMzMxMDBaKS9DcmVh - dG9yIChPbW5pR3JhZmZsZSBQcm9mZXNzaW9uYWwgNS4zLjYpL01vZERhdGUgKEQ6MjAx - MjA1MzAxNzMyMDBaKS9Qcm9kdWNlciAyMyAwIFIgL1RpdGxlICh0cm91dGVyKT4+CmVu - ZG9iagp4cmVmCjEgMQowMDAwMDExOTEwIDAwMDAwIG4gCnRyYWlsZXIKPDwvSUQgWzwz - NTdhNDhjN2U5Nzc2ZWFjNTM5ZmVkMmZjNDcyNTNmNj4gPDM1N2E0OGM3ZTk3NzZlYWM1 - MzlmZWQyZmM0NzI1M2Y2Pl0gL0luZm8gMSAwIFIgL1ByZXYgMTEyNTIgL1Jvb3QgMTUg - MCBSIC9TaXplIDI1Pj4Kc3RhcnR4cmVmCjEyMDkyCiUlRU9GCg== - - QuickLookThumbnail - - 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 - - ReadOnly - NO - RowAlign - 1 - RowSpacing - 36 - SheetTitle - Canvas 1 - SmartAlignmentGuidesActive - YES - SmartDistanceGuidesActive - YES - UniqueID - 1 - UseEntirePage - - VPages - 1 - WindowInfo - - CurrentSheet - 0 - ExpandedCanvases - - - name - Canvas 1 - - - Frame - {{146, 4}, {1160, 874}} - ListView - - OutlineWidth - 142 - RightSidebar - - ShowRuler - - Sidebar - - SidebarWidth - 120 - VisibleRegion - {{70.5, 0}, {505.5, 352.5}} - Zoom - 2 - ZoomValues - - - Canvas 1 - 2 - 1 - - - - saveQuickLookFiles - YES - - diff --git a/doc/bootcamp/figs/trouter.pdf b/doc/bootcamp/figs/trouter.pdf deleted file mode 100644 index 72cb59dd..00000000 Binary files a/doc/bootcamp/figs/trouter.pdf and /dev/null differ diff --git a/doc/bootcamp/scala-intro.tex b/doc/bootcamp/scala-intro.tex deleted file mode 100644 index c54e6f70..00000000 --- a/doc/bootcamp/scala-intro.tex +++ /dev/null @@ -1,198 +0,0 @@ -\begin{frame}[fragile]{Scala Bindings} -\begin{scala} -// constant -val x = 1 -val (x, y) = (1, 2) - -// variable -var y = 2 -y = 3 -\end{scala} -\end{frame} - -\begin{frame}[fragile]{Scala Collections} -\begin{scala} -// Array's -val tbl = new Array[Int](256) -tbl(0) = 32 -val y = tbl(0) -val n = tbl.length - -// ArrayBuffer's -import scala.collection.mutable.ArrayBuffer -val buf = new ArrayBuffer[Int]() -buf += 12 -val z = buf(0) -val l = buf.length - -// List's -val els = List(1, 2, 3) -val els2 = x :: y :: y :: Nil -val a :: b :: c :: Nil = els -val m = els.length - -// Tuple's -val (x, y, z) = (1, 2, 3) -\end{scala} -\end{frame} - -\begin{frame}[fragile]{Scala Maps and Sets} -\begin{scala} -import scala.collection.mutable.HashMap - -val vars = new HashMap[String, Int]() -vars("a") = 1 -vars("b") = 2 -vars.size -vars.contains("c") -vars.getOrElse("c", -1) -vars.keys -vars.values -\end{scala} - -\begin{scala} -import scala.collection.mutable.HashSet - -val keys = new HashSet[Int]() -keys += 1 -keys += 5 -keys.size -> 2 -keys.contains(2) -> false -\end{scala} -\end{frame} - - - -\begin{frame}[fragile]{Scala Iteration} -\begin{scala} -val tbl = new Array[Int](256) - -// loop over all indices -for (i <- 0 until tbl.length) - tbl(i) = i - -// loop of each sequence element -val tbl2 = new ArrayBuffer[Int] -for (e <- tbl) - tbl2 += 2*e - -// loop over hashmap key / values -for ((x, y) <- vars) - println("K " + x + " V " + y) -\end{scala} - -% // create second table with doubled elements -% val tbl2 = for (i <- 0 until 16) yield tbl(i)*2 -% // nested loop -% for (i <- 0 until 16; j <- 0 until 16) -% tbl(j*16 + i) = i - -\end{frame} - -\begin{frame}[fragile]{Scala Functions} -\begin{scala} -// simple scaling function, e.g., x2(3) => 6 -def x2 (x: Int) = 2 * x -\end{scala} - -\begin{scala} -// more complicated function with statements -def f (x: Int, y: Int) = { - val xy = x + y; - if (x < y) xy else -xy -} -\end{scala} -\end{frame} - -\begin{frame}[fragile]{Scala Functional} -\begin{scala} -// simple scaling function, e.g., x2(3) => 6 -def x2 (x: Int) = 2 * x -\end{scala} - -\begin{scala} -// produce list of 2 * elements, e.g., x2list(List(1, 2, 3)) => List(2, 4, 6) -def x2list (xs: List[Int]) = xs.map(x2) -\end{scala} - -\begin{scala} -// simple addition function, e.g., add(1, 2) => 3 -def add (x: Int, y: Int) = x + y -\end{scala} - -\begin{scala} -// sum all elements using pairwise reduction, e.g., sum(List(1, 2, 3)) => 6 -def sum (xs: List[Int]) = xs.foldLeft(0)(add) -\end{scala} -\end{frame} - -\begin{frame}[fragile]{Scala Object Oriented} - -\begin{scala} -class Blimp(r: Double) { - val rad = r - println("Another Blimp") -} - -new Blimp(10.0) -\end{scala} - -\begin{scala} -class Zep(h: Boolean, r: Double) extends Blimp(r) { - val isHydrogen = h -} - -new Zep(true, 100.0) -\end{scala} - -\end{frame} - -\begin{frame}[fragile]{Scala Singleton Objects} - -\begin{itemize} -\item like Java class methods -\item for top level methods -\end{itemize} -\begin{scala} -object Blimp { - var numBlimps = 0 - def apply(r: Double) = { - numBlimps += 1 - new Blimp(r) - } -} - -Blimp.numBlimps -Blimp(10.0) -\end{scala} - -\end{frame} - -% \begin{frame}[fragile]{Cloning} -% \begin{itemize} -% \item shallow copy of object -% \item user can override method to incorporate parameters -% \item \verb+this.type+ allows precise return types -% \end{itemize} -% \begin{scala} -% class Blimp(r: Double) { -% val rad = r -% override def clone(): this.type = new Blimp(r) -% } -% -% val b1 = new Blimp(10) -% val b2 = b1.clone() -% \end{scala} -% \end{frame} -% \begin{frame}[fragile]{Scala Console} -% \begin{scala} -% > scala -% scala> 1 + 2 -% => 3 -% scala> def f (x: Int) = 2 * x -% => (Int) => Int -% scala> f(4) -% => 8 -% \end{scala} -% \end{frame} -% diff --git a/doc/cheatsheet/bigduck.png b/doc/cheatsheet/bigduck.png deleted file mode 100644 index 82ee0d7f..00000000 Binary files a/doc/cheatsheet/bigduck.png and /dev/null differ diff --git a/doc/cheatsheet/cheatsheet.tex b/doc/cheatsheet/cheatsheet.tex deleted file mode 100644 index 023007fe..00000000 --- a/doc/cheatsheet/cheatsheet.tex +++ /dev/null @@ -1,464 +0,0 @@ -\documentclass[10pt,landscape]{article} -\usepackage{multicol} -\usepackage[landscape]{geometry} -\usepackage[procnames]{listings} -\usepackage[parfill]{parskip} -\usepackage{fixltx2e} -\usepackage[T1]{fontenc} -\usepackage{lmodern} -\usepackage{graphicx} - -\input{scala.tex} - -% Remove section numbering -\setcounter{secnumdepth}{0} - -\geometry{top=.75cm,left=.75cm,right=.75cm,bottom=.75cm} - - -\pagestyle{empty} -\setlength{\parskip}{0cm} - -\makeatletter -\renewcommand{\section}{\@startsection{section}{1}{0mm}% - {-0.5ex plus 4ex}% - {-0.01ex plus .01ex}%x - {\normalfont\large\bfseries}} -\renewcommand{\subsection}{\@startsection{subsection}{2}{0mm}% - {-0.5ex plus 4ex}% - {-0.01ex plus .01ex}% - {\normalfont\normalsize\bfseries}} -\renewcommand{\subsubsection}{\@startsection{subsubsection}{3}{0mm}% - {-0.01ex plus 0.01ex}% - {-0.01ex plus .01ex}% - {\normalfont\small\bfseries}} -\makeatother - -\begin{document} -\begin{multicols}{3} - -\newcommand*\ruleline[1]{\par\noindent\raisebox{.8ex}{\makebox[\linewidth]{\hrulefill\hspace{1ex}\raisebox{-.8ex}{#1}\hspace{1ex}\hrulefill}}} -\renewcommand{\tabcolsep}{.5mm} - -\ruleline{\Large{\textbf{Chisel Cheat Sheet}}} -\begin{center} -\includegraphics[scale=0.02]{bigduck} Version 0.5 (beta): \today -\end{center} - -\fbox{ \parbox{0.95\columnwidth} { -\subsection{Notation In This Document}: -\subsubsection{For Functions and Constructors}: \newline -Arguments given as \texttt{kwd:type} (name and type(s)) \newline -Arguments in brackets (\texttt{[...]}) are optional. -\subsubsection{For Operators}: \newline -\texttt{c}, \texttt{x}, \texttt{y} are Chisel \texttt{Data}; -\texttt{n}, \texttt{m} are Scala \texttt{Int} \newline -\texttt{w(x)}, \texttt{w(y)} are the widths of \texttt{x}, \texttt{y} (respectively) \newline -\texttt{minVal(x)}, \texttt{maxVal(x)} are the minimum or \newline -\phantom{x} maximum possible values of \texttt{x} -} } - -\section{Basic Chisel Constructs } \hrulefill -\subsection{Chisel Wire Operators}: \newline -\begin{tabular}{l l} -\verb$val x = UInt()$ & Allocate \verb$a$ as wire of type \verb$UInt()$ \\ -\verb$x := y$ & Assign (connect) wire \verb$y$ to wire \verb$x$ \\ -\verb$x <> y$ & Connect \verb$x$ and \verb$y$, wire directionality \\ - & is automatically inferred \\ -\end{tabular} - -\subsection{When } executes blocks conditionally by \verb$Bool$, \newline -\phantom{x} and is equivalent to Verilog \verb$if$ -\begin{scala} -when(condition1) { - // run if condition1 true and skip rest -} .elsewhen(condition2) { - // run if condition2 true and skip rest -} .unless(condition3) { - // run if condition3 false and skip rest -} .otherwise { - // run if none of the above ran -} -\end{scala} - -\subsection{Switch } executes blocks conditionally by data -\begin{scala} -switch(x) { - is(value1) { - // run if x === value1 - } is(value2) { - // run if x === value2 - } -} -\end{scala} - -\subsection{Enum } generates value literals for enumerations \newline -\verb$val s1::s2::$ ... \verb$::sn::Nil$ \newline -\verb$ = Enum(nodeType:UInt, n:Int)$ \newline -\begin{tabular}{l l l} -& \verb$s1$, \verb$s2$, ..., \verb$sn$ & will be created as \verb$nodeType$ literals \\ -& & with distinct values \\ -& \verb$nodeType$ & type of \verb$s1$, \verb$s2$, ..., \verb$sn$ \\ -& \verb$n$ & element count \\ -\end{tabular} - -\subsection{Math Helpers}: \newline -\begin{tabular}{l l} -\verb$log2Up(in:Int): Int$ & $log_2(\texttt{in})$ rounded up \\ -\verb$log2Down(in:Int): Int$ & $log_2(\texttt{in})$ rounded down \\ -\verb$isPow2(in:Int): Boolean$ & \verb$True$ if \verb$in$ is a power of 2 \\ -\end{tabular} - -\columnbreak - -\section{Basic Data Types } \hrulefill -\subsubsection{Constructors}: \newline -\verb$Bool([x:Boolean])$ \newline -\verb$Bits/UInt/SInt([x:Int/String], [width:Int])$ \newline -\begin{tabular}{l l l} -& \verb$x$ & {\em (optional)} create a literal from Scala type/ \\ -& & pased \verb$String$, or declare unassigned if missing \\ -& \verb$width$ & {\em (optional)} bit width (inferred if missing) \\ -\end{tabular} - -\subsubsection{Bits, UInt, SInt Casts}: reinterpret cast except for:\newline -\begin{tabular*}{\columnwidth}{@{\extracolsep{\fill} } l l l} -\verb$UInt$ $\rightarrow$ \verb$SInt$ & Zero-extend to SInt & \\ -\end{tabular*} - -\subsubsection{Bool Operators}: \newline -\begin{tabular*}{\columnwidth}{@{\extracolsep{\fill} } l l l} -Chisel & Explanation & Width \\ -\hline -\hline -\verb$!x$ & Logical NOT & \verb$1$ \\ -\verb$x && y$ & Logical AND & \verb$1$ \\ -\verb$x || y$ & Logical OR & \verb$1$ \\ -\end{tabular*} - -\subsubsection{Bits Operators}: \newline -\begin{tabular*}{\columnwidth}{@{\extracolsep{\fill} } l l l} -Chisel & Explanation & Width \\ -\hline -\hline -\verb$x(n)$ & Extract bit, \verb$0$ is LSB & \verb$1$ \\ -\verb$x(n, m)$ & Extract bitfield & \verb$n - m + 1$ \\ -\verb$x << y$ & Dynamic left shift & \verb$w(x) + maxVal(y)$ \\ -\verb$x >> y$ & Dynamic right shift & \verb$w(x) - minVal(y)$ \\ -\verb$x << n$ & Static left shift & \verb$w(x) + n$ \\ -\verb$x >> n$ & Static right shift & \verb$w(x) - n$ \\ -\verb$Fill(n, x)$ & Replicate \verb$x$, \verb$n$ times & \verb$n * w(x)$ \\ -\verb$Cat(x, y)$ & Concatenate bits & \verb$w(x) + w(y)$ \\ -\verb$Mux(c, x, y)$ & If \verb$c$, then \verb$x$; else \verb$y$ & \verb$max(w(x), w(y))$ \\ -\hline -\verb$~x$ & Bitwise NOT & \verb$w(x)$ \\ -\verb$x & y$ & Bitwise AND & \verb$max(w(x), w(y))$ \\ -\verb$x | y$ & Bitwise OR & \verb$max(w(x), w(y))$ \\ -\verb$x ^ y$ & Bitwise XOR & \verb$max(w(x), w(y))$ \\ -\hline -\verb$x === y$ & Equality{\small\textcolor{red}{(triple equals)}} & \verb$1$ \\ -\verb$x != y$ & Inequality & \verb$1$ \\ -\hline -\verb$andR(x)$ & AND-reduce & \verb$1$ \\ -\verb$orR(x)$ & OR-reduce & \verb$1$ \\ -\verb$xorR(x)$ & XOR-reduce & \verb$1$ \\ -\end{tabular*} - -\subsubsection{UInt, SInt Operators}: (bitwdths given for \verb$UInt$s) \newline -\begin{tabular*}{\columnwidth}{@{\extracolsep{\fill} } l l l} -Chisel & Explanation & Width \\ -\hline -\hline -\verb$x + y$ & Addition & \verb$max(w(x), w(y))$ \\ -\verb$x - y$ & Subtraction & \verb$max(w(x), w(y))$ \\ -\verb$x * y$ & Multiplication & \verb$w(x) + w(y)$ \\ -\verb$x / y$ & Division & \verb$w(x)$ \\ -\verb$x % y$ & Modulus & \verb$bits(maxVal(y) - 1)$ \\ -\hline -\verb$x > y$ & Greater than & \verb$1$ \\ -\verb$x >= y$ & Greater than or equal & \verb$1$ \\ -\verb$x < y$ & Less than & \verb$1$ \\ -\verb$x <= y$ & Less than or equal & \verb$1$ \\ -\hline -\verb$x >> y$ & Arithmetic right shift & \verb$w(x) - minVal(y)$ \\ -\verb$x >> n$ & Arithmetic right shift & \verb$w(x) - n$ \\ -\end{tabular*} - -\columnbreak - -\section{State Elements } \hrulefill\ -\subsection{Registers } retain state until updated \newline -\verb$val my_reg = Reg([outType:Data], [next:Data],$ \newline -\verb$ [init:Data])$ \newline -\begin{tabular}{l l l} -& \verb$outType$ & {\em (optional)} register type (or inferred) \\ -& \verb$next$ & {\em (optional)} update value every clock \\ -& \verb$init$ & {\em (optional)} initialization value on reset \\ -\end{tabular} -\subsubsection{Updating}: assign to latch new value on next clock: \newline -\verb$my_reg := next_val$ \newline -The last update (lexically, per clock) runs - -\subsection{Read-Write Memory } provide addressable memories \newline -\verb$val my_mem = Mem(out:Data, n:Int,$ \newline -\verb$ seqRead:Boolean)$ \newline -\begin{tabular}{l l l} -& \verb$out$ & memory element type \\ -& \verb$n$ & memory depth (elements) \\ -& \verb$seqRead$ & only update reads on clock edge \\ -\end{tabular} -\subsubsection{Using}: access elements by indexing: \newline -\verb$val readVal = my_mem(addr:UInt/Int)$ \newline -\phantom{x} for synchronous read: assign output to \verb$Reg$ \newline -\verb$mu_mem(addr:UInt/Int) := y$ - -\section{Modules } \hrulefill -\subsubsection{Defining}: subclass \verb$Module$ with elements, code: -\begin{scala} -class Accum(width:Int) extends Module { - val io = new Bundle { - val in = UInt(INPUT, width) - val out = UInt(OUTPUT, width) - } - val sum = new Reg(UInt()) - sum := sum + io.in - io.out := sum -} -\end{scala} -\subsubsection{Usage}: access elements using dot notation: \newline -\phantom{x} (code inside a \verb$Module$ is always running) -\begin{scala} -val my_module = Module(new Accum(32)) -my_module.io.in := some_data -val sum := my_module.io.out -\end{scala} - -\section{Hardware Generation } \hrulefill -\subsection{Functions } provide block abstractions for code -\subsubsection{Defining}: write Scala functions with Chisel code: -\begin{scala} -def Adder(op_a:UInt, op_b:UInt): UInt = { - op_a + op_b -} -\end{scala} -\subsubsection{Usage}: hardware is instantiated when called: -\begin{scala} -sum := Adder(UInt(1), some_data) -\end{scala} - -\subsection{If/For } can be used to control hardware generation \newline -\phantom{x} and is equivalent to Verilog \verb$generate if$/\verb$for$ - -\columnbreak - -\section{Aggregate Types } \hrulefill -\subsection{Bundle } contains \verb$Data$ types indexed by name -\subsubsection{Defining}: subclass \verb$Bundle$, define components: -\begin{scala} -class MyBundle extends Bundle { - val a = Bool() - val b = UInt(width = 32) -} -\end{scala} -\subsubsection{Constructor}: instantiate \verb$Bundle$ subclass: \newline -\verb$val my_bundle = new MyBundle()$ -\subsubsection{Inline defining}: define a \verb$Bundle$ type: -\begin{scala} -val my_bundle = new Bundle { - val a = Bool() - val b = UInt(width = 32) -} -\end{scala} -\subsubsection{Using}: access elements through dot notation: \newline -\verb$val bundleVal = my_bundle.a$ \newline -\verb$my_bundle.a := Bool(true)$ - -\subsection{Vec } is an indexable vector of \verb$Data$ types \newline -\verb$val myVec = Vec(elts:Iterable[Data])$ \newline -\begin{tabular}{l l l} -& \verb$elts$ & initial element \verb$Data$ (vector depth inferred) \\ -\end{tabular} - -\verb$val myVec = Vec.fill(n:Int) {gen:Data}$ \newline -\begin{tabular}{l l l} -& \verb$n$ & vector depth (elements) \\ -& \verb$gen$ & initial element \verb$Data$, called once per element \\ -\end{tabular} -\subsubsection{Using}: access elements by dynamic or static indexing: \newline -\verb$readVal := myVec(ind:Data/idx:Int)$ \newline -\verb$myVec(ind:Data/idx:Int) := writeVal$ -\subsubsection{Functions}: (\verb$T$ is the \verb$Vec$ element's type) \newline -\begin{tabular}{l l l} -& \verb$.forall(p:T=>Bool): Bool$ & AND-reduce \verb$p$ on all elts \\ -& \verb$.exists(p:T=>Bool): Bool$ & OR-reduce \verb$p$ on all elts \\ -& \verb$.contains(x:T): Bool$ & \verb$True$ if this contains \verb$x$ \\ -& \verb$.count(p:T=>Bool): UInt$ & count elts where \verb$p$ is \verb$True$ \\ -\end{tabular} -\begin{tabular}{l l l} -& \verb$.indexWhere(p:T=>Bool): UInt$ & \\ -& \verb$.lastIndexWhere(p:T=>Bool): UInt$ & \\ -& \verb$.onlyIndexWhere(p:T=>Bool): UInt$ & \\ -\end{tabular} - -\section{Standard Library: Function Blocks } \hrulefill -\subsection{Stateless}: \newline -\verb$PopCount(in:Bits/Seq[Bool]): UInt$ \newline -\phantom{x} Returns number of hot (= 1) bits in \verb$in$ - -\verb$Reverse(in:UInt): UInt$ \newline -\phantom{x} Reverses the bit order of \verb$in$ - -\verb$UIntToOH(in:UInt, [width:Int]): Bits$ \newline -\begin{tabular}{l l l} -& \multicolumn{2}{l}{Returns the one-hot encoding of \texttt{in}} \\ -& \verb$width$ & {\em(optional, else inferred)} output width \\ -\end{tabular} - -\verb$OHToUInt(in:Bits/Seq[Bool]): UInt$ \newline -\phantom{x} Returns the \verb$UInt$ representation of one-hot \verb$in$ - -\columnbreak - -\verb$PriorityEncoder(in:Bits/Iterable[Bool]): UInt$ \newline -\phantom{x} Returns the position the least significant \verb$1$ in \verb$in$ - -\verb$PriorityEncoderOH(in:Bits): UInt$ \newline -\phantom{x} Returns the position of the hot bit in \verb$in$ - -\verb$Mux1H(in:Iterable[(Data, Bool]): Data$ \newline -\verb$Mux1H(sel:Bits/Iterable[Bool],$ \newline -\verb$ in:Iterable[Data]): Data$ \newline -\verb$PriorityMux(in:Iterable[(Bool, Bits]): Bits$ \newline -\verb$PriorityMux(sel:Bits/Iterable[Bool],$ \newline -\verb$ in:Iterable[Bits]): Bits$ \newline -\begin{tabular}{l l l} -& \multicolumn{2}{l}{A mux tree with either a one-hot select or multiple} \\ -& \multicolumn{2}{l}{\phantom{x} selects (where the first inputs are prioritized)} \\ -& \verb$in$ & iterable of combined input and select \verb$(Bool, Bits)$ \\ -& & tuples or just mux input \verb$Bits$ \\ -& \verb$sel$ & select signals or bitvector, one per input \\ -\end{tabular} - -\subsection{Stateful}: \newline -\verb$LFSR16([increment:Bool]): UInt$ \newline -\begin{tabular}{l l l} -& \multicolumn{2}{l}{16-bit LFSR (to generate pseudorandom numbers)} \\ -& \verb$increment$ & {\em(optional, default True)} shift on next clock \\ -\end{tabular} - -\verb$ShiftRegister(in:Data, n:Int, [en:Bool]): Data$ \newline -\begin{tabular}{l l l} -& \multicolumn{2}{l}{Shift register, returns \texttt{n}-cycle delayed input \texttt{in}} \\ -& \verb$en$ & {\em(optional, default True)} enable \\ -\end{tabular} - -\section{Standard Library: Interfaces } \hrulefill -\subsection{DecoupledIO } \mbox{is a \texttt{Bundle} with a ready-valid interface} -\subsubsection{Constructor}: \newline -\verb$Decoupled(gen:Data)$ \newline -\begin{tabular}{l l l} -& \verb$gen$ & Chisel \verb$Data$ to wrap ready-valid protocol around \\ -\end{tabular} -\subsubsection{Interface}: \newline -\begin{tabular}{c c l l} -& (in) & \verb$.ready$ & ready \verb$Bool$ \\ -& (out) & \verb$.valid$ & valid \verb$Bool$ \\ -& (out) & \verb$.bits$ & data \\ -\end{tabular} - -\subsection{ValidIO } is a \verb$Bundle$ with a valid interface -\subsubsection{Constructor}: \newline -\verb$Valid(gen:Data)$ \newline -\begin{tabular}{l l l} -& \verb$gen$ & Chisel \verb$Data$ to wrap valid protocol around \\ -\end{tabular} -\subsubsection{Interface}: \newline -\begin{tabular}{c c l l} -& (out) & \verb$.valid$ & valid \verb$Bool$ \\ -& (out) & \verb$.bits$ & data \\ -\end{tabular} - -\subsection{Queue } is a \verb$Module$ providing a hardware queue -\subsubsection{Constructor}: \newline -\verb$Queue(enq:DecoupledIO, entries:Int)$ \newline -\begin{tabular}{l l l} -& \verb$enq$ & \verb$DecoupledIO$ source for the queue \\ -& \verb$entries$ & size of queue \\ -\end{tabular} -\subsubsection{Interface}: \newline -\begin{tabular}{l l l} -& \verb$.io.enq$ & \verb$DecoupledIO$ source (flipped) \\ -& \verb$.io.deq$ & \verb$DecoupledIO$ sink \\ -& \verb$.io.count$ & \verb$UInt$ count of elements in the queue \\ -\end{tabular} - -\columnbreak - -\subsection{Pipe } is a \verb$Module$ delaying input data -\subsubsection{Constructor}: \newline -\verb$Pipe(enqValid:Bool, enqBits:Data, [latency:Int])$ \newline -\verb$Pipe(enq:ValidIO, [latency:Int])$ \newline -\begin{tabular}{l l l} -& \verb$enqValid$ & input data, valid component \\ -& \verb$enqBits$ & input data, data component \\ -& \verb$enq$ & input data as \verb$ValidIO$ \\ -& \verb$latency$ & {\em(optional, default 1)} cycles to delay data by \\ -\end{tabular} -\subsubsection{Interface}: \newline -\begin{tabular}{l l l} -& \verb$.io.enq$ & \verb$ValidIO$ source (flipped) \\ -& \verb$.io.deq$ & \verb$ValidIO$ sink \\ -\end{tabular} - -\subsection{Arbiters } are \verb$Module$s connecting multiple producers\newline -\phantom{x} to one consumer \newline -\verb$Arbiter$ prioritizes lower producers \newline -\verb$RRArbiter$ runs in round-robin order -\subsubsection{Constructor}: \newline -\verb$Arbiter(gen:Data, n:Int)$ \newline -\begin{tabular}{l l l} -& \verb$gen$ & data type \\ -& \verb$n$ & number of producers \\ -\end{tabular} -\subsubsection{Interface}: \newline -\begin{tabular}{l l l} -& \verb$.io.in$ & \verb$Vec$ of \verb$DecoupledIO$ inputs (flipped) \\ -& \verb$.io.out$ & \verb$DecoupledIO$ output \\ -& \verb$.io.chosen$ & \verb$UInt$ input index on \verb$.io.out$, \\ -& & does not imply output is valid \\ -\end{tabular} - -\section{Tester } \hrulefill - -\verb$Tester$ is a class with functions for testing \verb$Module$s, connecting and communicating with a simulator: \newline -\begin{tabular*}{\columnwidth}{@{\extracolsep{\fill} } l l} -\verb$reset([n:Int])$ & reset the DUT for \verb$n$ (default 1) clocks \\ -\verb$step(n:Int$) & steps the DUT for \verb$n$ clocks \\ -\hline \end{tabular*} \begin{tabular*}{\columnwidth}{@{\extracolsep{\fill} } l l l} -\verb$poke(data:Bits, x:BigInt)$ & writes \verb$x$ to wire \verb$data$ \\ -\multicolumn{2}{l}{\texttt{poke(data:Aggregate, x:Array[BigInt])}} \\ -\multicolumn{2}{l}{\phantom{x} writes values from \texttt{x} to corresponding wires in \texttt{data}} \\ -\verb$peek(data:Bits): BigInt$ & reads from wire \verb$data$ \\ -\multicolumn{2}{l}{\texttt{peek(data:Aggregate): Array[BigInt]}} \\ -\multicolumn{2}{l}{\phantom{x} reads multiple values from source wires in \texttt{data}} \\ -\hline \end{tabular*} \begin{tabular*}{\columnwidth}{@{\extracolsep{\fill} } l l l} -\multicolumn{2}{l}{\texttt{expect(good:Boolean, msg:String): Boolean}} \\ -\multicolumn{2}{l}{\phantom{x} fails unless \texttt{good} is \texttt{True}, \texttt{msg} should describe the test} \\ -\multicolumn{2}{l}{\texttt{expect(data:Bits, target:BigInt): Boolean}} \\ -\multicolumn{2}{l}{\phantom{x} fails unless the value in wire \texttt{data} equals \texttt{target}} \\ -\end{tabular*} -\subsubsection{Defining}:\newline -Subclass \verb$Tester$ with testing code: -\begin{scala} -class MuxTester(c:Mux) extends Tester(c) { - for (sel <- 0 until 2) { - poke(c.io.sel, sel) - poke(c.io.in0, 0); poke(c.io.in1, 1) - step(1) - expect(c.io.out, sel) - } -} -\end{scala} - -\end{multicols} -\end{document} diff --git a/doc/cheatsheet/scala.tex b/doc/cheatsheet/scala.tex deleted file mode 100644 index bd00539a..00000000 --- a/doc/cheatsheet/scala.tex +++ /dev/null @@ -1,63 +0,0 @@ -% "define" Scala -\usepackage[T1]{fontenc} -\usepackage{microtype} - -\sbox0{\small\ttfamily A} -\edef\mybasewidth{\the\wd0 } - -\lstdefinelanguage{scala}{ - morekeywords={abstract,case,catch,class,def,% - do,else,extends,false,final,finally,% - for,if,implicit,import,match,mixin,% - new,null,object,override,package,% - private,protected,requires,return,sealed,% - super,this,throw,trait,true,try,% - type,val,var,while,with,yield}, - sensitive=true, - morecomment=[l]{//}, - morecomment=[n]{/*}{*/}, - morestring=[b]", - morestring=[b]', - morestring=[b]""" -} - -\usepackage{color} -\definecolor{dkgreen}{rgb}{0,0.6,0} -\definecolor{gray}{rgb}{0.5,0.5,0.5} -\definecolor{mauve}{rgb}{0.58,0,0.82} -\definecolor{light-gray}{gray}{0.75} - -% Default settings for code listings -\lstset{language=scala, - showstringspaces=false, - columns=fixed, % basewidth=\mybasewidth, - basicstyle={\small\ttfamily}, - numbers=none, - numberstyle=\footnotesize\color{gray}, - % identifierstyle=\color{red}, - keywordstyle=\color{blue}, - commentstyle=\color{dkgreen}, - stringstyle=\color{mauve}, - breakatwhitespace=true, - procnamekeys={def, val, var, class, trait, object, extends}, - procnamestyle=\ttfamily\color{red}, - frame=leftline, - rulecolor=\color{light-gray}, - xleftmargin=2mm, - aboveskip=2pt, - belowskip=2pt, -} - -\lstnewenvironment{scala} -{\lstset{language=scala}} -{} -\lstnewenvironment{cpp} -{\lstset{language=C++}} -{} -\lstnewenvironment{bash} -{\lstset{language=bash}} -{} -\lstnewenvironment{verilog} -{\lstset{language=verilog}} -{} - diff --git a/doc/cs250/cs250-1.tex b/doc/cs250/cs250-1.tex deleted file mode 100644 index 5b015706..00000000 --- a/doc/cs250/cs250-1.tex +++ /dev/null @@ -1,790 +0,0 @@ -% NOTES: -% enum slide -% difference between := and = -% link and plink pic -% filter pic -% examples of running chisel - -\documentclass[xcolor=pdflatex,dvipsnames,table]{beamer} -\usepackage{epsfig,graphicx} -\usepackage{palatino} -\usepackage{fancybox} -\usepackage{relsize} -\usepackage[procnames]{listings} - -\input{../style/scala.tex} -\input{../style/talk.tex} - -\title{Chisel @ CS250 -- Part I -- Lecture 02} -\author{Jonathan Bachrach} -\date{\today} -\institute[UC Berkeley]{EECS UC Berkeley} - -\begin{document} - -\begin{frame} -\titlepage -\end{frame} -\addtocounter{framenumber}{-1} - -% \begin{frame}[fragile]{tutorial.scala} -% \begin{scala} -% package Tutorial { -% -% import Chisel._ -% -% object Tutorial { -% def main(args: Array[String]): Unit = { -% val tut_args = args.slice(1, args.length) ++ -% Array("--targetDir", "../emulator", "--genHarness") -% args(0) match { -% case "gcd" => -% chiselMain(tut_args, () => new GCD()) -% ... -% } -% } -% } -% -% } -% \end{scala} -% \end{frame} - -\begin{frame} -\frametitle{Standard Design Methodology} -\begin{center} -\includegraphics[height=0.9\textheight]{figs/design.pdf} -\end{center} -\end{frame} - -\begin{frame} -\frametitle{Design Entry} -\begin{columns}[c] -\column{0.5\textwidth} -\begin{itemize} -\item Design circuits graphically -\item Used commonly until approximately 2002 -\item Schematics are intuitive -\item Labor intensive to produce (especially readable ones). -\item Requires a special editor tool -\item Unless hierarchy is carefully designed, schematics can be confusing and difficult to follow on large designs -\end{itemize} -\column{0.5\textwidth} -\begin{center} -\includegraphics[height=0.4\textheight]{figs/schematic-capture.pdf} -\end{center} -\end{columns} -\end{frame} - -\begin{frame}[fragile] -\frametitle{Hardware Description Languages} -\begin{columns}[c] -\column{0.45\textwidth} -\textbf{Structural Description}: connections of components with a nearly one-to-one correspondence to schematic diagram. -\begin{scala} -Decoder(output x0,x1,x2,x3; - input a,b) { - wire abar, bbar; - inv(bbar, b); - inv(abar, a); - and(x0, abar, bbar); - and(x1, abar, b ); - and(x2, a, bbar); - and(x3, a, b ); -} -\end{scala} -\column{0.45\textwidth} -\textbf{Behavioral Description}: use high-level constructs (similar to convential programming) to describe the circuit function. -\begin{scala} -Decoder(output x0,x1,x2,x3; - input a,b) { - case [a b] - 00: [x0 x1 x2 x3] = 0x1; - 01: [x0 x1 x2 x3] = 0x2; - 10: [x0 x1 x2 x3] = 0x4; - 11: [x0 x1 x2 x3] = 0x8; - endcase; -} -\end{scala} -\end{columns} -\end{frame} - -\begin{frame} - -\frametitle{Verilog Issues} -\begin{itemize} -\item Originally invented for simulation -\item Many constructs don't synthesize: ex: deassign, timing constructs -\item Others lead to mysterious results: for-loops -\item Difficult to understand synthesis implications of procedural assignments (always blocks), and blocking versus non-blocking assignments -\item In common use, most users ignore much of the language and stick to a very strict style -\item Very weak meta programming support for creating circuit generators -\item Various hacks around this over the years, ex: embedded TCL scripting -\item VHDL has much the same issues -\end{itemize} - -\end{frame} - -\begin{frame} - -\frametitle{Traditional Hardware Design Process} - -\begin{columns} - -\column{0.45\textwidth} - -\begin{center} -\includegraphics[height=0.9\textheight]{figs/traditional-static-design-process.pdf} -\end{center} - -\column{0.45\textwidth} - -\begin{center} -\includegraphics[height=0.9\textheight]{figs/traditional-generator-design-process.pdf} -\end{center} - -\end{columns} - -\end{frame} - -\begin{frame} - -\frametitle{Chisel} - -\textbf{Constructing Hardware In Scala Embedded Language} -\begin{itemize} -\item Embed a hardware-description language in Scala, using Scala's extension facilities -\item Chisel is just a set of class definitions in Scala and when you write a Chisel program you are actually writing a Scala program -\item A hardware module is just a data structure in Scala -\item Clean simple set of design construction primitives for RTL design -\item Full power of Scala for writing hardware generators -\item Different output routines can generate different types of output (C, FPGA-Verilog, ASIC-Verilog) from same hardware representation -\item Can be extended above with domain specific languages (such as declarative cache coherence specifications) -\item Can be extended below with new backends (such as quantum) -\item Open source with lots of libraries -\item Only 5200 lines of code in current version! -\end{itemize} - -\end{frame} - -\begin{frame} -\frametitle{Chisel Workflow} -\begin{center} -\includegraphics[height=0.9\textheight]{figs/workflow.pdf} -\end{center} - -\end{frame} - -\begin{frame}[fragile] -\frametitle{The Scala Programming Language} - -\begin{columns}[c] - -\column{0.75\textwidth} - -\begin{itemize} -\item Compiled to JVM -\begin{itemize} -\item Good performance -\item Great Java interoperability -\item Mature debugging, execution environments -\end{itemize} -\item Object Oriented -\begin{itemize} -\item Factory Objects, Classes -\item Traits, overloading etc -\end{itemize} -\item Functional -\begin{itemize} -\item Higher order functions -\item Anonymous functions -\item Currying etc -\end{itemize} -\item Extensible -\begin{itemize} -\item Domain Specific Languages (DSLs) -\end{itemize} -\end{itemize} - -\column{0.25\textwidth} - -\begin{center} -\includegraphics[height=0.4\textheight]{../bootcamp/figs/programming-scala.pdf} \\ -\includegraphics[height=0.4\textheight]{../bootcamp/figs/programming-in-scala.pdf} -\end{center} - -\end{columns} -\end{frame} - -\begin{frame} - -\frametitle{Chisel Hardware Design Process} - -\begin{center} -\includegraphics[height=0.9\textheight]{figs/chisel-design-process.pdf} -\end{center} - -\end{frame} - -\include{../bootcamp/scala-intro.tex} - -% \begin{frame}[fragile] -% \frametitle{Example} -% \begin{columns} -% -% \column{0.45\textwidth} -% -% \begin{footnotesize} -% \begin{scala} -% class GCD extends Module { -% val io = new Bundle { -% val a = UInt(INPUT, 16) -% val b = UInt(INPUT, 16) -% val z = UInt(OUTPUT, 16) -% val valid = Bool(OUTPUT) } -% val x = Reg(init = io.a) -% val y = Reg(init = io.b) -% when (x > y) { -% x := x - y -% } .otherwise { -% y := y - x -% } -% io.z := x -% io.valid := y === UInt(0) -% } -% \end{scala} -% \end{footnotesize} -% -% \column{0.45\textwidth} -% -% \begin{center} -% \includegraphics[width=0.9\textwidth]{figs/gcd.pdf} -% \end{center} -% -% \end{columns} -% \end{frame} - -\begin{frame}[fragile] -\frametitle{Chisel Example} -\begin{columns} - -\column{0.40\textwidth} - -\begin{footnotesize} -\begin{scala} -class Mux2 extends Module { - val io = new Bundle{ - val sel = UInt(INPUT, 1) - val in0 = UInt(INPUT, 1) - val in1 = UInt(INPUT, 1) - val out = UInt(OUTPUT, 1) - } - io.out := (io.sel & io.in1) | - (~io.sel & io.in0) -} -\end{scala} -\end{footnotesize} - -\column{0.50\textwidth} - -\begin{center} -\includegraphics[width=0.9\textwidth]{figs/mux2-component.pdf} -\end{center} - -\end{columns} -\end{frame} - -% \begin{frame}[fragile]{Scala Console} -% \begin{FramedVerb} -% \end{FramedVerb} -% \end{frame} - -\begin{frame}[fragile]{Literals} -\begin{scala} -UInt(1) // decimal 1-bit literal from Scala Int. -UInt("ha") // hexadecimal 4-bit literal from string. -UInt("o12") // octal 4-bit literal from string. -UInt("b1010") // binary 4-bit literal from string. - -SInt(5) // signed decimal 4-bit literal from Scala Int. -SInt(-8) // negative decimal 4-bit literal from Scala Int. -UInt(5) // unsigned decimal 3-bit literal from Scala Int. - -Bool(true) // Bool literals from Scala literals. -Bool(false) -\end{scala} -\end{frame} - -\begin{frame}[fragile]{Literals} -\begin{scala} -UInt("h_dead_beef") // 32-bit literal of type UInt. -UInt(1) // decimal 1-bit literal from Scala Int. -UInt("ha", 8) // hexadecimal 8-bit literal of type UInt. -UInt("o12", 6) // octal 6-bit literal of type UInt. -UInt("b1010", 12) // binary 12-bit literal of type UInt. - -SInt(5, 7) // signed decimal 7-bit literal of type SInt. -UInt(5, 8) // unsigned decimal 8-bit literal of type UInt. -\end{scala} -\end{frame} - -\begin{frame}[fragile]{Literal Node Construction} - -\begin{scala} -UInt(1) -\end{scala} - -\begin{center} -\includegraphics[height=0.7\textheight]{figs/ufix.pdf} -\end{center} - -\end{frame} - - -\begin{frame}[fragile]{Algebraic Construction} - -\begin{scala} -UInt(1) + UInt(2) -\end{scala} - -\begin{center} -\includegraphics[height=0.7\textheight]{figs/add.pdf} -\end{center} - -\end{frame} - - -\begin{frame}[fragile]{Combinational Circuits} - -\begin{scala} -(sel & in1) | (~sel & in0) -\end{scala} - -\begin{center} -\includegraphics[height=0.7\textheight]{figs/mux2-circuit.pdf} -\end{center} - -\end{frame} - -\begin{frame}[fragile]{Fan Out} - -\begin{scala} -val sel = a | b -val out = (sel & in1) | (~sel & in0) -\end{scala} - -\begin{center} -\includegraphics[height=0.7\textheight]{figs/mux2-named-sel.pdf} -\end{center} - -\end{frame} - -\begin{frame}[fragile]{Wires} - -\begin{scala} -val sel = UInt() -val out = (sel & in1) | (~sel & in0) -sel := a | b -\end{scala} - -\begin{center} -\includegraphics[width=0.9\textwidth]{figs/mux2-forward-sel.pdf} -\end{center} - -\end{frame} - -\begin{frame}[fragile]{Bitwise operators} -\textbf{Valid on UInt, SInt, Bool.} -\begin{scala} -// Bitwise-NOT -val invertedX = ~x -// Bitwise-AND -val hiBits = x & UInt("h_ffff_0000") -// Bitwise-OR -val flagsOut = flagsIn | overflow -// Bitwise-XOR -val flagsOut = flagsIn ^ toggle -\end{scala} -\end{frame} - -\begin{frame}[fragile]{Bitwise reductions} -\textbf{Valid on UInt and SInt. Returns Bool.} -\begin{scala} -// AND-reduction -val allSet = andR(x) -// OR-reduction -val anySet = orR(x) -// XOR-reduction -val parity = xorR(x) -\end{scala} -\noindent -where reduction applies the operation to all the bits. -\end{frame} - -\begin{frame}[fragile]{Equality comparison} -\textbf{Valid on UInt, SInt, and Bool. Returns Bool.} -\begin{scala} -// Equality -val equ = x === y -// Inequality -val neq = x != y -\end{scala} -\noindent -where \verb+===+ is used instead of \verb+==+ to avoid collision with Scala. -\end{frame} - -\begin{frame}[fragile]{Shifts} -\textbf{Valid on SInt and UInt.} -\begin{scala} -// Logical left shift. -val twoToTheX = SInt(1) << x -// Right shift (logical on UInt & UInt, arithmetic on SInt). -val hiBits = x >> UInt(16) -\end{scala} -\noindent -where logical is a raw shift and arithmetic performs top bit sign extension. -\end{frame} - -\begin{frame}[fragile]{Bitfield manipulation} -\textbf{Valid on SInt, UInt, and Bool.} -\begin{scala} -// Extract single bit, LSB has index 0. -val xLSB = x(0) -// Extract bit field from end to start bit pos. -val xTopNibble = x(15,12) -// Replicate a bit string multiple times. -val usDebt = Fill(3, UInt("hA")) -// Concatenates bit fields, w/ first arg on left -val float = Cat(sgn,exp,man) -\end{scala} -\end{frame} - -\begin{frame}[fragile]{Logical Operations} -\textbf{Valid on Bools. } -\begin{scala} -// Logical NOT. -val sleep = !busy -// Logical AND. -val hit = tagMatch && valid -// Logical OR. -val stall = src1busy || src2busy -// Two-input mux where sel is a Bool. -val out = Mux(sel, inTrue, inFalse) -\end{scala} -\end{frame} - -\begin{frame}[fragile]{Arithmetic operations} -\textbf{Valid on Nums: SInt and UInt. } -\begin{scala} -// Addition. -val sum = a + b -// Subtraction. -val diff = a - b -// Multiplication. -val prod = a * b -// Division. -val div = a / b -// Modulus -val mod = a % b -\end{scala} -\noindent -where \verb+SInt+ is a signed fixed-point number represented in two's complement and \verb+UInt+ is an unsigned fixed-point number. -\end{frame} - -\begin{frame}[fragile]{Arithmetic comparisons} -\textbf{Valid on Nums: SInt and UInt. Returns Bool.} -\begin{scala} -// Greater than. -val gt = a > b -// Greater than or equal. -val gte = a >= b -// Less than. -val lt = a < b -// Less than or equal. -val lte = a <= b -\end{scala} -\end{frame} - -\begin{frame}[fragile]{Bitwidth Inference} -\begin{center} -\begin{tabular}{ll} -{\bf operation} & {\bf bit width} \\ -\verb|z = x + y| & \verb+wz = max(wx, wy)+ \\ -\verb+z = x - y+ & \verb+wz = max(wx, wy)+\\ -\verb+z = x & y+ & \verb+wz = min(wx, wy)+ \\ -\verb+z = x | y+ & \verb+wz = max(wx, wy)+ \\ -\verb+z = Mux(c, x, y)+ & \verb+wz = max(wx, wy)+ \\ -\verb+z = w * y+ & \verb!wz = wx + wy! \\ -\verb+z = x << n+ & \verb!wz = wx + maxNum(n)! \\ -\verb+z = x >> n+ & \verb+wz = wx - minNum(n)+ \\ -\verb+z = Cat(x, y)+ & \verb!wz = wx + wy! \\ -\verb+z = Fill(n, x)+ & \verb+wz = wx * maxNum(n)+ \\ -% \verb+z = x < y+ & \verb+<= > >= && || != ===+ & \verb+wz = 1+ \\ -\end{tabular} -\end{center} -\end{frame} - -% \begin{frame}[fragile]{Node Class Hierarchy} -% -% \begin{center} -% \includegraphics[height=0.9\textheight]{../manual/figs/node-hierarchy.pdf} -% \end{center} -% -% \end{frame} - -\begin{frame}[fragile]{Functional Abstraction} -\begin{scala} -def mux2 (sel: UInt, in0: UInt, in1: UInt) = - (sel & in1) | (~sel & in0) - -val out = mux2(k,a,b) -\end{scala} -\begin{center} -\includegraphics[height=0.7\textheight]{figs/mux2-function.pdf} -\end{center} -\end{frame} - -\begin{frame}[fragile]{Bundles} - -\begin{columns} -\column{0.55\textwidth} -\begin{scala} -class MyFloat extends Bundle { - val sign = Bool() - val exponent = UInt(width = 8) - val significand = UInt(width = 23) -} - -val x = new MyFloat() -val xs = x.sign -\end{scala} - -\column{0.35\textwidth} - -\begin{center} -\includegraphics[height=0.9\textheight]{figs/myfloat.pdf} -\end{center} - -\end{columns} -\end{frame} - -\begin{frame}[fragile]{Vecs} -\begin{columns} -\column{0.6\textwidth} - -\begin{scala} -// Vector of 3 23-bit signed integers. -val myVec = Vec.fill(3) { SInt(width = 23) } -\end{scala} - -\begin{itemize} -\item can be used as Scala sequences -\item can also be nested into Chisel Bundles -\end{itemize} - -\column{0.3\textwidth} - -\begin{center} -\includegraphics[height=0.9\textheight]{figs/vec-3-fix.pdf} -\end{center} - -\end{columns} -\end{frame} - -\begin{frame}[fragile]{Static Vec Element Access} -\begin{scala} -val myVec = Vec.fill(3) { SInt(width = 23) } - -// Connect to one vector element chosen at elaboration time. -val sint0 = myVec(0) -val sint1 = myVec(1) -fix1 := data1 -myVec(2) := data2 -\end{scala} - -\begin{center} -\includegraphics[height=0.5\textheight]{figs/vec-3-static.pdf} -\end{center} -\end{frame} - -\begin{frame}[fragile]{Dynamic Vec Element Access} -\begin{scala} -val myVec = Vec.fill(3) { SInt(width = 23) } - -// Connect to one vector element chosen at runtime. -val out0 = myVec(addr0) -val out1 = myVec(addr1) -myVec(addr2) := data2 -\end{scala} - -\begin{center} -\includegraphics[height=0.6\textheight]{figs/vec-3-dynamic.pdf} -\end{center} -\end{frame} - -\begin{frame}[fragile]{Ports} - -\begin{columns} -\column{0.55\textwidth} - -\textbf{Data object with directions assigned to its members} - -\begin{scala} -class Decoupled extends Bundle { - val data = UInt(INPUT, 32) - val valid = Bool(OUTPUT) - val ready = Bool(INPUT) -} -\end{scala} - -\textbf{Direction assigned at instantiation time} - -\begin{scala} -class ScaleIO extends Bundle { - val in = new MyFloat().asInput - val scale = new MyFloat().asInput - val out = new MyFloat().asOutput -} -\end{scala} - -\column{0.35\textwidth} - -\begin{center} -\includegraphics[height=0.9\textheight]{figs/fifoio.pdf} -\end{center} - -\end{columns} - -\end{frame} - -\begin{frame}[fragile]{Module} - -\begin{columns} -\column{0.45\textwidth} - -\begin{itemize} -\item inherits from \verb+Module+ class, -\item contains an interface stored in a port field named \verb+io+, and -\item wires together subcircuits in its constructor. -\end{itemize} - -\begin{scala} -class Mux2 extends Module { - val io = new Bundle{ - val sel = UInt(INPUT, 1) - val in0 = UInt(INPUT, 1) - val in1 = UInt(INPUT, 1) - val out = UInt(OUTPUT, 1) - } - io.out := (io.sel & io.in1) | - (~io.sel & io.in0) -} -\end{scala} - -\column{0.45\textwidth} - -\begin{center} -\includegraphics[width=0.9\textwidth]{figs/mux2-component.pdf} -\end{center} - -\end{columns} - -\end{frame} - -\begin{frame}{Chisel Workflow} -\begin{center} -\includegraphics[height=0.9\textheight]{../bootcamp/figs/chisel-workflow.pdf} -\end{center} -\end{frame} - - - -\begin{frame}[fragile]{State Elements} - -\begin{scala} -Reg(next = in) -\end{scala} - -\begin{center} -\includegraphics[width=0.9\textwidth]{figs/reg-in.pdf} -\end{center} - -\end{frame} - -\begin{frame}[fragile]{Rising Edge} - -\begin{scala} -def risingEdge(x: Bool) = x && !Reg(next = x) -\end{scala} - -\begin{center} -\includegraphics[width=0.9\textwidth]{figs/rising-edge.pdf} -\end{center} - -\end{frame} - -\begin{frame}[fragile]{Counter} - -\begin{columns} -\column{0.6\textwidth} - -\begin{scala} -def counter(max: UInt) = { - val x = Reg(init = UInt(0, max.getWidth)) - x := Mux(x === max, UInt(0), x + UInt(1)) - x -} -\end{scala} - -\column{0.3\textwidth} - -\begin{center} -\includegraphics[height=0.9\textheight]{figs/counter.pdf} -\end{center} - -\end{columns} - -\end{frame} - -\begin{frame}[fragile]{Sequential Circuits} - -\begin{scala} -// Produce pulse every n cycles. -def pulse(n: UInt) = counter(n - UInt(1)) === UInt(0) -\end{scala} - -\begin{scala} -// Flip internal state when input true. -def toggle(p: Bool) = { - val x = Reg(init = Bool(false)) - x := Mux(p, !x, x) - x -} -\end{scala} - -\begin{scala} -// Square wave where each half cycle has given period. -def squareWave(period: UInt) = toggle(pulse(period)) -\end{scala} - -\end{frame} - -\begin{frame}[fragile]{Simple Two Step RTL Semantics} - -\begin{scala} -// reset -eval_combinational(true); -assign_next_state(true); -// execution -loop { - eval_combinational(false); - assign_next_state(false); -} -\end{scala} - -\begin{center} -\includegraphics[width=0.9\textwidth]{figs/two-phase-rtl-semantics.pdf} -\end{center} - -\end{frame} - -\end{document} diff --git a/doc/cs250/cs250-2.tex b/doc/cs250/cs250-2.tex deleted file mode 100644 index f42867d7..00000000 --- a/doc/cs250/cs250-2.tex +++ /dev/null @@ -1,1252 +0,0 @@ -% NOTES: -% enum slide -% difference between := and = -% link and plink pic -% filter pic -% examples of running chisel - -\documentclass[xcolor=pdflatex,dvipsnames,table]{beamer} -\usepackage{epsfig,graphicx} -\usepackage{palatino} -\usepackage{fancybox} -\usepackage{relsize} -\usepackage[procnames]{listings} - -\input{../style/scala.tex} -\input{../style/talk.tex} - -\title{Chisel @ CS250 -- Part II -- Lecture 07} -\author{Jonathan Bachrach} -\date{\today} -\institute[UC Berkeley]{EECS UC Berkeley} - -\begin{document} - -\begin{frame} -\titlepage -\end{frame} -\addtocounter{framenumber}{-1} - -% \begin{frame}[fragile]{Forward Declarations using Wires} -% -% \begin{scala} -% val pcPlus4 = UInt() -% val branchTarget = UInt() -% val pcNext = Mux(pcSel, branchTarget, pcPlus4) -% val pcReg = Reg(data = pcNext, resetVal = UInt(0, 32)) -% pcPlus4 := pcReg + UInt(4) -% ... -% branchTarget := addOut -% \end{scala} -% -% \begin{center} -% \includegraphics[height=0.5\textheight]{figs/forward.pdf} -% \end{center} -% -% \end{frame} - -\begin{frame}[fragile] -\frametitle{Accelerator Chisel Interface} -\begin{columns} -\column{0.45\textwidth} -{\lstset{basicstyle={\tiny\ttfamily}} -\begin{scala} -def class MemReq extends Bundle { - val cmd = UInt(width = 2) - val mtype = UInt(width = 2) - val tag = UInt(width = 9) - val addr = UInt(width = 64) - val data = UInt(width = 64) -} - -def class MemResp extends Bundle { - val cmd = UInt(width = 2) - val tag = UInt(width = 9) - val mtype = UInt(width = 2) - val data = UInt(width = 64) -} -\end{scala} -\begin{scala} -def class OpReq extends Bundle { - val code = new RoccInst() - val a = UInt(width = 64) - val b = UInt(width = 64) -} - -def class OpResp extends Bundle { - val idx = UInt(width = 5) - val data = UInt(width = 64) -} -\end{scala} - -} - -\column{0.45\textwidth} - -{\lstset{basicstyle={\tiny\ttfamily}} -\begin{scala} -def class RoccIO extends Bundle { - val busy = Bool(OUTPUT) - val isIntr = Bool(OUTPUT) - val memReq = Decoupled(new MemReq).flip - val memResp = Decoupled(new MemResp) - val opReq = Decoupled(new OpReq) - val opResp = Decoupled(new OpResp).flip -} -\end{scala} -} -\begin{center} -\includegraphics[width=0.9\textwidth]{figs/rocket-coprocessor.pdf} -\end{center} - -\end{columns} -\end{frame} - -\begin{frame}[fragile]{Accelerator Clarifications} -\begin{columns} -\column{0.45\textwidth} -\begin{itemize} -\item tags on write commands, -\item responses to write commands, -\item must keep busy asserted until all reads and writes have completed, and -\item memory system has single port with accelerator having priority -\end{itemize} -\column{0.45\textwidth} -\begin{center} -\includegraphics[width=0.9\textwidth]{figs/rocket-coprocessor.pdf} -\end{center} -\end{columns} -\end{frame} - -\begin{frame}[fragile]{What is Chisel?} -\begin{itemize} -\item Chisel is just a set of class definitions in Scala and - when you write a Chisel program you are actually writing a Scala program, -\item Chisel programs produce and manipulate a data structure in Scala using a convenient textural language layered on top of Scala, -\item Chisel makes it possible to create powerful and reusable hardware modules using modern programming language concepts, and -\item the same Chisel description can generate different types of output -\end{itemize} -\end{frame} - -\begin{frame}[fragile]{Today} -\begin{itemize} -\item conditional updates on wires, registers, and memories, -\item give you perspective, -\item roms and rams, -\item abstraction through object orientation and functional programming, -\item present how to make hierarchical modules, -\item teach you how to make reusable modules, -\item show you to even more powerful construction techniques. -\item introduce you to the standard library -\end{itemize} -\end{frame} - -\begin{frame}[fragile]{Conditional Updates} -When describing state operations, we could simply wire register inputs to combinational logic blocks, but it is often more convenient: -\begin{itemize} -\item to specify when updates to registers will occur and -\item to specify these updates spread across several separate statements -\end{itemize} - -\begin{columns} -\column{0.45\textwidth} -\begin{scala} -val r = Reg( UInt(width = 16) ) -when (c === UInt(0) ) { - r := r + UInt(1) -} -\end{scala} - -\column{0.45\textwidth} - -\begin{center} -\includegraphics[width=0.9\textwidth]{figs/conditional-increment.pdf} -\end{center} - -\end{columns} -\end{frame} - -\begin{frame}[fragile]{Conditional Updates Priority} - -\begin{scala} -when (c1) { r := Bits(1) } -when (c2) { r := Bits(2) } -\end{scala} - -\textbf{Conditional Update Order:} - -\begin{center} -\begin{tabular}{|c|c|c|l|} -\hline -\code{c1} & \code{c2} & \code{r} & \\ -\hline -0 & 0 & r & \code{r} unchanged \\ -0 & 1 & 2 & \\ -1 & 0 & 1 & \\ -1 & 1 & 2 & \code{c2} takes precedence over \code{c1} \\ -\hline -\end{tabular} -\end{center} - -\end{frame} - -\begin{frame}[fragile]{Conditional Update Synthesized Hardware} - -\begin{center} -\includegraphics[height=2in]{figs/conditional-updates.pdf} -\end{center} - -\begin{itemize} -\item Each \code{when} statement adds another level of data mux and ORs - the predicate into the enable chain and -\item the compiler effectively adds - the termination values to the end of the chain automatically. -\end{itemize} - -\end{frame} - -\begin{frame}[fragile]{Targetting Multiple Registers} - -\begin{scala} -r := Reg( init = UInt(3) ) -s := Reg( init = UInt(3) ) -when (c1) { r := UInt(1); s := UInt(1) } -when (c2) { r := UInt(2) } -\end{scala} - -leads to \code{r} and \code{s} being updated according to the -following truth table: - -{\footnotesize -\begin{center} -\begin{tabular}{|c|c|c|c|l|} -\hline -\code{c1} & \code{c2} & \code{r} & \code{s} & \\ -\hline -0 & 0 & 3 & 3 & \\ -0 & 1 & 2 & 3 & \\ -1 & 0 & 1 & 1 & \code{r} updated in \code{c2} block, \code{s} updated using default \\ -1 & 1 & 2 & 1 & \\ -\hline -\end{tabular} -\end{center} -} - -\end{frame} - -\begin{frame}[fragile]{Conditional Update Nesting} - -\begin{scala} -when (a) { when (b) { body } } -\end{scala} - -which is the same as: - -\begin{scala} -when (a && b) { body } -\end{scala} - -\end{frame} - -\begin{frame}[fragile]{Conditional Update Chaining} - -\begin{scala} -when (c1) { u1 } -.elsewhen (c2) { u2 } -.otherwise { ud } -\end{scala} - -which is the same as: - -\begin{scala} -when (c1) { u1 } -when (!c1 && c2) { u2 } -when (!(c1 || c2)) { ud } -\end{scala} - -\end{frame} - -\begin{frame}[fragile]{Switch Statement} - -\begin{scala} -switch(idx) { - is(v1) { u1 } - is(v2) { u2 } -} -\end{scala} - -which is the same as: - -\begin{scala} -when (idx === v1) { u1 } -when (idx === v2) { u2 } -\end{scala} - -\end{frame} - -% \begin{frame}[fragile]{Enums} -% \begin{scala} -% val s_even :: s_odd :: Nil = Enum(2){ UInt() } -% \end{scala} -% \end{frame} - - -\begin{frame}[fragile]{Conditional Updates Everywhere} -Conditional updates also work for -\begin{itemize} -\item wires but must have defaults and -\item for memory reads and writes as we'll see soon... -\end{itemize} - -For wires, we can do conditional updates as follows: - -\begin{scala} -val w = Bits(width = 32) -w := Bits(0) // default value -when (c1) { w := Bits(1) } -when (c2) { w := Bits(2) } -\end{scala} - -\noindent -which is the same as - -\begin{scala} -val w = Bits(width = 32) -when (Bool(true)) { w := Bits(0) } // default value -when (c1) { w := Bits(1) } -when (c2) { w := Bits(2) } -\end{scala} - -\end{frame} - -\begin{frame}[fragile]{Enums} -Enums can be defined to create a list of increasing nums. - -\begin{scala} -object Enum { - def apply[T <: UInt](type: T, n: Int): List[T] = ... -} -\end{scala} - -\begin{scala} -val s_even :: s_odd :: Nil = Enum(UInt(), 2) -\end{scala} - -\end{frame} - -\begin{frame}[fragile]{Finite State Machines} - -\begin{columns} -\column{0.65\textwidth} - -Finite state machines can now be readily defined as follows: - -\begin{scala} -class Parity extends Module { - val io = new Bundle { - val in = Bool(INPUT) - val out = Bool(OUTPUT) } - val s_even :: s_odd :: Nil = Enum(UInt(), 2) - val state = Reg(resetVal = s_even) - when (io.in) { - when (state === s_even) { state := s_odd } - .otherwise { state := s_even } - } - io.out := (state === s_odd) -} -\end{scala} - -\column{0.25\textwidth} - -\begin{center} -\includegraphics[height=0.9\textheight]{figs/parity.pdf} -\end{center} - -\end{columns} -\end{frame} - -\input{../talks/microsoft/libs-to-langs-guts.tex} - - -\begin{frame}[fragile]{ROM} - -\begin{scala} -val d = Array(UInt(1), UInt(2), UInt(4), UInt(8)) -val m = ROM(UInt(width = 32), d) -val r = m(counter(UInt(3))) -\end{scala} - -\begin{center} -\includegraphics[height=0.7\textheight]{figs/rom.pdf} -\end{center} - -\end{frame} - -\begin{frame}[fragile]{Mul Lookup Table} -\begin{columns} -\column{0.52\textwidth} - -\begin{scala} -class Mul extends Module { - val io = new Bundle { - val x = UInt(INPUT, 4) - val y = UInt(INPUT, 4) - val z = UInt(OUTPUT, 8) } - - val muls = new Array[UInt](256) - for (x <- 0 until 16; y <- 0 until 16) - muls((x << 4) | y) = UInt(x * y) - - val tbl = ROM(UInt(8), muls) - - io.z := tbl((io.x << 4) | io.y) -} -\end{scala} - -\column{0.38\textwidth} - -\begin{center} -\includegraphics[width=0.9\textwidth]{figs/muls.pdf} -\end{center} - -\end{columns} -\end{frame} - -\begin{frame}[fragile]{RAM} -RAM is supported using the \code{Mem} construct - -\begin{scala} -val m = Mem(Bits(width = 32), 32) -\end{scala} - -\noindent -where -\begin{itemize} -\item writes to Mems are positive-edge-triggered -\item reads are either combinational or positive-edge-triggered -\item ports are created by applying a \code{UInt} index -\end{itemize} -\end{frame} - -\begin{frame}[fragile]{32-entry Register File} - -\begin{scala} -val regs = Mem(Bits(width = 32), 32) -when (wrEn) { - regs(wrAddr) := wrData -} -val iDat = regs(iAddr) -val mDat = regs(mAddr) -\end{scala} - -\begin{center} -\includegraphics[height=0.55\textheight]{figs/mem.pdf} -\end{center} - -\end{frame} - -\begin{frame}[fragile]{Sequential Read Ports} -Sequential read ports are inferred when: -\begin{itemize} -\item optional parameter \code{seqRead} is set and -\item read address is a reg -\end{itemize} - -\begin{scala} -al ram1r1w = - Mem(UInt(width = 32), 1024, seqRead = true) -val reg_raddr = Reg(UInt()) -when (wen) { ram1r1w(waddr) := wdata } -when (ren) { reg_raddr := raddr } -val rdata = ram1r1w(reg_raddr) -\end{scala} - -\begin{center} -\includegraphics[height=0.4\textheight]{figs/mem-seq-read.pdf} -\end{center} - -\end{frame} - -\begin{frame}[fragile]{Single-ported SRAM} -Single-ported SRAMs can be inferred when the read and write conditions are -mutually exclusive in the same \code{when} chain - -\begin{scala} -al ram1p = - Mem(UInt(width = 32), 1024, seqRead = true) -val reg_raddr = Reg(UInt()) -when (wen) { ram1p(waddr) := wdata } -.elsewhen (ren) { reg_raddr := raddr } -val rdata = ram1p(reg_raddr) -\end{scala} - -\begin{center} -\includegraphics[height=0.5\textheight]{figs/mem-single-ported.pdf} -\end{center} - -\end{frame} - -\begin{frame}[fragile]{Mem Write Masks } -Mem also supports write masks for subword writes. -\begin{itemize} -\item A given bit is written if the corresponding mask bit is set. -\end{itemize} - -\begin{scala} -val ram = Mem(UInt(width = 32), 256) -when (wen) { ram.write(waddr, wdata, wmask) } -\end{scala} - -\end{frame} - -\begin{frame}{Prepare for Warp Speed and Be Happy} -Congratulations, you have all that you need at this point to write Chisel programs! -You can write RTL, define modules (even with recursive data types), and wire them together. -\vspace{5mm} -\begin{itemize} -\item In order to attain true hardware description power though, you need to be able to write reusable RTL, modules and interfaces. -\item This will allow you to both use and write generic module libraries and more quickly explore design space. -\item To do this, we will use modern programming techniques such as: -\begin{itemize} -\item object orientation, -\item functional programming, -\item parameterized types -\end{itemize} -\item You will be greatly rewarded for your efforts! -\end{itemize} - -\end{frame} - -\begin{frame}[fragile]{Parameterized Types in Scala} -First we need to learn about parameterized types in Scala. -We can define a generic \code{Mux} function as taking a boolean condition and \code{con} and \code{alt} arguments (corresponding to then and else expressions) of type \code{T} as follows: - -\begin{scala} -def Mux[T <: Data](c: Bool, con: T, alt: T): T = ... -\end{scala} - -\noindent -where -\begin{itemize} -\item \code{T} is required to be a subclass of \code{Data} and -\item the type of \code{con} and \code{alt} are required to match. -\end{itemize} - -\noindent -You can think of the type parameter as a way of just constraining the types of the allowable arguments. - -\end{frame} - -\begin{frame}[fragile] -\frametitle{Revisiting GCD} -\begin{columns} - -\column{0.45\textwidth} - -\begin{footnotesize} -\begin{scala} -class GCD extends Module { - val io = new Bundle { - val a = UInt(INPUT, 16) - val b = UInt(INPUT, 16) - val z = UInt(OUTPUT, 16) - val valid = Bool(OUTPUT) } - val x = Reg(init = io.a) - val y = Reg(init = io.b) - when (x > y) { - x := x - y - } .otherwise { - y := y - x - } - io.z := x - io.valid := y === UInt(0) -} -\end{scala} -\end{footnotesize} - -\column{0.45\textwidth} - -\begin{center} -\includegraphics[width=0.9\textwidth]{../talks/retreat-1/figs/gcd.pdf} -\end{center} - -\end{columns} -\note{defining modules is a matter of \\[1cm] -defining its interface and then \\[1cm] -wiring outputs to compute logic and state defined in terms of inputs. \\[1cm] -here we're defining registers and conditional updates on them. \\[1cm] -this module outputs valid true when an answer is ready.} -\end{frame} - -\begin{frame}[fragile] -\frametitle{Valid Wrapper} - -\begin{columns} - -\column{0.65\textwidth} - -\begin{footnotesize} -\begin{scala} -class Valid[T <: Data](dtype: T) extends Bundle { - val data = dtype.clone - val valid = Bool() - override def clone = new Valid(dtype) -} - -class GCD extends Module { - val io = new Bundle { - val a = UInt(INPUT, 16) - val b = UInt(INPUT, 16) - val out = new Valid(UInt(OUTPUT, 16)) - } } - ... - io.out.data := x - io.out.valid := y === UInt(0) -} - -\end{scala} -\end{footnotesize} - -\column{0.3\textwidth} - -\begin{center} -\includegraphics[width=0.9\textwidth]{../talks/retreat-1/figs/valid.pdf} -\end{center} - -\end{columns} -\note{now gcd had a valid signal on its output. \\[1cm] -we can generalize this idea by defining a wrapper class that bundles a valid with a data signal. \\[1cm] -now we can rewrite GCD using an interface using this valid wrapper for its output. } - -\end{frame} - -\begin{frame}[fragile] -\frametitle{Function Filters} - -\begin{footnotesize} -\begin{scala} -abstract class Filter[T <: Data](dtype: T) extends Module { - val io = new Bundle { - val in = new Valid(dtype).asInput - val out = new Valid(dtype).asOutput -} } - -class FunctionFilter[T <: Data](f: T => T, dtype: T) extends Filter(dtype) { - io.out.valid := io.in.valid - io.out := f(io.in) -} -\end{scala} -\end{footnotesize} - -\begin{center} -\includegraphics[height=0.4\textheight]{../talks/sketching13/figs/function-filter.pdf} -\end{center} - -\note{suppose we want to write hardware filters. \\[1cm] -one way to create a reusable filter would be \\[1cm] -to create a filter class that takes a function as argument that definines its filter operation.} - -\end{frame} - -\begin{frame}[fragile] -\frametitle{Clipping Filter} - -\begin{footnotesize} -\begin{scala} -def clippingFilter[T <: Num](limit: Int, dtype: T) = - new FunctionFilter(min(limit, max(-limit, _)), dtype) -\end{scala} -\end{footnotesize} - -\begin{center} -\includegraphics[height=0.4\textheight]{../talks/retreat-1/figs/clipping-filter.pdf} -\end{center} -\note{using this reusable substrate then it is easy to create an instance of a filter.} -\end{frame} - - -\begin{frame}[fragile] -\frametitle{Shifting Filter} - -\begin{footnotesize} -\begin{scala} -def shiftingFilter[T <: Num](shift: Int, dtype: T) = - new FunctionFilter(_ >> shift, dtype) -\end{scala} -\end{footnotesize} - -\begin{center} -\includegraphics[height=0.4\textheight]{../talks/retreat-1/figs/shifting-filter.pdf} -\end{center} -\note{and reuse it for shift filter} -\end{frame} - -\begin{frame}[fragile] -\frametitle{Chained Filter} - -\begin{footnotesize} -\begin{scala} -class ChainedFilter[T <: Num](dtype: T) extends Filter(dtype) = { - val shift = new ShiftFilter(2, dtype) - val clipper = new ClippingFilter(1 << 7, dtype) - io.in <> shift.io.in - shift.io.out <> clipper.io.in - clipper.io.out <> io.out -} -\end{scala} -% \begin{scala} -% class ChainedFilter[T <: Num](dtype: T) extends Filter(dtype) = { -% val fir = new TstFIR(dtype) -% val shift = new ShiftFilter(2, dtype) -% val clipper = new ClippingFilter(1 << 7, dtype) -% io.in <> fir.io.in -% fir.io.out <> shift.io.in -% shift.io.out <> clipper.io.in -% clipper.io.out <> io.out -% } -% \end{scala} -\end{footnotesize} - -\begin{center} -\includegraphics[height=0.4\textheight]{../talks/sketching13/figs/chained-filter2.pdf} -\end{center} -\note{and chain together...} -\end{frame} - -\begin{frame}[fragile, shrink] -\frametitle{Functional Composition} - -% \begin{itemize} -% \item natural -% \item reusable -% \item composable -% \end{itemize} -% \vskip1cm - -\begin{Large} -\begin{columns} - -\column{0.45\textwidth} -\verb+Map(ins, x => x * y)+ \\ -\begin{center} -\includegraphics[height=0.6\textheight]{../bootcamp/figs/map.pdf} \\[2cm] -\end{center} - -\column{0.45\textwidth} -\vskip2mm -\verb+Chain(n, in, x => f(x))+ \\ -\begin{center} -\includegraphics[width=0.9\textwidth]{../bootcamp/figs/chain.pdf} \\ -\end{center} - -\verb+Reduce(ins, Max)+ \\ -\begin{center} -\includegraphics[width=0.9\textwidth]{../bootcamp/figs/reduce.pdf} \\ -\end{center} - -\end{columns} - -\end{Large} -\note{the previous example showed a simple use of functional programming. \\[1cm] -Scala provides strong support for functional programming and -it turns out that functional programming is a powerful way to define hardware. \\[1cm] -for example, you can create a parallel set of blocks using map and reduce to creation reduction trees and chain to create a pipeline.} -\end{frame} - -\begin{frame}[fragile]{Generator} -\begin{footnotesize} -\begin{scala} -def delays[T <: Data](x: T, n: Int): List[T] = - if (n <= 1) List(x) else x :: taps(Reg(next = x), n-1) - -def FIR[T <: Num](hs: Seq[T], x: T): T = - (hs, delays(x, hs.length)).zipped.map( _ * _ ).reduce( _ + _ ) - -class TstFIR extends Module { - val io = new Bundle{ val x = SInt(INPUT, 8); val y = SInt(OUTPUT, 8) } - val h = Array(SInt(1), SInt(2), SInt(4)) - io.y := FIR(h, io.x) -} -\end{scala} -\end{footnotesize} -\begin{center} -\includegraphics[height=0.35\textheight]{../cs294-88/lectures/advanced-chisel/figs/inner-product-fir.png} -\end{center} -\note{as an advanced example, consider writing an FIR filter which is defined by the equation below. \\[1cm] -essentially it's a sum of products of coefficients and delayed versions of input.\\[1cm] -we can write this quite simply using map and reduce as above.} -\end{frame} - -\begin{frame}[fragile]{Interface Views} -\begin{columns} -\column{0.40\textwidth} - -\begin{scala} -class Cpu extends Module { - val io = new CpuIo() - val c = new CtlPath() - val d = new DatPath() - c.io.ctl <> d.io.ctl - c.io.dat <> d.io.dat - c.io.imem <> io.imem - d.io.imem <> io.imem - c.io.dmem <> io.dmem - d.io.dmem <> io.dmem - d.io.host <> io.host -} -\end{scala} - -\column{0.50\textwidth} - -\begin{center} -\includegraphics[width=0.9\textwidth]{../tutorial/figs/cpu.png} -\end{center} - -\end{columns} -\end{frame} - -\begin{frame}[fragile]{CPU Interfaces} -\begin{columns} -\column{0.40\textwidth} - -\begin{scala} -class RomIo extends Bundle { - val isVal = Bool(INPUT) - val raddr = UInt(INPUT, 32) - val rdata = Bits(OUTPUT, 32) -} - -class RamIo extends RomIo { - val isWr = Bool(INPUT) - val wdata = Bits(INPUT, 32) -} - -class CpathIo extends Bundle { - val imem = RomIo().flip() - val dmem = RamIo().flip() - ... } - -class DpathIo extends Bundle { - val imem = RomIo().flip() - val dmem = RamIo().flip() - ... } -\end{scala} - -\column{0.50\textwidth} - -\begin{center} -\includegraphics[width=0.9\textwidth]{../tutorial/figs/cpu.png} -\end{center} - -\end{columns} -\end{frame} - -\begin{frame}[fragile]{Partial Interface Fulfillment} -\begin{columns} -\column{0.40\textwidth} - -\begin{scala} -class Cpath extends Module { - val io = new CpathIo(); - ... - io.imem.isVal := ...; - io.dmem.isVal := ...; - io.dmem.isWr := ...; - ... -} - -class Dpath extends Module { - val io = new DpathIo(); - ... - io.imem.raddr := ...; - io.dmem.raddr := ...; - io.dmem.wdata := ...; - ... -} -\end{scala} - -\column{0.50\textwidth} - -\begin{center} -\includegraphics[width=0.9\textwidth]{../tutorial/figs/cpu.png} -\end{center} - -\end{columns} -\end{frame} - -\begin{frame}[fragile]{Multiple Partial Bulk Connections} -\begin{columns} -\column{0.40\textwidth} - -\begin{scala} -class Cpu extends Module { - val io = new CpuIo() - val c = new CtlPath() - val d = new DatPath() - c.io.ctl <> d.io.ctl - c.io.dat <> d.io.dat - c.io.imem <> io.imem - d.io.imem <> io.imem - c.io.dmem <> io.dmem - d.io.dmem <> io.dmem - d.io.host <> io.host -} -\end{scala} - -\column{0.50\textwidth} - -\begin{center} -\includegraphics[width=0.9\textwidth]{../tutorial/figs/cpu.png} -\end{center} - -\end{columns} -\end{frame} - -\begin{frame} -\begin{columns} - -\column{0.65\textwidth} - -\frametitle{Resources} -\begin{itemize} -\item Scala books -\item \url{chisel.eecs.berkeley.edu} -\item Chisel writings -\begin{itemize} -\item Chisel tutorial -\item Chisel manual -\item Chisel DAC-2012 paper -\end{itemize} -\item Chisel examples on github -\begin{itemize} -\item Sodor Processors -\item Floating Point Unit -\item Rocket Processor -\item Hwacha Vector Unit -\end{itemize} -\end{itemize} - -\column{0.25\textwidth} - -\begin{center} -\includegraphics[height=0.4\textheight]{../bootcamp/figs/programming-scala.pdf} \\ -\includegraphics[height=0.4\textheight]{../bootcamp/figs/programming-in-scala.pdf} -\end{center} - -\end{columns} -\end{frame} - -\begin{frame} -\frametitle{Standard Library in ChiselUtil.scala} -\begin{itemize} -\item Basic Utils -\item Vecs -\item Queues -\item Arbiters -% \item Crossbars -\item Structural Memory -\end{itemize} -\end{frame} - -\begin{frame}[fragile] -\frametitle{Bits Properties} -\begin{scala} -object log2Up { - def apply(in: Int): Int = if(in == 1) 1 else ceil(log(in)/log(2)).toInt -} - -object log2Down { - def apply(x : Int): Int = if (x == 1) 1 else floor(log(x)/log(2.0)).toInt -} - -object isPow2 { - def apply(in: Int): Boolean = in > 0 && ((in & (in-1)) == 0) -} - -object PopCount { - def apply(in: Seq[Bool]): UInt = ... - def apply(in: Bits): UInt = ... -} -\end{scala} -\end{frame} - -\begin{frame}[fragile] -\frametitle{Bits Functions} -\begin{itemize} -\item LFSR16 -- random number generator -\item Reverse -- reverse order of bits -\item FillInterleaved -- space out booleans into uint -\end{itemize} -\begin{scala} -object LFSR16 { - def apply(increment: Bool = Bool(true)): UInt = ... -} -object Reverse { - def apply(in: UInt): UInt = ... -} -object FillInterleaved { - def apply(n: Int, in: Bits): UInt = ... -} -\end{scala} -\end{frame} - -\begin{frame}[fragile] -\frametitle{Stateful Functions} -\begin{itemize} -\item n cycle delayed version of input signal -\end{itemize} -\begin{scala} -object ShiftRegister { - def apply[T <: Data](in: T, n: Int, en: Bool = Bool(true)): T = ... -} -\end{scala} -\begin{itemize} -\item enable driven counter with parameterized wrapping -\end{itemize} -\begin{scala} -object Counter { - def apply(cond: Bool, n: Int): (UInt, Bool) = ... -} -\end{scala} -\end{frame} - -\begin{frame}[fragile] -\frametitle{Priority Encoding Functions} -\begin{itemize} -\item UIntToOH -- returns one hot encoding of input int -\item OHToUInt -- returns int version of one hot encoding input -\item Mux1H -- builds mux tree of input vector using a one hot encoded select signal -\end{itemize} -\begin{scala} -object UIntToOH { - def apply(in: UInt, width: Int = -1): Bits = ... -} - -object OHToUInt { - def apply(in: Seq[Bool]): UInt = ... -} - -object Mux1H { - def apply[T <: Data](sel: Vec[Bool], in: Vec[T]): T = ... -} -\end{scala} -\end{frame} - -\begin{frame}[fragile] -\frametitle{Priority Mux Function} -\begin{itemize} -\item PriorityMux -- build mux tree allow multiple select signals with priority given to first select signal -\end{itemize} -\begin{scala} -object PriorityMux { - def apply[T <: Bits](in: Seq[(Bool, T)]): T = ... - def apply[T <: Bits](sel: Seq[Bool], in: Seq[T]): T = ... - def apply[T <: Bits](sel: Bits, in: Seq[T]): T = ... -} -\end{scala} -\end{frame} - -\begin{frame}[fragile] -\frametitle{Priority Encoding Functions} -\begin{itemize} -\item PriorityEncoder -- returns the bit position of the trailing 1 in the input vector - with the assumption that multiple bits of the input bit vector can be set -\item PriorityEncoderOH -- returns the bit position of the trailing 1 in the input vector - with the assumption that only one bit in the input vector can be set. -\end{itemize} -\begin{scala} -object PriorityEncoder { - def apply(in: Seq[Bool]): UInt = ... - def apply(in: Bits): UInt = ... -} - -object PriorityEncoderOH { - def apply(in: Bits): UInt = ... - def apply(in: Seq[Bool]): Seq[UInt] = ... -} -\end{scala} -\end{frame} - -\begin{frame}[fragile]{Vec Construction} -\begin{scala} -object Vec { - def apply[T <: Data](elts: Seq[T]): Vec[T] - def apply[T <: Data](elts: Vec[T]): Vec[T] - def apply[T <: Data](elt0: T, elts: T*): Vec[T] - - def fill[T <: Data](n: Int)(f: => T): Vec[T] - def tabulate[T <: Data](n: Int)(f: Int => T): Vec[T] - def tabulate[T <: Data](n1: Int, n2: Int)(f: (Int, Int) => T): Vec[Vec[T]] -} -\end{scala} -\begin{scala} -Vec(A, L, M) -Vec.fill(3){ UInt(width = 8) } ==== - Vec(UInt(width = 8), UInt(width = 8), UInt(width = 8)) -Vec.tabulate(3){ UInt(_) } ==== - Vec(UInt(0), UInt(1), UInt(2)) -val v = Vec.fill(0){ UInt(width = 8) } -for ... - v += UInt(width = 8) -\end{scala} -\end{frame} - - -\begin{frame}[fragile]{Functional Vec} -\begin{scala} -class Vec[T <: Data](val gen: () => T) - extends Data with Cloneable with BufferProxy[T] { - ... - def forall(p: T => Bool): Bool - def exists(p: T => Bool): Bool - def contains(x: T): Bool - def count(p: T => Bool): UInt - - def indexWhere(p: T => Bool): UInt - def lastIndexWhere(p: T => Bool): UInt -} -\end{scala} -\begin{scala} -Vec(K, L, M).contains(x) ==== ( x === K || x === L || x === M ) -\end{scala} -\end{frame} - - -\begin{frame}[fragile] -\frametitle{Queues} -\begin{itemize} -\item Required parameter \verb+entries+ controls depth -\item The width is determined from the inputs. -\end{itemize} -\begin{scala} -class QueueIO[T <: Data](type: T, entries: Int) extends Bundle { - val enq = Decoupled(data.clone).flip - val deq = Decoupled(data.clone) - val count = UFix(OUTPUT, log2Up(entries+1)) -} - -class Queue[T <: Data] - (type: T, entries: Int, - pipe: Boolean = false, - flow: Boolean = false - flushable: Boolean = false) - extends Module -\end{scala} -\begin{scala} -val q = new Queue(UInt(), 16) -q.io.enq <> producer.io.out -consumer.io.in <> q.io.deq -\end{scala} -\end{frame} - -\begin{frame}[fragile] -\frametitle{Pipes} -\begin{itemize} -\item delays data coming down pipeline by \verb+latency+ cycles -\item similar to \verb+ShiftRegister+ but exposes Pipe interface -\end{itemize} -\begin{scala} -class PipeIO[+T <: Data](data: T) extends Bundle { - val valid = Bool(OUTPUT) - val bits = data.clone.asOutput -} - -class Pipe[T <: Data](type: T, latency: Int = 1) extends Module -\end{scala} -\begin{scala} -val pipe = new Pipe(UInt()) -pipe.io.enq <> produce.io.out -consumer.io.in <> pipe.io.deq -\end{scala} -\end{frame} - -\begin{frame}[fragile] -\frametitle{Fixed Priority Arbiter} -\begin{itemize} -\item sequences \verb+n+ producers into 1 consumer -\item priority is given to lower producer -\end{itemize} -\begin{scala} -class ArbiterIO[T <: Data](data: T, n: Int) extends Bundle { - val in = Vec.fill(n) { Decoupled(data) }.flip - val out = Decoupled( data.clone ) - val chosen = Bits(OUTPUT, log2Up(n)) -} - -class Arbiter[T <: Data](type: T, n: Int) extends Module -\end{scala} -\begin{scala} -val arb = new Arbiter(UInt(), 2) -arb.io.in(0) <> producer0.io.out -arb.io.in(1) <> producer1.io.out -consumer.io.in <> arb.io.out -\end{scala} -\end{frame} - -\begin{frame}[fragile] -\frametitle{Round Robin Arbiter} -\begin{itemize} -\item sequences \verb+n+ producers into 1 consumer -\item producers are chosen in round robin order -\end{itemize} -\begin{scala} -class ArbiterIO[T <: Data](data: T, n: Int) extends Bundle { - val in = Vec.fill(n) { Decoupled(data) }.flip - val out = Decoupled( data.clone ) - val chosen = Bits(OUTPUT, log2Up(n)) -} - -class RRArbiter[T <: Data](type: T, n: Int) extends Module -\end{scala} -\begin{scala} -val arb = new RRArbiter(UInt(), 2) -arb.io.in(0) <> producer0.io.out -arb.io.in(1) <> producer1.io.out -consumer.io.in <> arb.io.out -\end{scala} -\end{frame} - -% \begin{frame}[fragile] -% \frametitle{Crossbar} -% \begin{itemize} -% \item Priority -% \item Round Robin -% \end{itemize} -% \end{frame} - - -\begin{frame}[fragile] -\frametitle{Structural Memory} -\begin{itemize} -\item Defined number of ports -\item Port specific accesses -\end{itemize} -\begin{scala} -class FunMem[T <: Data] - (data: T, depth: Int, numReads: Int, numWrites: Int) { - ... - def read(addr: UInt, idx: Int = 0): T = ... - def write(addr: UInt, data: T, idx: Int = 0) = ... - ... -} -\end{scala} -\begin{scala} -val cellDats = new FunMem(Bits(width = DATA_WIDTH), NUM_CELLS, 1, 1) -when (isWrite0) { - cellDats.write(ca0, dat0, 0) -} -when (isWrite1) { - cellDats.write(ca1, dat1, 1) -} -... cellDats.read(ca, 0) ... -... cellDats.read(ca, 1) ... -\end{scala} -\end{frame} - -\begin{frame}{Acknowledgements} -\begin{itemize} -\item ``What is Chisel?'' based on slides from Patrick Li -\end{itemize} -\end{frame} - -\end{document} diff --git a/doc/cs250/cs250-3.tex b/doc/cs250/cs250-3.tex deleted file mode 100644 index 478d394b..00000000 --- a/doc/cs250/cs250-3.tex +++ /dev/null @@ -1,603 +0,0 @@ -\documentclass[xcolor=pdflatex,dvipsnames,table]{beamer} -\usepackage{epsfig,graphicx} -\usepackage{palatino} -\usepackage{fancybox} -\usepackage{relsize} -\usepackage[procnames]{listings} - -\input{../style/scala.tex} -\input{../style/talk.tex} - -\title{Chisel @ CS250 -- Part III -- Lecture 8} -\author{Jonathan Bachrach} -\date{\today} -\institute[UC Berkeley]{EECS UC Berkeley} - -\begin{document} - -\begin{frame} -\titlepage -\end{frame} -\addtocounter{framenumber}{-1} - -\begin{frame}{Options for Testing Chisel Designs} -\begin{itemize} -\item testing using assert and printf in Chisel -\item testing Verilog using VCS -\item testing from within Scala -\begin{itemize} -\item test C++ executable -\item test Verilog using VCS -\end{itemize} -\item testing inside C++ simulator -\begin{itemize} -\item VCD debugging -\item manual testing from within C++ -\end{itemize} -\end{itemize} -\end{frame} - -\begin{frame}{Simulation Options} -\begin{center} -\includegraphics[height=0.9\textheight]{../talks/dac12/figs/perf.pdf} -\end{center} -\end{frame} - -\begin{frame}{Chisel Workflow} -\begin{center} -\includegraphics[height=0.9\textheight]{../bootcamp/figs/chisel-workflow.pdf} -\end{center} -\end{frame} - -\begin{frame}[fragile]{printf / sprintf} -\begin{itemize} -\item during simulation -\begin{itemize} -\item \verb+printf+ prings the formatted string to the console on rising clock edges -\item \verb+sprintf+ returns the formatted string as a bit vector -\end{itemize} -\item format specifiers are -\begin{itemize} -\item \verb+%b+ -- binary number -\item \verb+%d+ -- decimal number -\item \verb+%x+ -- hexidecimal number -\item \verb+%s+ -- string consisting of a sequence of 8-bit extended ASCII chars -\item \verb+%%+ -- specifies a literal %. -\end{itemize} -\end{itemize} -the following prints the line \verb+"0x4142 16706 AB"+ on cycles when \verb+c+ is true: -\begin{scala} -val x = Bits(0x4142) -val s1 = sprintf("%x %s", x, x); -when (c) { printf("%d %s\n", x, s1); } -\end{scala} -\end{frame} - -\begin{frame}[fragile]{assert} -\begin{itemize} -\item simulation time assertions are provided by \verb+assert+ construct -\item if assert arguments false on rising edge then -\begin{itemize} -\item an error is printed and -\item simulation terminates -\end{itemize} -\end{itemize} -the following will terminate after 10 clock cycles: -\begin{scala} -val x = Reg(init = UInt(0, 4)) -x := x + UInt(1) -assert(x < UInt(10)) -\end{scala} -\end{frame} - -\begin{frame}{Verilog Debugging} -% \begin{columns} -% \column{0.35\textwidth} -\begin{itemize} -\item produce Verilog from Chisel -\item write tests in Verilog harness -\item use waveform debugger -\end{itemize} -% \column{0.55\textwidth} -% \begin{center} -% \includegraphics[height=0.7\textheight]{figs/modelsim.png} -% \end{center} -% \end{columns} -\end{frame} - -\begin{frame}{Chisel Based Testing Overview} -\begin{columns} -\column{0.55\textwidth} -\begin{itemize} -\item tests written in Chisel -\item Chisel -\begin{itemize} -\item compiles, -\item runs, and -\item talks to DUT using pipes -\end{itemize} -\item User -\begin{itemize} -\item sets inputs + get outputs using -\begin{itemize} -\item Chisel data to get nodes and -\item tables from nodes to values -\end{itemize} -\item specifies nodes to trace -\end{itemize} -\end{itemize} - -\column{0.35\textwidth} -\begin{center} -\includegraphics[width=0.9\textwidth]{figs/chisel-testing.pdf} -\end{center} -\end{columns} -\end{frame} - -\begin{frame}[fragile]{Chisel Based Testing Details} - -\begin{columns} -\column{0.4\textwidth} -{\lstset{basicstyle={\tiny\ttfamily}} -\begin{scala} -package Tutorial -import Chisel._ - -class Combinational extends Module { - val io = new Bundle { - val x = UInt(INPUT, 16) - val y = UInt(INPUT, 16) - val z = UInt(OUTPUT, 16) } - io.z := io.x + io.y -} - -class CombinationalTests(c: Combinational) - extends Tester(c) { - val maxInt = 1 << 16 - for (i <- 0 until 10) { - val x = rnd.nextInt(maxInt) - val y = rnd.nextInt(maxInt) - poke(c.io.x, x) - poke(c.io.y, y) - step(1) - expect(c.io.z, (x + y)&(maxInt-1)) - } -} -\end{scala} -} -\column{0.5\textwidth} -{\lstset{basicstyle={\tiny\ttfamily}} -\begin{scala} -class Tester[T <: Module] - (val c: T, val isTrace: Boolean = true) { - var ok: Boolean - val rnd: Random - def reset(n: Int = 1) - def poke(data: Bits, x: BigInt) - def step(n: Int): Int - def peek(data: Bits): BigInt - def expect (data: Bits, target: BigInt): Boolean -} -\end{scala} -} -\begin{scriptsize} -users utilize: -\begin{itemize} -\item \code{poke} to set input port and state values, -\item \code{step} to execute the circuit one time unit, -\item \code{peek} to read port and state values, and -\item \code{expect} to compare peeked circuit values to expected arguments. -\end{itemize} -\end{scriptsize} - -\begin{center} -\includegraphics[width=0.8\textwidth]{../tutorial/figs/DUT.pdf} -\end{center} - -\end{columns} -\end{frame} - -\begin{frame}[fragile]{Binding Tester to Module} - -\begin{scala} -object chiselMainTest { - def apply[T <: Module] - (args: Array[String], comp: () => T)( - tester: T => Tester[T]): T -} -\end{scala} - -\noindent and used as follows: - -\begin{scala} -chiselMainTest(args ++ Array("--compile", "--test", "--genHarness"), - () => new Combinational()){ - c => new CombinationalTests(c) -} -\end{scala} - -\end{frame} - -\begin{frame}[fragile]{\code{ChiselMain*} Arguments} - -\begin{tabular}{ll} -\verb+--targetDir+ & target pathname prefix \\ -\verb+--genHarness+ & generate harness file for C++ \\ -\verb+--backend v+ & generate verilog \\ -\verb+--backend c+ & generate C++ (default)\\ -\verb+--compile+ & compiles generated C++ \\ -\verb+--test+ & generates C++ with test plumbing \\ -\verb+--vcd+ & enable vcd dumping \\ -\verb+--debug+ & put all wires in C++ class file \\ -\end{tabular} - -\end{frame} - -\begin{frame}[fragile]{Running Tests Examples} - -\begin{scala} -sbt "project tutorial" "run Combinational ... --compile --test --genHarness" -... -PASSED -\end{scala} - -or through makefile - -\begin{scala} -cd CHISEL/tutorial/emulator -make combinational -... -PASSED -\end{scala} -\end{frame} - -\begin{frame}[fragile]{Simple Decoupled Circuits Testing} -\begin{scala} -class GCDTests(c: GCD) extends Tester(c) { - val (a, b, z) = (64, 48, 16) - var t = 0 - do { - val first = if (t == 0) 1 else 0; - poke(c.io.a, a) - poke(c.io.b, b) - poke(c.io.e, first) - step(1) - t += 1 - } while (t <= 1 || peek(c.io.v) == 0) - expect(c.io.z, z) -} -\end{scala} -\end{frame} - -\begin{frame}[fragile]{Testing Coprocessor} -\begin{center} -\includegraphics[width=0.8\textwidth]{figs/rocket-coprocessor.pdf} -\end{center} -\end{frame} - -\begin{frame}[fragile]{More Powerful Decoupled Circuits} - -{\lstset{basicstyle={\scriptsize\ttfamily}} -\begin{scala} -class AdvTester[+T <: Module](val dut: T, val ios: Array[Node]) - extends Tester[T](dut, ios) { - - val preprocessors = new ArrayBuffer[Processable]() - - val postprocessors = new ArrayBuffer[Processable]() - - // like step but does pre and post processing and work - def takestep(work: => Unit = {}) = ... - - def until(pred: => Boolean, maxCycles: Int = ...)(work: => Unit): Boolean = ... - - def do_until(pred: => Boolean, maxCycles: Int = ...)(work: => Unit): Boolean = ... - - def eventually(pred: => Boolean, maxCycles: Int = ...) = - until(pred, maxCycles){ } -} -\end{scala} -} -\vfill -{\tiny by Stephen Twigg and Eric Love} -\end{frame} - -\begin{frame}[fragile]{Sources + Sinks for Testing Decoupled Circuits} -\verb+DecoupledSource+ -\begin{itemize} -\item queue from tester to DUT -\item tester enqueues data onto queue -\item handlers moving data from queue to decoupled interface -\item can use \verb+until+ to wait until data shows up on queue -\end{itemize} -\verb+DecoupledSink+ -\begin{itemize} -\item queue from DUT to tester -\item tester sees data on queue -\item handlers moving data from decoupled interface to queue -\item can use \verb+until+ to wait until data shows up on queue -\end{itemize} -\end{frame} - -\begin{frame}[fragile]{Decoupled Testing Coprocessor} -Imagine testing your coprocessor with AdvTester (instead of rocket core): -\begin{scala} -val commands = new DecoupledSource(dut.io.cmd, ...) -val responses = new DecoupledSink(dut.io.resp, ...) -... -defTests { - ... - commands.inputs.enqueue(TestCmd.setup(0, 1, 10)) - until(!responses.outputs.isEmpty) { } - val resp = response.outputs.dequeue() - assert(resp.data == ..., "test 1 failed: bad response") - assert(resp.rd == 10, "test 1 failed: bad rd returned") - ... -} -\end{scala} -\begin{itemize} -\item memory can also be handled in tester using Scala queues and Scala memory and a process that gets stepped to handle mem requests. -\end{itemize} -\end{frame} - -\begin{frame}[fragile]{C++ Simulator} -\begin{itemize} -\item cycle accurate simulator -\begin{itemize} -\item easy way to debug designs -\end{itemize} -\item compile chisel to one C++ class -\begin{itemize} -\item topologically sorts nodes based on dependencies -\end{itemize} -\item simulates using two phases -\begin{itemize} -\item \code{clock\_lo} for combinational -\item \code{clock\_hi} for state updates -\end{itemize} -\item using fast multiword c++ template library -\begin{itemize} -\item now though expand in chisel backend -\item use same representation -\end{itemize} -\end{itemize} -\end{frame} - -\begin{frame}[fragile]{Creating C++ Output} -In order to construct a circuit, -the user calls \code{chiselMain} from their top level \code{main} function: - -\begin{scala} -object chiselMain { - def apply[T <: Module] - (args: Array[String], comp: () => T): T -} -\end{scala} - -\noindent -which when run creates C++ files named -\code{{\it module\_name}.cpp} and \code{{\it module\_name}.h} in -the directory specified with -\code{--targetDir {\it dir\_name}} argument. - -\begin{scala} -chiselMain(Array("--backend", "c", "--targetDir", "../emulator"), - () => new GCD()) -\end{scala} - -\end{frame} - -\begin{frame}[fragile]{{\tt dat\_t}} -\begin{scala} -template -class dat_t { - public: - const static int n_words = ((w - 1) / 64) + 1; - val_t values[n_words]; - inline val_t lo_word ( void ) { return values[0]; } - ... -} - -template dat_t DAT(val_t value); -template dat_t LIT(val_t value); - -template std::string dat_to_str (dat_t val); - -std::string read_tok(FILE* f); - -template void str_to_dat(std::string str, dat_t& res); -\end{scala} -\end{frame} - -\begin{frame}[fragile]{{\tt mod\_t}} -\begin{scala} -class mod_t { - public: - std::vector< mod_t* > children; - virtual void init ( void ) { }; - virtual void clock_lo ( dat_t<1> reset ) { }; - virtual void clock_hi ( dat_t<1> reset ) { }; - virtual void print ( FILE* f ) { }; - virtual bool scan ( FILE* f ) { return true; }; - virtual void dump ( FILE* f, int t ) { }; -}; -\end{scala} -\end{frame} - -\begin{frame}[fragile]{C++ Simulator Outputs} -\begin{itemize} -\item \code{GCD.h} -- the header for the single class -\item \code{GCD.cpp} -- the implementation of the single class -\item \code{GCD-emulator.cpp} -- the harness which cycles the design -\item \code{GCD.vcd} -- produced when running design with vcd output -\end{itemize} -\end{frame} - -\begin{frame}[fragile]{GCD.h} -\begin{scala} -#include "emulator.h" - -class GCD_t : public mod_t { - public: - dat_t<1> GCD__io_v; - dat_t<16> GCD__io_b; - dat_t<1> GCD__io_e; - dat_t<16> GCD__y; - dat_t<16> GCD__y_shadow; - dat_t<16> GCD__io_a; - dat_t<16> GCD__x; - dat_t<16> GCD__x_shadow; - dat_t<16> GCD__io_z; - - void init ( val_t rand_init = 0 ); - void clock_lo ( dat_t<1> reset ); - void clock_hi ( dat_t<1> reset ); - void print ( FILE* f ); - bool scan ( FILE* f ); - void dump ( FILE* f, int t ); -}; -\end{scala} -\end{frame} - -\begin{frame}[fragile]{Name Mangling Scheme} -\begin{itemize} -\item chisel object names are mangled to -\begin{itemize} -\item maintain uniqueness and avoid name conflicts -\item maintain hierarchical membership -\item avoid problems with C++ naming convention -\end{itemize} -\item basic scheme is pathname consisting of -\begin{itemize} -\item Module name first followed by \code{\_\_} -\item hierarchy elements separated with \code{\_}'s in order with -\begin{itemize} -\item numbers for vector elements -\item names for bundle fields -\end{itemize} -\item actual object name last -\end{itemize} -\item examples -\begin{itemize} -\item \code{val io = Bundle\{ val x = UInt(width = 32) \}} produces -\begin{itemize} -\item \code{A\_\_io\_x} -\end{itemize} -\item \code{... Vec.fill(2)\{ Decoupled( Bool() ) \}} produces -\begin{itemize} -\item \code{B\_\_io\_ports\_0\_ready} -\end{itemize} -\end{itemize} -\end{itemize} -\end{frame} - -\begin{frame}[fragile]{GCD.cpp} - -{\lstset{basicstyle={\tiny\ttfamily}} -\begin{scala} -#include "GCD.h" - -void GCD_t::init ( val_t rand_init ) { - { GCD__y.values[0] = rand_init ? rand_val() & 65535 : 0; } - { GCD__x.values[0] = rand_init ? rand_val() & 65535 : 0; } -} -void GCD_t::clock_lo ( dat_t<1> reset ) { - val_t T0__w0; - ... -}; -void GCD_t::clock_hi ( dat_t<1> reset ) { - GCD__y = GCD__y_shadow; - GCD__x = GCD__x_shadow; -} -void GCD_t::print ( FILE* f ) { - fprintf(f, "%s", TO_CSTR(GCD__io_z)); - fprintf(f, "%s", " "); - fprintf(f, "%s", TO_CSTR(GCD__io_v)); - fprintf(f, "\n"); - fflush(f); -} -bool GCD_t::scan ( FILE* f ) { - str_to_dat(read_tok(f), GCD__io_a); - str_to_dat(read_tok(f), GCD__io_b); - str_to_dat(read_tok(f), GCD__io_e); - return(!feof(f)); -} -void GCD_t::dump(FILE *f, int t) { -} -\end{scala} -} -\end{frame} - -\begin{frame}[fragile]{GCD-emulator.cpp} -\begin{scala} -#include "GCD.h" -int main (int argc, char* argv[]) { - GCD_t* c = new GCD_t(); - int lim = (argc > 1) ? atoi(argv[1]) : -1; - c->init(); - for (int i = 0; i < 5; i++) { - dat_t<1> reset = LIT<1>(1); - c->clock_lo(reset); - c->clock_hi(reset); - } - for (int t = 0; lim < 0 || t < lim; t++) { - dat_t<1> reset = LIT<1>(0); - if (!c->scan(stdin)) break; - c->clock_lo(reset); - c->print(stdout); - c->clock_hi(reset); - } -} -\end{scala} -\end{frame} - -\begin{frame}[fragile]{VCD Debugging} -\begin{itemize} -\item use \code{--vcd} arg to have simulation produce VCD output -\item run your compiled C++ emulation app for a number of cycles -\begin{itemize} -\item specifying the number of cycles as a first argument -\end{itemize} -\item can view waveforms with -\begin{itemize} -\item \code{vcs} -- commercial -\item GTKWave -- open source -\end{itemize} -\item can hierarchically focus on particular signals -\item can view in a variety of formats -\end{itemize} -\end{frame} - -\begin{frame}[fragile]{Manual C++ Testing} -\begin{itemize} -\item test Chisel code by manually -\begin{itemize} -\item setting circuit inputs directly in your C++ code -\item inserting \code{printf}'s in your C++ code -\end{itemize} -\item in your c++ harness insert calls to -\begin{itemize} -\item \code{str\_to\_dat(read\_tok(f), GCD\_\_io\_a)} to set values -\item \code{TO\_CSTR(GCD\_\_io\_z)} to create string for printing -\end{itemize} -\item in your chisel code -\begin{itemize} -\item wrap nodes with \code{debug} as in \code{debug(io.z)} -\end{itemize} -\item in your \code{chiselMain} -\begin{itemize} -\item you can add \code{---debug} arg to get everything available in object -\end{itemize} -\end{itemize} -\end{frame} - - - -\begin{frame}[fragile]{Onwards} -\begin{itemize} -\item for simple tests can write test vector files -\item check out Chisel tutorial code -\end{itemize} -\end{frame} - -\end{document} diff --git a/doc/cs250/cs250.tex b/doc/cs250/cs250.tex deleted file mode 100644 index 220f909b..00000000 --- a/doc/cs250/cs250.tex +++ /dev/null @@ -1,1297 +0,0 @@ -% NOTES: -% enum slide -% difference between := and = -% link and plink pic -% filter pic -% examples of running chisel - -\documentclass[xcolor=pdflatex,dvipsnames,table]{beamer} -\usepackage{epsfig,graphicx} -\usepackage{palatino} -\usepackage{fancybox} -\usepackage{relsize} -\usepackage[procnames]{listings} - -\input{../style/scala.tex} -\input{../style/talk.tex} - -\title{Chisel @ CS250} -\author{Jonathan Bachrach} -\date{\today} -\institute[UC Berkeley]{EECS UC Berkeley} - -\begin{document} - -\begin{frame} -\titlepage -\end{frame} -\addtocounter{framenumber}{-1} - -% \begin{frame}[fragile]{tutorial.scala} -% \begin{scala} -% package Tutorial { -% -% import Chisel._ -% -% object Tutorial { -% def main(args: Array[String]): Unit = { -% val tut_args = args.slice(1, args.length) ++ -% Array("--targetDir", "../emulator", "--genHarness") -% args(0) match { -% case "gcd" => -% chiselMain(tut_args, () => new GCD()) -% ... -% } -% } -% } -% -% } -% \end{scala} -% \end{frame} - -\begin{frame} -\frametitle{Standard Design Methodology} -\begin{center} -\includegraphics[height=0.9\textheight]{figs/design.pdf} -\end{center} -\end{frame} - -\begin{frame} -\frametitle{Design Entry} -\begin{columns}[c] -\column{0.5\textwidth} -\begin{itemize} -\item Design circuits graphically -\item Used commonly until approximately 2002 -\item Schematics are intuitive -\item Labor intensive to produce (especially readable ones). -\item Requires a special editor tool -\item Unless hierarchy is carefully designed, schematics can be confusing and difficult to follow on large designs -\end{itemize} -\column{0.5\textwidth} -\begin{center} -\includegraphics[height=0.4\textheight]{figs/schematic-capture.pdf} -\end{center} -\end{columns} -\end{frame} - -\begin{frame}[fragile] -\frametitle{Hardware Description Languages} -\begin{columns}[c] -\column{0.45\textwidth} -\textbf{Structural Description}: connections of components with a nearly one-to-one correspondence to schematic diagram. -\begin{scala} -Decoder(output x0,x1,x2,x3; - input a,b) { - wire abar, bbar; - inv(bbar, b); - inv(abar, a); - and(x0, abar, bbar); - and(x1, abar, b ); - and(x2, a, bbar); - and(x3, a, b ); -} -\end{scala} -\column{0.45\textwidth} -\textbf{Behavioral Description}: use high-level constructs (similar to convential programming) to describe the circuit function. -\begin{scala} -Decoder(output x0,x1,x2,x3; - input a,b) { - case [a b] - 00: [x0 x1 x2 x3] = 0x1; - 01: [x0 x1 x2 x3] = 0x2; - 10: [x0 x1 x2 x3] = 0x4; - 11: [x0 x1 x2 x3] = 0x8; - endcase; -} -\end{scala} -\end{columns} -\end{frame} - -\begin{frame} - -\frametitle{Verilog Issues} -\begin{itemize} -\item Originally invented for simulation -\item Many constructs don't synthesize: ex: deassign, timing constructs -\item Others lead to mysterious results: for-loops -\item Difficult to understand synthesis implications of procedural assignments (always blocks), and blocking versus non-blocking assignments -\item In common use, most users ignore much of the language and stick to a very strict style -\item Very weak meta programming support for creating circuit generators -\item Various hacks around this over the years, ex: embedded TCL scripting -\item VHDL has much the same issues -\end{itemize} - -\end{frame} - -\begin{frame} - -\frametitle{Chisel} - -\textbf{Constructing Hardware In Scala Embedded Language} -\begin{itemize} -\item Embed a hardware-description language in Scala, using Scala's extension facilities -\item Chisel is just a set of class definitions in Scala and when you write a Chisel program you are actually writing a Scala program -\item A hardware module is just a data structure in Scala -\item Clean simple set of design construction primitives for RTL design -\item Full power of Scala for writing hardware generators -\item Different output routines can generate different types of output (C, FPGA-Verilog, ASIC-Verilog) from same hardware representation -\item Can be extended above with domain specific languages (such as declarative cache coherence specifications) -\item Can be extended below with new backends (such as quantum) -\item Open source with lots of libraries -\item Only 5200 lines of code in current version! -\end{itemize} - -\end{frame} - -\begin{frame} -\frametitle{Chisel Workflow} -\begin{center} -\includegraphics[height=0.9\textheight]{figs/workflow.pdf} -\end{center} - -\end{frame} - -\begin{frame}[fragile] -\frametitle{The Scala Programming Language} - -\begin{columns}[c] - -\column{0.75\textwidth} - -\begin{itemize} -\item Compiled to JVM -\begin{itemize} -\item Good performance -\item Great Java interoperability -\item Mature debugging, execution environments -\end{itemize} -\item Object Oriented -\begin{itemize} -\item Factory Objects, Classes -\item Traits, overloading etc -\end{itemize} -\item Functional -\begin{itemize} -\item Higher order functions -\item Anonymous functions -\item Currying etc -\end{itemize} -\item Extensible -\begin{itemize} -\item Domain Specific Languages (DSLs) -\end{itemize} -\end{itemize} - -\column{0.25\textwidth} - -\begin{center} -\includegraphics[height=0.4\textheight]{figs/programming-scala.pdf} \\ -\includegraphics[height=0.4\textheight]{figs/programming-in-scala.pdf} -\end{center} - -\end{columns} -\end{frame} - -\begin{frame}[fragile]{Scala Collections} -\begin{scala} -// Array's -val tbl = new Array[Int](256) -tbl(0) = 32 -val y = tbl(0) -val n = tbl.length - -// ArrayBuffer's -val buf = new ArrayBuffer[Int]() -buf += 12 -val z = buf(0) -val l = buf.length - -// List's -val els = List(1, 2, 3) -val a :: b :: c :: Nil = els -val m = els.length -\end{scala} -\end{frame} - -\begin{frame}[fragile]{Scala Iteration} -\begin{scala} -val tbl = new Array[Int](256) - -// loop over all indices -for (i <- 0 until tbl.length) - tbl(i) = i - -// loop of each sequence element -for (e <- tbl) - tbl(i) += e - -// nested loop -for (i <- 0 until 16; j <- 0 until 16) - tbl(j*16 + i) = i - -// create second table with doubled elements -val tbl2 = for (i <- 0 until 16) yield tbl(i)*2 -\end{scala} -\end{frame} - -\begin{frame}[fragile]{Scala Functional} -\begin{scala} -// simple scaling function, e.g., x2(3) => 6 -def x2 (x: Int) = 2 * x -\end{scala} - -\begin{scala} -// produce list of 2 * elements, e.g., x2list(List(1, 2, 3)) => List(2, 4, 6) -def x2list (xs: List[Int]) = xs.map(x2) -\end{scala} - -\begin{scala} -// simple addition function, e.g., add(1, 2) => 3 -def add (x: Int, y: Int) = x + y -\end{scala} - -\begin{scala} -// sum all elements using pairwise reduction, e.g., sum(List(1, 2, 3)) => 6 -def sum (xs: List[Int]) = xs.foldLeft(0)(add) -\end{scala} -\end{frame} - -\begin{frame}[fragile]{Scala Object Oriented} - -\begin{scala} -object Blimp { - var numBlimps = 0 - def apply(r: Double) = { - numBlimps += 1 - new Blimp(r) - } -} - -Blimp.numBlimps -Blimp(10.0) - -class Blimp(r: Double) { - val rad = r - println("Another Blimp") -} - -class Zep(r: Double) extends Blimp(r) -\end{scala} - -\end{frame} - -\begin{frame}[fragile]{Scala Console} -\begin{scala} -> scala -scala> 1 + 2 -=> 3 -scala> def f (x: Int) = 2 * x -=> (Int) => Int -scala> f(4) -=> 8 -\end{scala} -\end{frame} - -% \begin{frame}[fragile] -% \frametitle{Example} -% \begin{columns} -% -% \column{0.45\textwidth} -% -% \begin{footnotesize} -% \begin{scala} -% class GCD extends Component { -% val io = new Bundle { -% val a = UFix(INPUT, 16) -% val b = UFix(INPUT, 16) -% val z = UFix(OUTPUT, 16) -% val valid = Bool(OUTPUT) } -% val x = Reg(resetVal = io.a) -% val y = Reg(resetVal = io.b) -% when (x > y) { -% x := x - y -% } .otherwise { -% y := y - x -% } -% io.z := x -% io.valid := y === UFix(0) -% } -% \end{scala} -% \end{footnotesize} -% -% \column{0.45\textwidth} -% -% \begin{center} -% \includegraphics[width=0.9\textwidth]{figs/gcd.pdf} -% \end{center} -% -% \end{columns} -% \end{frame} - -\begin{frame}[fragile] -\frametitle{Chisel Example} -\begin{columns} - -\column{0.40\textwidth} - -\begin{footnotesize} -\begin{scala} -class Mux2 extends Component { - val io = new Bundle{ - val sel = Bits(INPUT, 1) - val in0 = Bits(INPUT, 1) - val in1 = Bits(INPUT, 1) - val out = Bits(OUTPUT, 1) - } - io.out := (io.sel & io.in1) | - (~io.sel & io.in0) -} -\end{scala} -\end{footnotesize} - -\column{0.50\textwidth} - -\begin{center} -\includegraphics[width=0.9\textwidth]{figs/mux2-component.pdf} -\end{center} - -\end{columns} -\end{frame} - -% \begin{frame}[fragile]{Scala Console} -% \begin{FramedVerb} -% \end{FramedVerb} -% \end{frame} - -\begin{frame}[fragile]{Literals} -\begin{scala} -Bits(1) // decimal 1-bit literal from Scala Int. -Bits("ha") // hexadecimal 4-bit literal from string. -Bits("o12") // octal 4-bit literal from string. -Bits("b1010") // binary 4-bit literal from string. - -Fix(5) // signed decimal 4-bit literal from Scala Int. -Fix(-8) // negative decimal 4-bit literal from Scala Int. -UFix(5) // unsigned decimal 3-bit literal from Scala Int. - -Bool(true) // Bool literals from Scala literals. -Bool(false) -\end{scala} -\end{frame} - -\begin{frame}[fragile]{Literals} -\begin{scala} -Bits("h_dead_beef") // 32-bit literal of type Bits. -Bits(1) // decimal 1-bit literal from Scala Int. -Bits("ha", 8) // hexadecimal 8-bit literal of type Bits. -Bits("o12", 6) // octal 6-bit literal of type Bits. -Bits("b1010", 12) // binary 12-bit literal of type Bits. - -Fix(5, 7) // signed decimal 7-bit literal of type Fix. -UFix(5, 8) // unsigned decimal 8-bit literal of type UFix. -\end{scala} -\end{frame} - -\begin{frame}[fragile]{Literal Node Construction} - -\begin{scala} -UFix(1) -\end{scala} - -\begin{center} -\includegraphics[height=0.7\textheight]{figs/ufix.pdf} -\end{center} - -\end{frame} - - -\begin{frame}[fragile]{Algebraic Construction} - -\begin{scala} -UFix(1) + UFix(1) -\end{scala} - -\begin{center} -\includegraphics[height=0.7\textheight]{figs/add.pdf} -\end{center} - -\end{frame} - - -\begin{frame}[fragile]{Combinational Circuits} - -\begin{scala} -(sel & in1) | (~sel & in0) -\end{scala} - -\begin{center} -\includegraphics[height=0.7\textheight]{figs/mux2-circuit.pdf} -\end{center} - -\end{frame} - -\begin{frame}[fragile]{Fan Out} - -\begin{scala} -val sel = a | b -val out = (sel & in1) | (~sel & in0) -\end{scala} - -\begin{center} -\includegraphics[height=0.7\textheight]{figs/mux2-named-sel.pdf} -\end{center} - -\end{frame} - -\begin{frame}[fragile]{Wires} - -\begin{scala} -val sel = Bits() -val out = (sel & in1) | (~sel & in0) -sel := a | b -\end{scala} - -\begin{center} -\includegraphics[width=0.9\textwidth]{figs/mux2-forward-sel.pdf} -\end{center} - -\end{frame} - -\begin{frame}[fragile]{Bitwise operators} -\textbf{Valid on Bits, Fix, UFix, Bool.} -\begin{scala} -// Bitwise-NOT -val invertedX = ~x -// Bitwise-AND -val hiBits = x & Bits("h_ffff_0000") -// Bitwise-OR -val flagsOut = flagsIn | overflow -// Bitwise-XOR -val flagsOut = flagsIn ^ toggle -\end{scala} -\end{frame} - -\begin{frame}[fragile]{Bitwise reductions} -\textbf{Valid on Bits, Fix, and UFix. Returns Bool.} -\begin{scala} -// AND-reduction -val allSet = andR(x) -// OR-reduction -val anySet = orR(x) -// XOR-reduction -val parity = xorR(x) -\end{scala} -\noindent -where reduction applies the operation to all the bits. -\end{frame} - -\begin{frame}[fragile]{Equality comparison} -\textbf{Valid on Bits, Fix, UFix, and Bool. Returns Bool.} -\begin{scala} -// Equality -val equ = x === y -// Inequality -val neq = x != y -\end{scala} -\noindent -where \verb+===+ is used instead of \verb+==+ to avoid collision with Scala. -\end{frame} - -\begin{frame}[fragile]{Shifts} -\textbf{Valid on Bits, Fix, and UFix.} -\begin{scala} -// Logical left shift. -val twoToTheX = Fix(1) << x -// Right shift (logical on Bits & UFix, arithmetic on Fix). -val hiBits = x >> UFix(16) -\end{scala} -\noindent -where logical is a raw shift and arithmetic performs top bit sign extension. -\end{frame} - -\begin{frame}[fragile]{Bitfield manipulation} -\textbf{Valid on Bits, Fix, UFix, and Bool.} -\begin{scala} -// Extract single bit, LSB has index 0. -val xLSB = x(0) -// Extract bit field from end to start bit pos. -val xTopNibble = x(15,12) -// Replicate a bit string multiple times. -val usDebt = Fill(3, Bits("hA")) -// Concatenates bit fields, w/ first arg on left -val float = Cat(sgn,exp,man) -\end{scala} -\end{frame} - -\begin{frame}[fragile]{Logical Operations} -\textbf{Valid on Bools. } -\begin{scala} -// Logical NOT. -val sleep = !busy -// Logical AND. -val hit = tagMatch && valid -// Logical OR. -val stall = src1busy || src2busy -// Two-input mux where sel is a Bool. -val out = Mux(sel, inTrue, inFalse) -\end{scala} -\end{frame} - -\begin{frame}[fragile]{Arithmetic operations} -\textbf{Valid on Nums: Fix and UFix. } -\begin{scala} -// Addition. -val sum = a + b -// Subtraction. -val diff = a - b -// Multiplication. -val prod = a * b -// Division. -val div = a / b -// Modulus -val mod = a % b -\end{scala} -\noindent -where \verb+Fix+ is a signed fixed-point number represented in two's complement and \verb+UFix+ is an unsigned fixed-point number. -\end{frame} - -\begin{frame}[fragile]{Arithmetic comparisons} -\textbf{Valid on Nums: Fix and UFix. Returns Bool.} -\begin{scala} -// Greater than. -val gt = a > b -// Greater than or equal. -val gte = a >= b -// Less than. -val lt = a < b -// Less than or equal. -val lte = a <= b -\end{scala} -\end{frame} - -\begin{frame}[fragile]{Bitwidth Inference} -\begin{center} -\begin{tabular}{ll} -{\bf operation} & {\bf bit width} \\ -\verb|z = x + y| & \verb+wz = max(wx, wy)+ \\ -\verb+z = x - y+ & \verb+wz = max(wx, wy)+\\ -\verb+z = x & y+ & \verb+wz = min(wx, wy)+ \\ -\verb+z = x | y+ & \verb+wz = max(wx, wy)+ \\ -\verb+z = Mux(c, x, y)+ & \verb+wz = max(wx, wy)+ \\ -\verb+z = w * y+ & \verb!wz = wx + wy! \\ -\verb+z = x << n+ & \verb!wz = wx + maxNum(n)! \\ -\verb+z = x >> n+ & \verb+wz = wx - minNum(n)+ \\ -\verb+z = Cat(x, y)+ & \verb!wz = wx + wy! \\ -\verb+z = Fill(n, x)+ & \verb+wz = wx * maxNum(n)+ \\ -% \verb+z = x < y+ & \verb+<= > >= && || != ===+ & \verb+wz = 1+ \\ -\end{tabular} -\end{center} -\end{frame} - -% \begin{frame}[fragile]{Node Class Hierarchy} -% -% \begin{center} -% \includegraphics[height=0.9\textheight]{../manual/figs/node-hierarchy.pdf} -% \end{center} -% -% \end{frame} - -\begin{frame}[fragile]{Functional Abstraction} -\begin{scala} -def mux2 (sel: Bits, in0: Bits, in1: Bits) = - (sel & in1) | (~sel & in0) - -val out = mux2(k,a,b) -\end{scala} -\begin{center} -\includegraphics[height=0.7\textheight]{figs/mux2-function.pdf} -\end{center} -\end{frame} - -\begin{frame}[fragile]{Bundles} - -\begin{columns} -\column{0.55\textwidth} -\begin{scala} -class MyFloat extends Bundle { - val sign = Bool() - val exponent = UFix(width = 8) - val significand = UFix(width = 23) -} - -val x = new MyFloat() -val xs = x.sign -\end{scala} - -\column{0.35\textwidth} - -\begin{center} -\includegraphics[height=0.9\textheight]{figs/myfloat.pdf} -\end{center} - -\end{columns} -\end{frame} - -\begin{frame}[fragile]{Vecs} -\begin{columns} -\column{0.55\textwidth} - -\begin{scala} -// Vector of 3 23-bit signed integers. -val myVec = Vec(3) { Fix(width = 23) } -\end{scala} - -\begin{itemize} -\item can be used as Scala sequences -\item can be nested into Chisel Bundles -\end{itemize} - -\column{0.35\textwidth} - -\begin{center} -\includegraphics[height=0.9\textheight]{figs/vec-3-fix.pdf} -\end{center} - -\end{columns} -\end{frame} - -\begin{frame}[fragile]{Vec Static Element Access} -\begin{scala} -val myVec = Vec(3) { Fix(width = 23) } - -// Connect to one vector element chosen at elaboration time. -val r0 = Reg(){ Fix(width = 23) } -r0 := myVec(0) -val fix1 = myVec(1) -fix1 := data1 -myVec(2) := data2 -\end{scala} - -\begin{center} -\includegraphics[height=0.5\textheight]{figs/vec-3-static.pdf} -\end{center} -\end{frame} - -\begin{frame}[fragile]{Vec Dynamic Element Access} -\begin{scala} -val myVec = Vec(3) { Fix(width = 23) } - -// Connect to one vector element chosen dynamically. -val out = myVec(addr1) -myVec(addr2) := data2 -\end{scala} - -\begin{center} -\includegraphics[height=0.6\textheight]{figs/vec-3-dynamic.pdf} -\end{center} -\end{frame} - -\begin{frame}[fragile]{Ports} - -\begin{columns} -\column{0.55\textwidth} - -\textbf{Data object with directions assigned to its members} - -\begin{scala} -class FIFOIO extends Bundle { - val bits = Bits(INPUT, 32) - val valid = Bool(OUTPUT) - val ready = Bool(INPUT) -} -\end{scala} - -\textbf{Direction assigned at instantiation time} - -\begin{scala} -class ScaleIO extends Bundle { - val in = new MyFloat().asInput - val scale = new MyFloat().asInput - val out = new MyFloat().asOutput -} -\end{scala} - -\column{0.35\textwidth} - -\begin{center} -\includegraphics[height=0.9\textheight]{figs/fifoio.pdf} -\end{center} - -\end{columns} - -\end{frame} - -\begin{frame}[fragile]{Component} - -\begin{columns} -\column{0.45\textwidth} - -\begin{itemize} -\item inherits from \verb+Component+, -\item contains an interface stored in a port field named \verb+io+, and -\item wires together subcircuits in its constructor. -\end{itemize} - -\begin{scala} -class Mux2 extends Component { - val io = new Bundle{ - val sel = Bits(INPUT, 1) - val in0 = Bits(INPUT, 1) - val in1 = Bits(INPUT, 1) - val out = Bits(OUTPUT, 1) - } - io.out := (io.sel & io.in1) | - (~io.sel & io.in0) -} -\end{scala} - -\column{0.45\textwidth} - -\begin{center} -\includegraphics[width=0.9\textwidth]{figs/mux2-component.pdf} -\end{center} - -\end{columns} - -\end{frame} - -\begin{frame}{Chisel Workflow} -\begin{center} -\includegraphics[height=0.9\textheight]{figs/chisel-workflow.pdf} -\end{center} -\end{frame} - - - -\begin{frame}[fragile]{State Elements} - -\begin{scala} -Reg(in) -\end{scala} - -\begin{center} -\includegraphics[width=0.9\textwidth]{figs/reg-in.pdf} -\end{center} - -\end{frame} - -\begin{frame}[fragile]{Rising Edge} - -\begin{scala} -def risingEdge(x: Bool) = x && !Reg(x) -\end{scala} - -\begin{center} -\includegraphics[width=0.9\textwidth]{figs/rising-edge.pdf} -\end{center} - -\end{frame} - -\begin{frame}[fragile]{Counter} - -\begin{columns} -\column{0.6\textwidth} - -\begin{scala} -def counter(max: UFix) = { - val x = Reg(resetVal = UFix(0, max.getWidth)) - x := Mux(x == max, UFix(0), x + UFix(1)) - x -} -\end{scala} - -\column{0.3\textwidth} - -\begin{center} -\includegraphics[height=0.9\textheight]{figs/counter.pdf} -\end{center} - -\end{columns} - -\end{frame} - -\begin{frame}[fragile]{Sequential Circuits} - -\begin{scala} -// Produce pulse every n cycles. -def pulse(n: UFix) = counter(n - UFix(1)) === UFix(0) -\end{scala} - -\begin{scala} -// Flip internal state when input true. -def toggle(p: Bool) = { - val x = Reg(resetVal = Bool(false)) - x := Mux(p, !x, x) - x -} -\end{scala} - -\begin{scala} -// Square wave where each half cycle has given period. -def squareWave(period: UFix) = toggle(pulse(period)) -\end{scala} - -\end{frame} - -% \begin{frame}[fragile]{Forward Declarations using Wires} -% -% \begin{scala} -% val pcPlus4 = UFix() -% val branchTarget = UFix() -% val pcNext = Mux(pcSel, branchTarget, pcPlus4) -% val pcReg = Reg(data = pcNext, resetVal = UFix(0, 32)) -% pcPlus4 := pcReg + UFix(4) -% ... -% branchTarget := addOut -% \end{scala} -% -% \begin{center} -% \includegraphics[height=0.5\textheight]{figs/forward.pdf} -% \end{center} -% -% \end{frame} - -\begin{frame}[fragile]{Conditional Updates} - -\begin{columns} -\column{0.45\textwidth} - -\begin{scala} -val r = Reg() { UFix(16) } -when (c === UFix(0) ) { - r := r + UFix(1) -} -\end{scala} - -\column{0.45\textwidth} - -\begin{center} -\includegraphics[width=0.9\textwidth]{figs/conditional-increment.pdf} -\end{center} - -\end{columns} -\end{frame} - -\begin{frame}[fragile]{Conditional Updates Priority} - -\begin{scala} -when (c1) { r := Bits(1) } -when (c2) { r := Bits(2) } -\end{scala} - -\textbf{Conditional Update Order:} - -\begin{center} -\begin{tabular}{|c|c|c|l|} -\hline -\code{c1} & \code{c2} & \code{r} & \\ -\hline -0 & 0 & r & \code{r} unchanged \\ -0 & 1 & 2 & \\ -1 & 0 & 1 & \\ -1 & 1 & 2& \code{c2} takes precedence over \code{c1} \\ -\hline -\end{tabular} -\end{center} - -\end{frame} - -\begin{frame}[fragile]{Conditional Update Synthesized Hardware} - -\begin{center} -\includegraphics[height=2in]{figs/conditional-updates.pdf} -\end{center} - -\begin{itemize} -\item Each \code{when} statement adds another level of data mux and ORs - the predicate into the enable chain and -\item the compiler effectively adds - the termination values to the end of the chain automatically. -\end{itemize} - -\end{frame} - -\begin{frame}[fragile]{Targetting Multiple Registers} - -\begin{scala} -r := Fix(3) -s := Fix(3) -when (c1) { r := Fix(1); s := Fix(1) } -when (c2) { r := Fix(2) } -\end{scala} - -leads to \code{r} and \code{s} being updated according to the -following truth table: - -{\footnotesize -\begin{center} -\begin{tabular}{|c|c|c|c|l|} -\hline -\code{c1} & \code{c2} & \code{r} & \code{s} & \\ -\hline -0 & 0 & 3 & 3 & \\ -0 & 1 & 2 & 3 & \\ -1 & 0 & 1 & 1 & \code{r} updated in \code{c2} block, \code{s} updated using default \\ -1 & 1 & 2 & 1 & \\ -\hline -\end{tabular} -\end{center} -} - - -\end{frame} - -\begin{frame}[fragile]{Conditional Update Nesting} - -\begin{scala} -when (a) { when (b) { body } } -\end{scala} - -which is the same as: - -\begin{scala} -when (a && b) { body } -\end{scala} - -\end{frame} - -\begin{frame}[fragile]{Conditional Update Chaining} - -\begin{scala} -when (c1) { u1 } -.elsewhen (c2) { u2 } -.otherwise { ud } -\end{scala} - -which is the same as: - -\begin{scala} -when (c1) { u1 } -when (!c1 && c2) { u2 } -when (!(c1 || c2)) { ud } -\end{scala} - -\end{frame} - -\begin{frame}[fragile]{Switch Statement} - -\begin{scala} -switch(idx) { - is(v1) { u1 } - is(v2) { u2 } -} -\end{scala} - -which is the same as: - -\begin{scala} -when (idx === v1) { u1 } -when (idx === v2) { u2 } -\end{scala} - -\end{frame} - -% \begin{frame}[fragile]{Enums} -% \begin{scala} -% val s_even :: s_odd :: Nil = Enum(2){ UFix() } -% \end{scala} -% \end{frame} - - -\begin{frame}[fragile]{Finite State Machines} - -\begin{columns} -\column{0.65\textwidth} - -\begin{scala} -class Parity extends Component { - val io = new Bundle { - val in = Bool(INPUT) - val out = Bool(OUTPUT) } - val s_even :: s_odd :: Nil = Enum(2){ UFix() } - val state = Reg(resetVal = s_even) - when (io.in) { - when (state === s_even) { state := s_odd } - .otherwise { state := s_even } - } - io.out := (state === s_odd) -} -\end{scala} - -\column{0.25\textwidth} - -\begin{center} -\includegraphics[height=0.9\textheight]{figs/parity.pdf} -\end{center} - -\end{columns} -\end{frame} - -\begin{frame}[fragile]{ROM} - -\begin{scala} -val i = Array(UFix(1), UFix(2), UFix(4), UFix(8)) -val m = ROM(i){ UFix(width = 32) } -val r = m(counter(UFix(3))) -\end{scala} - -\begin{center} -\includegraphics[height=0.7\textheight]{figs/rom.pdf} -\end{center} - -\end{frame} - -\begin{frame}[fragile]{Mul Lookup Table Problem} -\begin{scala} -class Mul extends Component { - val io = new Bundle { - val x = UFix(INPUT, 4) - val y = UFix(INPUT, 4) - val z = UFix(OUTPUT, 8) } - - val muls = new Array[UFix](256) - for (x <- 0 until 16; y <- 0 until 16) - muls((x << 4) | y) = x * y - - val tbl = ROM(muls){ UFix(8) } - - io.z := tbl((io.x << 4) | io.y) -} -\end{scala} - -\end{frame} - -\begin{frame}[fragile]{Memories} - -\begin{scala} -val regs = Mem(32){ Bits(width = 32) } -when (wrEn) { - regs(wrAddr) := wrData -} -val iDat = regs(iAddr) -val mDat = regs(mAddr) -\end{scala} - -\begin{center} -\includegraphics[height=0.6\textheight]{figs/mem.pdf} -\end{center} - -\end{frame} - -\begin{frame}[fragile]{Port Classes, Subclasses, and Nesting} - -\begin{columns} -\column{0.55\textwidth} - -\begin{scala} -class LinkIO extends Bundle { - val data = Bits(OUTPUT, 16) - val valid = Bool(OUTPUT) -} -\end{scala} - -\column{0.35\textwidth} - -\begin{center} -\includegraphics[height=0.9\textheight]{figs/link-io.pdf} -\end{center} - -\end{columns} -\end{frame} - -\begin{frame}[fragile]{Bundle Subclassing} - -\begin{columns} -\column{0.55\textwidth} - -We can then extend \verb+SimpleLink+ by adding parity bits using -bundle inheritance: - -\begin{scala} -class PLinkIO extends LinkIO { - val parity = Bits(OUTPUT, 5) -} -\end{scala} - -\noindent -In general, users can organize their interfaces into hierarchies using inheritance in order to promote reuse. - -\column{0.35\textwidth} - -\begin{center} -\includegraphics[height=0.9\textheight]{figs/plink-io.pdf} -\end{center} - -\end{columns} - -\end{frame} - -\begin{frame}[fragile]{Filter IO} - -\begin{columns} -\column{0.55\textwidth} - -From there we can define a filter interface by nesting two -\verb+LinkIO+s into a new \verb+FilterIO+ bundle: - -\begin{scala} -class FilterIO extends Bundle { - val in = new LinkIO().flip - val out = new LinkIO() -} -\end{scala} - -\noindent -where \verb+flip+ recursively changes the ``gender'' of a bundle, -changing input to output and output to input. - -\column{0.35\textwidth} - -\begin{center} -\includegraphics[height=0.9\textheight]{figs/filter-io.pdf} -\end{center} - -\end{columns} -\end{frame} - -\begin{frame}[fragile]{Filter} - -We can now define a filter by defining a filter class extending component: - -\begin{columns} -\column{0.45\textwidth} - -\begin{scala} -class Filter extends Component { - val io = new FilterIO() - io.out.valid := io.in.valid - io.out.data := io.in.data -} -\end{scala} - -\column{0.45\textwidth} - -\begin{center} -\includegraphics[width=0.9\textwidth]{figs/pass-through-filter.pdf} -\end{center} -\end{columns} - -\noindent -where the \verb+io+ field contains \verb+FilterIO+. - -\end{frame} - -\begin{frame}[fragile]{Bulk Connections} -We can now compose two filters into a filter block as follows: - -\begin{columns} -\column{0.40\textwidth} - -\begin{scala} -class Block extends Component { - val io = new FilterIO() - val f1 = new Filter() - val f2 = new Filter() - - f1.io.in <> io.in - f1.io.out <> f2.io.in - f2.io.out <> io.out -} -\end{scala} - -\column{0.50\textwidth} - -\begin{center} -\includegraphics[width=0.9\textwidth]{figs/block.pdf} -\end{center} - -\end{columns} - -\noindent -where \verb+<>+ bulk connects interfaces. -\begin{itemize} -\item Bulk connections connect leaf ports of the same name to each other. -\item After all connections are made and the circuit is being elaborated, -Chisel warns users if ports have other than exactly one connection to them. -\end{itemize} - -\end{frame} - -\begin{frame}[fragile]{Router Interface} - -{\lstset{basicstyle={\scriptsize\ttfamily}} -\begin{scala} -class ReadCmd extends Bundle { - val addr = UFix(width = 32) -} - -class WriteCmd extends ReadCmd { - val data = UFix(width = 32) -} - -class Packet extends Bundle { - val header = UFix(width = 8) - val body = Bits(width = 64) -} - -class RouterIO(n: Int) extends Bundle { - override def clone = new RouterIO(n).asInstanceOf[this.type] - val reads = new DeqIO(){ new ReadCmd() } - val replies = new EnqIO(){ UFix(width = 8) } - val writes = new DeqIO(){ new WriteCmd() } - val in = new DeqIO(){ new Packet() } - val outs = Vec(n){ new EnqIO(){ new Packet() } } -} -\end{scala} -} - -\end{frame} - - -\begin{frame} -\begin{columns} - -\column{0.65\textwidth} - -\frametitle{Resources} -\begin{itemize} -\item Scala books -\item \url{chisel.eecs.berkeley.edu} -\item Chisel writings -\begin{itemize} -\item Chisel tutorial -\item Chisel manual -\item Chisel DAC-2012 paper -\end{itemize} -\item Chisel examples on github -\begin{itemize} -\item Sodor Processors -\item Floating Point Unit -\item Rocket Processor -\item Hwacha Vector Unit -\end{itemize} -\end{itemize} - -\column{0.25\textwidth} - -\begin{center} -\includegraphics[height=0.4\textheight]{figs/programming-scala.pdf} \\ -\includegraphics[height=0.4\textheight]{figs/programming-in-scala.pdf} -\end{center} - -\end{columns} - -\end{frame} - -\begin{frame} -\frametitle{Advanced Topics} -\begin{itemize} -\item Library Interfaces and Data Structures -\item Polymorphism and Parameterization -\item Higher-order Functions -\item Layering Domain Specific Languages on Top -\end{itemize} -\end{frame} - -\end{document} diff --git a/doc/cs250/figs/FIFOIO.graffle b/doc/cs250/figs/FIFOIO.graffle deleted file mode 100644 index 3b93b177..00000000 Binary files a/doc/cs250/figs/FIFOIO.graffle and /dev/null differ diff --git a/doc/cs250/figs/FIFOIO.pdf b/doc/cs250/figs/FIFOIO.pdf deleted file mode 100644 index bac09da8..00000000 Binary files a/doc/cs250/figs/FIFOIO.pdf and /dev/null differ diff --git a/doc/cs250/figs/abcd.graffle b/doc/cs250/figs/abcd.graffle deleted file mode 100644 index 3ae90706..00000000 Binary files a/doc/cs250/figs/abcd.graffle and /dev/null differ diff --git a/doc/cs250/figs/abcd.pdf b/doc/cs250/figs/abcd.pdf deleted file mode 100644 index b2ad00f3..00000000 Binary files a/doc/cs250/figs/abcd.pdf and /dev/null differ diff --git a/doc/cs250/figs/add.graffle b/doc/cs250/figs/add.graffle deleted file mode 100644 index 930e02fd..00000000 Binary files a/doc/cs250/figs/add.graffle and /dev/null differ diff --git a/doc/cs250/figs/add.pdf b/doc/cs250/figs/add.pdf deleted file mode 100644 index 5b4f0b6d..00000000 Binary files a/doc/cs250/figs/add.pdf and /dev/null differ diff --git a/doc/cs250/figs/block.graffle b/doc/cs250/figs/block.graffle deleted file mode 100644 index 5919cce2..00000000 Binary files a/doc/cs250/figs/block.graffle and /dev/null differ diff --git a/doc/cs250/figs/block.pdf b/doc/cs250/figs/block.pdf deleted file mode 100644 index acbb674a..00000000 Binary files a/doc/cs250/figs/block.pdf and /dev/null differ diff --git a/doc/cs250/figs/chisel-design-process.graffle b/doc/cs250/figs/chisel-design-process.graffle deleted file mode 100644 index bfed2540..00000000 Binary files a/doc/cs250/figs/chisel-design-process.graffle and /dev/null differ diff --git a/doc/cs250/figs/chisel-design-process.pdf b/doc/cs250/figs/chisel-design-process.pdf deleted file mode 100644 index 5194b0bc..00000000 Binary files a/doc/cs250/figs/chisel-design-process.pdf and /dev/null differ diff --git a/doc/cs250/figs/chisel-testing.graffle b/doc/cs250/figs/chisel-testing.graffle deleted file mode 100644 index a0b3dac5..00000000 Binary files a/doc/cs250/figs/chisel-testing.graffle and /dev/null differ diff --git a/doc/cs250/figs/chisel-testing.pdf b/doc/cs250/figs/chisel-testing.pdf deleted file mode 100644 index 81dc05a2..00000000 Binary files a/doc/cs250/figs/chisel-testing.pdf and /dev/null differ diff --git a/doc/cs250/figs/chiseler.pdf b/doc/cs250/figs/chiseler.pdf deleted file mode 100644 index 2b6614c8..00000000 Binary files a/doc/cs250/figs/chiseler.pdf and /dev/null differ diff --git a/doc/cs250/figs/conditional-increment.graffle b/doc/cs250/figs/conditional-increment.graffle deleted file mode 100644 index f45b615c..00000000 Binary files a/doc/cs250/figs/conditional-increment.graffle and /dev/null differ diff --git a/doc/cs250/figs/conditional-increment.pdf b/doc/cs250/figs/conditional-increment.pdf deleted file mode 100644 index 77717065..00000000 Binary files a/doc/cs250/figs/conditional-increment.pdf and /dev/null differ diff --git a/doc/cs250/figs/conditional-updates.graffle b/doc/cs250/figs/conditional-updates.graffle deleted file mode 100644 index 405294b3..00000000 Binary files a/doc/cs250/figs/conditional-updates.graffle and /dev/null differ diff --git a/doc/cs250/figs/conditional-updates.pdf b/doc/cs250/figs/conditional-updates.pdf deleted file mode 100644 index bab0b336..00000000 Binary files a/doc/cs250/figs/conditional-updates.pdf and /dev/null differ diff --git a/doc/cs250/figs/counter.graffle b/doc/cs250/figs/counter.graffle deleted file mode 100644 index fc693c93..00000000 Binary files a/doc/cs250/figs/counter.graffle and /dev/null differ diff --git a/doc/cs250/figs/counter.pdf b/doc/cs250/figs/counter.pdf deleted file mode 100644 index a48daa58..00000000 Binary files a/doc/cs250/figs/counter.pdf and /dev/null differ diff --git a/doc/cs250/figs/decoupled-block.graffle b/doc/cs250/figs/decoupled-block.graffle deleted file mode 100644 index ca1635fb..00000000 Binary files a/doc/cs250/figs/decoupled-block.graffle and /dev/null differ diff --git a/doc/cs250/figs/decoupled-block.pdf b/doc/cs250/figs/decoupled-block.pdf deleted file mode 100644 index 655a711c..00000000 Binary files a/doc/cs250/figs/decoupled-block.pdf and /dev/null differ diff --git a/doc/cs250/figs/decoupled-filter-io.graffle b/doc/cs250/figs/decoupled-filter-io.graffle deleted file mode 100644 index ef5a757f..00000000 Binary files a/doc/cs250/figs/decoupled-filter-io.graffle and /dev/null differ diff --git a/doc/cs250/figs/decoupled-filter-io.pdf b/doc/cs250/figs/decoupled-filter-io.pdf deleted file mode 100644 index 6a71655b..00000000 Binary files a/doc/cs250/figs/decoupled-filter-io.pdf and /dev/null differ diff --git a/doc/cs250/figs/design-loop-compile-test-debug-eval.pdf b/doc/cs250/figs/design-loop-compile-test-debug-eval.pdf deleted file mode 100644 index b5501b26..00000000 Binary files a/doc/cs250/figs/design-loop-compile-test-debug-eval.pdf and /dev/null differ diff --git a/doc/cs250/figs/design-loop-debug.graffle b/doc/cs250/figs/design-loop-debug.graffle deleted file mode 100644 index c1dc927a..00000000 Binary files a/doc/cs250/figs/design-loop-debug.graffle and /dev/null differ diff --git a/doc/cs250/figs/design-loop-debug.pdf b/doc/cs250/figs/design-loop-debug.pdf deleted file mode 100644 index a438f224..00000000 Binary files a/doc/cs250/figs/design-loop-debug.pdf and /dev/null differ diff --git a/doc/cs250/figs/design-loop-program-compile-test-debug-eval.graffle b/doc/cs250/figs/design-loop-program-compile-test-debug-eval.graffle deleted file mode 100644 index 1f40bee1..00000000 Binary files a/doc/cs250/figs/design-loop-program-compile-test-debug-eval.graffle and /dev/null differ diff --git a/doc/cs250/figs/design-loop-program-compile-test-debug-eval.pdf b/doc/cs250/figs/design-loop-program-compile-test-debug-eval.pdf deleted file mode 100644 index fac9140e..00000000 Binary files a/doc/cs250/figs/design-loop-program-compile-test-debug-eval.pdf and /dev/null differ diff --git a/doc/cs250/figs/design-loop-program-eval.graffle b/doc/cs250/figs/design-loop-program-eval.graffle deleted file mode 100644 index 3772a375..00000000 Binary files a/doc/cs250/figs/design-loop-program-eval.graffle and /dev/null differ diff --git a/doc/cs250/figs/design-loop-program-eval.pdf b/doc/cs250/figs/design-loop-program-eval.pdf deleted file mode 100644 index 996c66ee..00000000 Binary files a/doc/cs250/figs/design-loop-program-eval.pdf and /dev/null differ diff --git a/doc/cs250/figs/design-loop-programming.graffle b/doc/cs250/figs/design-loop-programming.graffle deleted file mode 100644 index a6019efa..00000000 Binary files a/doc/cs250/figs/design-loop-programming.graffle and /dev/null differ diff --git a/doc/cs250/figs/design-loop-programming.pdf b/doc/cs250/figs/design-loop-programming.pdf deleted file mode 100644 index 7b4e497e..00000000 Binary files a/doc/cs250/figs/design-loop-programming.pdf and /dev/null differ diff --git a/doc/cs250/figs/design-loop-test-debug-eval.graffle b/doc/cs250/figs/design-loop-test-debug-eval.graffle deleted file mode 100644 index 68054330..00000000 Binary files a/doc/cs250/figs/design-loop-test-debug-eval.graffle and /dev/null differ diff --git a/doc/cs250/figs/design-loop-test-debug-eval.pdf b/doc/cs250/figs/design-loop-test-debug-eval.pdf deleted file mode 100644 index fcf33206..00000000 Binary files a/doc/cs250/figs/design-loop-test-debug-eval.pdf and /dev/null differ diff --git a/doc/cs250/figs/design-loop-test.graffle b/doc/cs250/figs/design-loop-test.graffle deleted file mode 100644 index cd53f6b3..00000000 Binary files a/doc/cs250/figs/design-loop-test.graffle and /dev/null differ diff --git a/doc/cs250/figs/design-loop-test.pdf b/doc/cs250/figs/design-loop-test.pdf deleted file mode 100644 index ed85b178..00000000 Binary files a/doc/cs250/figs/design-loop-test.pdf and /dev/null differ diff --git a/doc/cs250/figs/design-loop.graffle b/doc/cs250/figs/design-loop.graffle deleted file mode 100644 index 4f0b4748..00000000 Binary files a/doc/cs250/figs/design-loop.graffle and /dev/null differ diff --git a/doc/cs250/figs/design-loop.pdf b/doc/cs250/figs/design-loop.pdf deleted file mode 100644 index 01c18086..00000000 Binary files a/doc/cs250/figs/design-loop.pdf and /dev/null differ diff --git a/doc/cs250/figs/design.graffle b/doc/cs250/figs/design.graffle deleted file mode 100644 index a3f86254..00000000 Binary files a/doc/cs250/figs/design.graffle and /dev/null differ diff --git a/doc/cs250/figs/design.pdf b/doc/cs250/figs/design.pdf deleted file mode 100644 index e5d8d417..00000000 Binary files a/doc/cs250/figs/design.pdf and /dev/null differ diff --git a/doc/cs250/figs/filter-io.graffle b/doc/cs250/figs/filter-io.graffle deleted file mode 100644 index d826175c..00000000 Binary files a/doc/cs250/figs/filter-io.graffle and /dev/null differ diff --git a/doc/cs250/figs/filter-io.pdf b/doc/cs250/figs/filter-io.pdf deleted file mode 100644 index b6cf1186..00000000 Binary files a/doc/cs250/figs/filter-io.pdf and /dev/null differ diff --git a/doc/cs250/figs/filter.graffle b/doc/cs250/figs/filter.graffle deleted file mode 100644 index a0c7778f..00000000 --- a/doc/cs250/figs/filter.graffle +++ /dev/null @@ -1,1274 +0,0 @@ - - - - - ActiveLayerIndex - 0 - ApplicationVersion - - com.omnigroup.OmniGrafflePro - 138.33.0.157554 - - AutoAdjust - - BackgroundGraphic - - Bounds - {{0, 0}, {576, 733}} - Class - SolidGraphic - ID - 2 - Style - - shadow - - Draws - NO - - stroke - - Draws - NO - - - - CanvasOrigin - {0, 0} - ColumnAlign - 1 - ColumnSpacing - 36 - CreationDate - 2012-05-29 16:25:21 -0700 - Creator - Jonathan Bachrach - DisplayScale - 1 0/72 in = 1 0/72 in - GraphDocumentVersion - 8 - GraphicsList - - - Class - Group - Graphics - - - Class - LineGraphic - ID - 53 - Points - - {468, 333} - {540, 333} - - Style - - stroke - - HeadArrow - 0 - TailArrow - 0 - Width - 3 - - - - - Class - LineGraphic - ID - 54 - Points - - {522, 243} - {522, 333} - - Style - - stroke - - HeadArrow - 0 - TailArrow - 0 - Width - 3 - - - - - Class - LineGraphic - ID - 55 - Points - - {504, 243} - {504, 333} - - Style - - stroke - - HeadArrow - 0 - TailArrow - 0 - Width - 3 - - - - - Class - LineGraphic - ID - 56 - Points - - {468, 243} - {540, 243} - - Style - - stroke - - HeadArrow - 0 - TailArrow - 0 - Width - 3 - - - - - Class - LineGraphic - ID - 57 - Points - - {486, 243} - {486, 333} - - Style - - stroke - - HeadArrow - 0 - TailArrow - 0 - Width - 3 - - - - - ID - 52 - - - Class - Group - Graphics - - - Class - LineGraphic - ID - 47 - Points - - {36, 333} - {108, 333} - - Style - - stroke - - HeadArrow - 0 - TailArrow - 0 - Width - 3 - - - - - Class - LineGraphic - ID - 48 - Points - - {90, 243} - {90, 333} - - Style - - stroke - - HeadArrow - 0 - TailArrow - 0 - Width - 3 - - - - - Class - LineGraphic - ID - 49 - Points - - {72, 243} - {72, 333} - - Style - - stroke - - HeadArrow - 0 - TailArrow - 0 - Width - 3 - - - - - Class - LineGraphic - ID - 50 - Points - - {36, 243} - {108, 243} - - Style - - stroke - - HeadArrow - 0 - TailArrow - 0 - Width - 3 - - - - - Class - LineGraphic - ID - 51 - Points - - {54, 243} - {54, 333} - - Style - - stroke - - HeadArrow - 0 - TailArrow - 0 - Width - 3 - - - - - ID - 46 - - - Bounds - {{379.5, 297.5}, {63, 35}} - Class - ShapedGraphic - FitText - YES - Flow - Resize - FontInfo - - Color - - w - 0 - - Font - Helvetica - Size - 21 - - ID - 16 - Line - - ID - 15 - Position - 0.47222220897674561 - RotationType - 0 - - Shape - Rectangle - Style - - shadow - - Draws - NO - - stroke - - Draws - NO - Width - 2 - - - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1038\cocoasubrtf360 -{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural - -\f0\fs42 \cf0 ready} - - Wrap - NO - - - Class - LineGraphic - FontInfo - - Font - Helvetica - Size - 20 - - ID - 15 - Points - - {360, 315} - {468, 315} - - Style - - stroke - - HeadArrow - 0 - TailArrow - StickArrow - Width - 2 - - - - - Bounds - {{385.5, 270.5}, {51, 35}} - Class - ShapedGraphic - FitText - YES - Flow - Resize - FontInfo - - Color - - w - 0 - - Font - Helvetica - Size - 21 - - ID - 14 - Line - - ID - 13 - Position - 0.47222220897674561 - RotationType - 0 - - Shape - Rectangle - Style - - shadow - - Draws - NO - - stroke - - Draws - NO - Width - 2 - - - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1038\cocoasubrtf360 -{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural - -\f0\fs42 \cf0 data} - - Wrap - NO - - - Class - LineGraphic - FontInfo - - Font - Helvetica - Size - 20 - - ID - 13 - Points - - {360, 288} - {468, 288} - - Style - - stroke - - HeadArrow - StickArrow - TailArrow - 0 - Width - 2 - - - - - Bounds - {{133.5, 270.5}, {51, 35}} - Class - ShapedGraphic - FitText - YES - Flow - Resize - FontInfo - - Color - - w - 0 - - Font - Helvetica - Size - 21 - - ID - 12 - Line - - ID - 11 - Position - 0.47222220897674561 - RotationType - 0 - - Shape - Rectangle - Style - - shadow - - Draws - NO - - stroke - - Draws - NO - Width - 2 - - - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1038\cocoasubrtf360 -{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural - -\f0\fs42 \cf0 data} - - Wrap - NO - - - Class - LineGraphic - FontInfo - - Font - Helvetica - Size - 20 - - ID - 11 - Points - - {108, 288} - {216, 288} - - Style - - stroke - - HeadArrow - StickArrow - TailArrow - 0 - Width - 2 - - - - - Bounds - {{127.5, 297.5}, {63, 35}} - Class - ShapedGraphic - FitText - YES - Flow - Resize - FontInfo - - Color - - w - 0 - - Font - Helvetica - Size - 21 - - ID - 10 - Line - - ID - 9 - Position - 0.47222220897674561 - RotationType - 0 - - Shape - Rectangle - Style - - shadow - - Draws - NO - - stroke - - Draws - NO - Width - 2 - - - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1038\cocoasubrtf360 -{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural - -\f0\fs42 \cf0 ready} - - Wrap - NO - - - Class - LineGraphic - FontInfo - - Font - Helvetica - Size - 20 - - ID - 9 - Points - - {108, 315} - {216, 315} - - Style - - stroke - - HeadArrow - 0 - TailArrow - StickArrow - Width - 2 - - - - - Bounds - {{384, 243.5}, {54, 35}} - Class - ShapedGraphic - FitText - YES - Flow - Resize - FontInfo - - Color - - w - 0 - - Font - Helvetica - Size - 21 - - ID - 8 - Line - - ID - 7 - Position - 0.47222220897674561 - RotationType - 0 - - Shape - Rectangle - Style - - shadow - - Draws - NO - - stroke - - Draws - NO - Width - 2 - - - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1038\cocoasubrtf360 -{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural - -\f0\fs42 \cf0 valid} - - Wrap - NO - - - Class - LineGraphic - FontInfo - - Font - Helvetica - Size - 20 - - ID - 7 - Points - - {360, 261} - {468, 261} - - Style - - stroke - - HeadArrow - StickArrow - TailArrow - 0 - Width - 2 - - - - - Bounds - {{132, 243.5}, {54, 35}} - Class - ShapedGraphic - FitText - YES - Flow - Resize - FontInfo - - Color - - w - 0 - - Font - Helvetica - Size - 21 - - ID - 6 - Line - - ID - 5 - Position - 0.47222220897674561 - RotationType - 0 - - Shape - Rectangle - Style - - shadow - - Draws - NO - - stroke - - Draws - NO - Width - 2 - - - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1038\cocoasubrtf360 -{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural - -\f0\fs42 \cf0 valid} - - Wrap - NO - - - Class - LineGraphic - FontInfo - - Font - Helvetica - Size - 20 - - ID - 5 - Points - - {108, 261} - {216, 261} - - Style - - stroke - - HeadArrow - StickArrow - TailArrow - 0 - Width - 2 - - - - - Bounds - {{216, 216}, {144, 144}} - Class - ShapedGraphic - FontInfo - - Font - Helvetica - Size - 22 - - ID - 3 - Shape - Rectangle - Style - - stroke - - Width - 2 - - - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1038\cocoasubrtf360 -{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural - -\f0\fs78 \cf0 Filter} - - - - GridInfo - - ShowsGrid - YES - SnapsToGrid - YES - - GuidesLocked - NO - GuidesVisible - YES - HPages - 1 - ImageCounter - 1 - KeepToScale - - Layers - - - Lock - NO - Name - Layer 1 - Print - YES - View - YES - - - LayoutInfo - - Animate - NO - circoMinDist - 18 - circoSeparation - 0.0 - layoutEngine - dot - neatoSeparation - 0.0 - twopiSeparation - 0.0 - - LinksVisible - NO - MagnetsVisible - NO - MasterSheets - - ModificationDate - 2012-05-30 10:08:02 -0700 - Modifier - Jonathan Bachrach - NotesVisible - NO - Orientation - 2 - OriginVisible - NO - PageBreaks - YES - PrintInfo - - NSBottomMargin - - float - 41 - - NSLeftMargin - - float - 18 - - NSPaperSize - - coded - BAtzdHJlYW10eXBlZIHoA4QBQISEhAdOU1ZhbHVlAISECE5TT2JqZWN0AIWEASqEhAx7X05TU2l6ZT1mZn2WgWQCgRgDhg== - - NSRightMargin - - float - 18 - - NSTopMargin - - float - 18 - - - PrintOnePage - - QuickLookPreview - - JVBERi0xLjMKJcTl8uXrp/Og0MTGCjUgMCBvYmoKPDwgL0xlbmd0aCA2IDAgUiAvRmls - dGVyIC9GbGF0ZURlY29kZSA+PgpzdHJlYW0KeAGlVctu20AMvO9X8KgcvNmntLo2aA65 - BRbQQ9FD4MRAArlAHmjRv++Qu5Ilx1acFoIg2iJnyRGHfKZbeiaDKzY1Nd7TywN9o590 - efVqafNKVq7XDa2MjsT3xHFLztbkG082BL4VovEn/UbUDe6njHO1liMMra9wmpUfK37w - gZudoDBSQeEc1uqWYx3nYAjnT+JcShRC5MgvHSdmjHHUbci3GRrPVfDae+cSQHVU3Y4u - r602OLzbUnX92L89vFxQ90RfO6HgfVLWJHK1JaRnvLZi95KXQW0GtU1SmpTidHMkrmDE - RgdGtPBSjN6P6EHX+LVGNu+4t96C+BBBfiAfmZ/tjB01ScXGlkID4oQdVwrDc+WA0gZ8 - rQZoc0a+U/Xr7oK5dKrqs0HV42DcX9AP6m4yWcOnnZw5lu9rU4pHttqWErmoJdJCHUbS - JK6QXWwmTe1o79UzF/JJFkjzyR8nTR1pqWDtP5CmRtLof0izzuhWeRulMyAoWLkTlkiz - 1movvjsShBI3oCX0E96MXv3oZdGDpzrNNRSMpRrIuc/UKRVKn9l0rM9q7ero00GfKSgP - ffbyMHRVaTiq0F7ceVT9ObPPlIgTY2AUJ+yPKRPZEY+PSZwaJZjCXpziNb5p7ZI4PQXM - mWhBWR6Ai5SNg2s/t2YiNTpARYHJOxxb93dv4GwYWh/qUOosSkkJdZ6pw3kceB0wMj+i - Q8Usjm+W+PEJo2vg5/3oomc1zl5R4Sf4ORhilfCjzuKncbot4gl1OkNyCvPU11gqJcqP - CD02YEbLktt77d/MJccTyMqFxeYbzOuZ5GajfbplhJ8PJXfQNZ+RnJ9s7sPxzgRg/bjg - oR7eQ9jduaUOPXkk+Lp4ilIRc9yVQbGrMiiMZdAWy0WOh3HaM38pccD8wxY/7cqZhjSk - ytZpX4blVhkIyLkcL4txIzRcfGEt40Y3cMDWaV/Jl9sV3PNHmNJw+xf6Sgd1CmVuZHN0 - cmVhbQplbmRvYmoKNiAwIG9iago3MzIKZW5kb2JqCjMgMCBvYmoKPDwgL1R5cGUgL1Bh - Z2UgL1BhcmVudCA0IDAgUiAvUmVzb3VyY2VzIDcgMCBSIC9Db250ZW50cyA1IDAgUiAv - TWVkaWFCb3ggWzAgMCA1NzYgNzMzXQo+PgplbmRvYmoKNyAwIG9iago8PCAvUHJvY1Nl - dCBbIC9QREYgL1RleHQgXSAvQ29sb3JTcGFjZSA8PCAvQ3MxIDggMCBSIC9DczIgOSAw - IFIgPj4gL0ZvbnQgPDwKL0YxLjAgMTAgMCBSID4+ID4+CmVuZG9iagoxMSAwIG9iago8 - PCAvTGVuZ3RoIDEyIDAgUiAvTiAzIC9BbHRlcm5hdGUgL0RldmljZVJHQiAvRmlsdGVy - IC9GbGF0ZURlY29kZSA+PgpzdHJlYW0KeAGFVM9rE0EU/jZuqdAiCFprDrJ4kCJJWato - RdQ2/RFiawzbH7ZFkGQzSdZuNuvuJrWliOTi0SreRe2hB/+AHnrwZC9KhVpFKN6rKGKh - Fy3xzW5MtqXqwM5+8943731vdt8ADXLSNPWABOQNx1KiEWlsfEJq/IgAjqIJQTQlVdvs - TiQGQYNz+Xvn2HoPgVtWw3v7d7J3rZrStpoHhP1A4Eea2Sqw7xdxClkSAog836Epx3QI - 3+PY8uyPOU55eMG1Dys9xFkifEA1Lc5/TbhTzSXTQINIOJT1cVI+nNeLlNcdB2luZsbI - EL1PkKa7zO6rYqGcTvYOkL2d9H5Os94+wiHCCxmtP0a4jZ71jNU/4mHhpObEhj0cGDX0 - +GAVtxqp+DXCFF8QTSeiVHHZLg3xmK79VvJKgnCQOMpkYYBzWkhP10xu+LqHBX0m1xOv - 4ndWUeF5jxNn3tTd70XaAq8wDh0MGgyaDUhQEEUEYZiwUECGPBoxNLJyPyOrBhuTezJ1 - JGq7dGJEsUF7Ntw9t1Gk3Tz+KCJxlEO1CJL8Qf4qr8lP5Xn5y1yw2Fb3lK2bmrry4DvF - 5Zm5Gh7X08jjc01efJXUdpNXR5aseXq8muwaP+xXlzHmgjWPxHOw+/EtX5XMlymMFMXj - VfPqS4R1WjE3359sfzs94i7PLrXWc62JizdWm5dn/WpI++6qvJPmVflPXvXx/GfNxGPi - KTEmdornIYmXxS7xkthLqwviYG3HCJ2VhinSbZH6JNVgYJq89S9dP1t4vUZ/DPVRlBnM - 0lSJ93/CKmQ0nbkOb/qP28f8F+T3iuefKAIvbODImbptU3HvEKFlpW5zrgIXv9F98LZu - a6N+OPwEWDyrFq1SNZ8gvAEcdod6HugpmNOWls05Uocsn5O66cpiUsxQ20NSUtcl12VL - FrOZVWLpdtiZ0x1uHKE5QvfEp0plk/qv8RGw/bBS+fmsUtl+ThrWgZf6b8C8/UUKZW5k - c3RyZWFtCmVuZG9iagoxMiAwIG9iago3MzcKZW5kb2JqCjggMCBvYmoKWyAvSUNDQmFz - ZWQgMTEgMCBSIF0KZW5kb2JqCjEzIDAgb2JqCjw8IC9MZW5ndGggMTQgMCBSIC9OIDEg - L0FsdGVybmF0ZSAvRGV2aWNlR3JheSAvRmlsdGVyIC9GbGF0ZURlY29kZSA+PgpzdHJl - YW0KeAGFUk9IFFEc/s02EoSIQYV4iHcKCZUprKyg2nZ1WZVtW5XSohhn37qjszPTm9k1 - xZMEXaI8dQ+iY3Ts0KGbl6LArEvXIKkgCDx16PvN7OoohG95O9/7/f1+33tEbZ2m7zsp - QVRzQ5UrpaduTk2Lgx8pRR3UTlimFfjpYnGMseu5kr+719Zn0tiy3se1dvv2PbWVZWAh - 6i22txD6IZFmAB+ZnyhlgLPAHZav2D4BPFgOrBrwI6IDD5q5MNPRnHSlsi2RU+aiKCqv - YjtJrvv5uca+i7WJg/5cj2bWjr2z6qrRTNS090ShvA+uRBnPX1T2bDUUpw3jnEhDGiny - rtXfK0zHEZErEEoGUjVkuZ9qTp114HUYu126k+P49hClPslgqIm16bKZHYV9AHYqy+wQ - 8AXo8bJiD+eBe2H/W1HDk8AnYT9kh3nWrR/2F65T4HuEPTXgzhSuxfHaih9eLQFD91Qj - aIxzTcTT1zlzpIjvMdQZmPdGOaYLMXeWqhM3gDthH1mqZgqxXfuu6iXuewJ30+M70Zs5 - C1ygHElysRXZFNA8CVgUfYuwSQ48Ps4eVeB3qJjAHLmJ3M0o9x7VERtno1KBVnqNV8ZP - 47nxxfhlbBjPgH6sdtd7fP/p4xV117Y+PPmNetw5rr2dG1VhVnFlC93/xzKEj9knOabB - 06FZWGvYduQPmsxMsAwoxH8FPpf6khNV3NXu7bhFEsxQPixsJbpLVG4p1Oo9g0qsHCvY - AHZwksQsWhy4U2u6OXh32CJ6bflNV7Lrhv769nr72vIebcqoKSgTzbNEZpSxW6Pk3Xjb - /WaREZ84Or7nvYpayf5JRRA/hTlaKvIUVfRWUNbEb2cOfhu2flw/pef1Qf08CT2tn9Gv - 6KMRvgx0Sc/Cc1Efo0nwsGkh4hKgioMz1E5UY40D4inx8rRbZJH9D0AZ/WYKZW5kc3Ry - ZWFtCmVuZG9iagoxNCAwIG9iago3MDQKZW5kb2JqCjkgMCBvYmoKWyAvSUNDQmFzZWQg - MTMgMCBSIF0KZW5kb2JqCjQgMCBvYmoKPDwgL1R5cGUgL1BhZ2VzIC9NZWRpYUJveCBb - MCAwIDYxMiA3OTJdIC9Db3VudCAxIC9LaWRzIFsgMyAwIFIgXSA+PgplbmRvYmoKMTUg - MCBvYmoKPDwgL1R5cGUgL0NhdGFsb2cgL091dGxpbmVzIDIgMCBSIC9QYWdlcyA0IDAg - UiA+PgplbmRvYmoKMiAwIG9iago8PCAvTGFzdCAxNiAwIFIgL0ZpcnN0IDE3IDAgUiA+ - PgplbmRvYmoKMTcgMCBvYmoKPDwgL1BhcmVudCAxOCAwIFIgL0NvdW50IDAgL0Rlc3Qg - WyAzIDAgUiAvWFlaIDAgNzMzIDAgXSAvVGl0bGUgKENhbnZhcyAxKQo+PgplbmRvYmoK - MTggMCBvYmoKPDwgPj4KZW5kb2JqCjE2IDAgb2JqCjw8IC9QYXJlbnQgMTggMCBSIC9D - b3VudCAwIC9EZXN0IFsgMyAwIFIgL1hZWiAwIDczMyAwIF0gL1RpdGxlIChDYW52YXMg - MSkKPj4KZW5kb2JqCjE5IDAgb2JqCjw8IC9MZW5ndGggMjAgMCBSIC9MZW5ndGgxIDc1 - ODggL0ZpbHRlciAvRmxhdGVEZWNvZGUgPj4Kc3RyZWFtCngBvVkNdFRFlr71/jsdku5O - Ov2T7nQ3ne7O/y8kaRPJI3SHhJAQCGAaiaQDCQkSjRiiMAMTFRQCMiLyo3gcUZffwTyS - DDYwsNEF0RlHcUbxZ9kdVHQ8HnOY3VXXEZLe+16HSDijh7PHY1VuVd26VbdufXXf7fcq - nStWNsME6AYaahcEO1pASZbTWF1c3B7siPC6i1h3L+7qtEd4NgWAXt7SsbQ9wgtPAERZ - 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 - jHS+QWyEyV46snXkyxdHWgY44YUJnMMoPJHM1CBcD8oxQknhZrzT/WcJvQ7vhn3K3fBM - mIV3v7dBABZiL8Hb6sj7Gof/v4PK+gXz/NPTK5qXdzV3ti0OKiOuaZT/rygi1SI1InUg - dSM9hvQskoQ0iHQuPJqwDWNtgu+G43lZ+/XyJTfwyl6um992g1y+57x+vvz+eT2v/P/y - uvldN8hXyfz/AQXRxFEKZW5kc3RyZWFtCmVuZG9iagoyMCAwIG9iago0NjcyCmVuZG9i - agoyMSAwIG9iago8PCAvVHlwZSAvRm9udERlc2NyaXB0b3IgL0FzY2VudCA3NzAgL0Nh - cEhlaWdodCA2ODQgL0Rlc2NlbnQgLTIzMCAvRmxhZ3MgMzIKL0ZvbnRCQm94IFstOTUx - IC00ODEgMTQ0NSAxMTIyXSAvRm9udE5hbWUgL0lYWlVFRytIZWx2ZXRpY2EgL0l0YWxp - Y0FuZ2xlIDAKL1N0ZW1WIDAgL01heFdpZHRoIDE1MDAgL1hIZWlnaHQgNTEzIC9Gb250 - RmlsZTIgMTkgMCBSID4+CmVuZG9iagoyMiAwIG9iagpbIDYxMSAwIDAgMCAwIDAgMCAw - IDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgNTU2IDAgMCA1NTYg - NTU2CjAgMCAwIDIyMiAwIDAgMjIyIDAgMCAwIDAgMCAzMzMgMCAyNzggMCA1MDAgMCAw - IDUwMCBdCmVuZG9iagoxMCAwIG9iago8PCAvVHlwZSAvRm9udCAvU3VidHlwZSAvVHJ1 - ZVR5cGUgL0Jhc2VGb250IC9JWFpVRUcrSGVsdmV0aWNhIC9Gb250RGVzY3JpcHRvcgoy - MSAwIFIgL1dpZHRocyAyMiAwIFIgL0ZpcnN0Q2hhciA3MCAvTGFzdENoYXIgMTIxIC9F - bmNvZGluZyAvTWFjUm9tYW5FbmNvZGluZwo+PgplbmRvYmoKMjMgMCBvYmoKKE1hYyBP - UyBYIDEwLjYuOCBRdWFydHogUERGQ29udGV4dCkKZW5kb2JqCjI0IDAgb2JqCihEOjIw - MTIwNTMwMTcwODEzWjAwJzAwJykKZW5kb2JqCjEgMCBvYmoKPDwgL1Byb2R1Y2VyIDIz - IDAgUiAvQ3JlYXRpb25EYXRlIDI0IDAgUiAvTW9kRGF0ZSAyNCAwIFIgPj4KZW5kb2Jq - CnhyZWYKMCAyNQowMDAwMDAwMDAwIDY1NTM1IGYgCjAwMDAwMDg2NDcgMDAwMDAgbiAK - MDAwMDAwMjk3MCAwMDAwMCBuIAowMDAwMDAwODQ3IDAwMDAwIG4gCjAwMDAwMDI4MjEg - MDAwMDAgbiAKMDAwMDAwMDAyMiAwMDAwMCBuIAowMDAwMDAwODI4IDAwMDAwIG4gCjAw - MDAwMDA5NTEgMDAwMDAgbiAKMDAwMDAwMTkyMSAwMDAwMCBuIAowMDAwMDAyNzg1IDAw - MDAwIG4gCjAwMDAwMDgzNzggMDAwMDAgbiAKMDAwMDAwMTA2MSAwMDAwMCBuIAowMDAw - MDAxOTAxIDAwMDAwIG4gCjAwMDAwMDE5NTcgMDAwMDAgbiAKMDAwMDAwMjc2NSAwMDAw - MCBuIAowMDAwMDAyOTA0IDAwMDAwIG4gCjAwMDAwMDMxMzMgMDAwMDAgbiAKMDAwMDAw - MzAxOCAwMDAwMCBuIAowMDAwMDAzMTExIDAwMDAwIG4gCjAwMDAwMDMyMjYgMDAwMDAg - biAKMDAwMDAwNzk4OCAwMDAwMCBuIAowMDAwMDA4MDA5IDAwMDAwIG4gCjAwMDAwMDgy - MzQgMDAwMDAgbiAKMDAwMDAwODU1MyAwMDAwMCBuIAowMDAwMDA4NjA1IDAwMDAwIG4g - CnRyYWlsZXIKPDwgL1NpemUgMjUgL1Jvb3QgMTUgMCBSIC9JbmZvIDEgMCBSIC9JRCBb - IDxhMWZhNmQ4NWVmYmIxZmRhNzA4YzNjYjIyZGE5MWZlYj4KPGExZmE2ZDg1ZWZiYjFm - ZGE3MDhjM2NiMjJkYTkxZmViPiBdID4+CnN0YXJ0eHJlZgo4NzIyCiUlRU9GCjEgMCBv - YmoKPDwvQXV0aG9yIChKb25hdGhhbiBCYWNocmFjaCkvQ3JlYXRpb25EYXRlIChEOjIw - MTIwNTI5MjMyNTAwWikvQ3JlYXRvciAoT21uaUdyYWZmbGUgUHJvZmVzc2lvbmFsIDUu - My42KS9Nb2REYXRlIChEOjIwMTIwNTMwMTcwODAwWikvUHJvZHVjZXIgMjMgMCBSIC9U - aXRsZSAoZmlsdGVyKT4+CmVuZG9iagp4cmVmCjEgMQowMDAwMDA5Mzc5IDAwMDAwIG4g - CnRyYWlsZXIKPDwvSUQgWzxhMWZhNmQ4NWVmYmIxZmRhNzA4YzNjYjIyZGE5MWZlYj4g - PGExZmE2ZDg1ZWZiYjFmZGE3MDhjM2NiMjJkYTkxZmViPl0gL0luZm8gMSAwIFIgL1By - ZXYgODcyMiAvUm9vdCAxNSAwIFIgL1NpemUgMjU+PgpzdGFydHhyZWYKOTU2MAolJUVP - Rgo= - - QuickLookThumbnail - - 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 - - ReadOnly - NO - RowAlign - 1 - RowSpacing - 36 - SheetTitle - Canvas 1 - SmartAlignmentGuidesActive - YES - SmartDistanceGuidesActive - YES - UniqueID - 1 - UseEntirePage - - VPages - 1 - WindowInfo - - CurrentSheet - 0 - ExpandedCanvases - - - name - Canvas 1 - - - Frame - {{512, 4}, {710, 874}} - ListView - - OutlineWidth - 142 - RightSidebar - - ShowRuler - - Sidebar - - SidebarWidth - 120 - VisibleRegion - {{0, 0}, {561, 705}} - Zoom - 1 - ZoomValues - - - Canvas 1 - 1 - 1 - - - - saveQuickLookFiles - YES - - diff --git a/doc/cs250/figs/filter.pdf b/doc/cs250/figs/filter.pdf deleted file mode 100644 index 2f7a5433..00000000 Binary files a/doc/cs250/figs/filter.pdf and /dev/null differ diff --git a/doc/cs250/figs/filtering.graffle b/doc/cs250/figs/filtering.graffle deleted file mode 100644 index b19cf31e..00000000 Binary files a/doc/cs250/figs/filtering.graffle and /dev/null differ diff --git a/doc/cs250/figs/filtering.pdf b/doc/cs250/figs/filtering.pdf deleted file mode 100644 index 8a444715..00000000 Binary files a/doc/cs250/figs/filtering.pdf and /dev/null differ diff --git a/doc/cs250/figs/forward.graffle b/doc/cs250/figs/forward.graffle deleted file mode 100644 index 0aef9ed6..00000000 Binary files a/doc/cs250/figs/forward.graffle and /dev/null differ diff --git a/doc/cs250/figs/forward.pdf b/doc/cs250/figs/forward.pdf deleted file mode 100644 index 7df01517..00000000 Binary files a/doc/cs250/figs/forward.pdf and /dev/null differ diff --git a/doc/cs250/figs/lines-pie.py b/doc/cs250/figs/lines-pie.py deleted file mode 100755 index ef45290c..00000000 --- a/doc/cs250/figs/lines-pie.py +++ /dev/null @@ -1,41 +0,0 @@ -#!/usr/bin/env python - -from pylab import * - -# create figure -figwidth = 10 # inches -figheight = 10 # inches -figure(1, figsize=(figwidth, figheight)) -rcParams['font.size'] = 40.0 -rcParams['axes.titlesize'] = 24.0 -rcParams['xtick.labelsize'] = 24.0 -rcParams['legend.fontsize'] = 28.0 -# 568 aggregates -# 464 state -explode=(0.03, 0.06, 0.04, 0.05, 0.0) -colors=('r','b','y','m','g') -Ncols = 1 -plotheight = figwidth/Ncols -H = plotheight/figheight -W = 1.0 / Ncols -margin = 0.05 -left = [W*margin, W*(1+margin), W*(2+margin)] -bottom = H*2*margin -width = W*(1-2*margin) -height = H*(1-2*margin) - -tot = 5200.0 -ops = (1329.0 / tot)*100.0 -state = (464.0 / tot)*100.0 -aggregates = (568.0 / tot)*100.0 -backends = (1442.0 / tot)*100.0 -core = 100.0 - (backends + ops + aggregates + state) -fracs = [ops, state, aggregates, backends, core] -axes([left[0], bottom, width, height]) -patches = pie(fracs, colors=colors, explode=explode, autopct='%1.f%%', shadow=True) -# title('') -legend((patches[0], patches[0], patches[0], patches[0], patches[0], patches[0]), - ('ops', 'state', 'aggregates', 'backends', 'etc'), loc=(0,-.05)) - -savefig('linecount') -show() diff --git a/doc/cs250/figs/link-io.graffle b/doc/cs250/figs/link-io.graffle deleted file mode 100644 index 9824abba..00000000 Binary files a/doc/cs250/figs/link-io.graffle and /dev/null differ diff --git a/doc/cs250/figs/link-io.pdf b/doc/cs250/figs/link-io.pdf deleted file mode 100644 index 7e413c41..00000000 Binary files a/doc/cs250/figs/link-io.pdf and /dev/null differ diff --git a/doc/cs250/figs/max.png b/doc/cs250/figs/max.png deleted file mode 100644 index 377232bc..00000000 Binary files a/doc/cs250/figs/max.png and /dev/null differ diff --git a/doc/cs250/figs/mem-seq-read.graffle b/doc/cs250/figs/mem-seq-read.graffle deleted file mode 100644 index 393f889a..00000000 Binary files a/doc/cs250/figs/mem-seq-read.graffle and /dev/null differ diff --git a/doc/cs250/figs/mem-seq-read.pdf b/doc/cs250/figs/mem-seq-read.pdf deleted file mode 100644 index a5f7beb3..00000000 Binary files a/doc/cs250/figs/mem-seq-read.pdf and /dev/null differ diff --git a/doc/cs250/figs/mem-single-ported.graffle b/doc/cs250/figs/mem-single-ported.graffle deleted file mode 100644 index a00d180a..00000000 Binary files a/doc/cs250/figs/mem-single-ported.graffle and /dev/null differ diff --git a/doc/cs250/figs/mem-single-ported.pdf b/doc/cs250/figs/mem-single-ported.pdf deleted file mode 100644 index 31b70972..00000000 Binary files a/doc/cs250/figs/mem-single-ported.pdf and /dev/null differ diff --git a/doc/cs250/figs/mem.graffle b/doc/cs250/figs/mem.graffle deleted file mode 100644 index 9a85e811..00000000 Binary files a/doc/cs250/figs/mem.graffle and /dev/null differ diff --git a/doc/cs250/figs/mem.pdf b/doc/cs250/figs/mem.pdf deleted file mode 100644 index 931b55a4..00000000 Binary files a/doc/cs250/figs/mem.pdf and /dev/null differ diff --git a/doc/cs250/figs/milky-mist.jpg b/doc/cs250/figs/milky-mist.jpg deleted file mode 100644 index 9c13c0da..00000000 Binary files a/doc/cs250/figs/milky-mist.jpg and /dev/null differ diff --git a/doc/cs250/figs/modelsim.png b/doc/cs250/figs/modelsim.png deleted file mode 100644 index b9f72793..00000000 Binary files a/doc/cs250/figs/modelsim.png and /dev/null differ diff --git a/doc/cs250/figs/muls.graffle b/doc/cs250/figs/muls.graffle deleted file mode 100644 index ead37682..00000000 Binary files a/doc/cs250/figs/muls.graffle and /dev/null differ diff --git a/doc/cs250/figs/muls.pdf b/doc/cs250/figs/muls.pdf deleted file mode 100644 index 8498a587..00000000 Binary files a/doc/cs250/figs/muls.pdf and /dev/null differ diff --git a/doc/cs250/figs/mux2-circuit.graffle b/doc/cs250/figs/mux2-circuit.graffle deleted file mode 100644 index d5563315..00000000 Binary files a/doc/cs250/figs/mux2-circuit.graffle and /dev/null differ diff --git a/doc/cs250/figs/mux2-circuit.pdf b/doc/cs250/figs/mux2-circuit.pdf deleted file mode 100644 index 4cd85529..00000000 Binary files a/doc/cs250/figs/mux2-circuit.pdf and /dev/null differ diff --git a/doc/cs250/figs/mux2-component.graffle b/doc/cs250/figs/mux2-component.graffle deleted file mode 100644 index d0c9d87c..00000000 Binary files a/doc/cs250/figs/mux2-component.graffle and /dev/null differ diff --git a/doc/cs250/figs/mux2-component.pdf b/doc/cs250/figs/mux2-component.pdf deleted file mode 100644 index 3c88fba7..00000000 Binary files a/doc/cs250/figs/mux2-component.pdf and /dev/null differ diff --git a/doc/cs250/figs/mux2-forward-sel.graffle b/doc/cs250/figs/mux2-forward-sel.graffle deleted file mode 100644 index 30c482df..00000000 Binary files a/doc/cs250/figs/mux2-forward-sel.graffle and /dev/null differ diff --git a/doc/cs250/figs/mux2-forward-sel.pdf b/doc/cs250/figs/mux2-forward-sel.pdf deleted file mode 100644 index 41f83166..00000000 Binary files a/doc/cs250/figs/mux2-forward-sel.pdf and /dev/null differ diff --git a/doc/cs250/figs/mux2-function.graffle b/doc/cs250/figs/mux2-function.graffle deleted file mode 100644 index a11b1789..00000000 Binary files a/doc/cs250/figs/mux2-function.graffle and /dev/null differ diff --git a/doc/cs250/figs/mux2-function.pdf b/doc/cs250/figs/mux2-function.pdf deleted file mode 100644 index fe8c253f..00000000 Binary files a/doc/cs250/figs/mux2-function.pdf and /dev/null differ diff --git a/doc/cs250/figs/mux2-named-sel.graffle b/doc/cs250/figs/mux2-named-sel.graffle deleted file mode 100644 index 36bd3959..00000000 Binary files a/doc/cs250/figs/mux2-named-sel.graffle and /dev/null differ diff --git a/doc/cs250/figs/mux2-named-sel.pdf b/doc/cs250/figs/mux2-named-sel.pdf deleted file mode 100644 index 57c8b506..00000000 Binary files a/doc/cs250/figs/mux2-named-sel.pdf and /dev/null differ diff --git a/doc/cs250/figs/mux2.graffle b/doc/cs250/figs/mux2.graffle deleted file mode 100644 index 97a40326..00000000 --- a/doc/cs250/figs/mux2.graffle +++ /dev/null @@ -1,835 +0,0 @@ - - - - - ActiveLayerIndex - 0 - ApplicationVersion - - com.omnigroup.OmniGrafflePro - 138.33.0.157554 - - AutoAdjust - - BackgroundGraphic - - Bounds - {{0, 0}, {576, 733}} - Class - SolidGraphic - ID - 2 - Style - - shadow - - Draws - NO - - stroke - - Draws - NO - - - - CanvasOrigin - {0, 0} - ColumnAlign - 1 - ColumnSpacing - 36 - CreationDate - 2012-05-29 13:39:35 -0700 - Creator - Jonathan Bachrach - DisplayScale - 1 0/72 in = 1 0/72 in - GraphDocumentVersion - 8 - GraphicsList - - - Bounds - {{151.75, 230.5}, {43, 39}} - Class - ShapedGraphic - FitText - YES - Flow - Resize - FontInfo - - Color - - w - 0 - - Font - Helvetica - Size - 24 - - ID - 14 - Line - - ID - 13 - Position - 0.47222220897674561 - RotationType - 0 - - Shape - Rectangle - Style - - shadow - - Draws - NO - - stroke - - Draws - NO - Width - 2 - - - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1038\cocoasubrtf360 -{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural - -\f0\fs48 \cf0 in1} - - Wrap - NO - - - Class - LineGraphic - FontInfo - - Font - Helvetica - Size - 23 - - ID - 13 - Points - - {135, 250} - {216, 250} - - Style - - stroke - - HeadArrow - StickArrow - TailArrow - 0 - Width - 2 - - - - - Bounds - {{376.25, 196.5}, {44, 39}} - Class - ShapedGraphic - FitText - YES - Flow - Resize - FontInfo - - Color - - w - 0 - - Font - Helvetica - Size - 24 - - ID - 10 - Line - - ID - 9 - Position - 0.47222220897674561 - RotationType - 0 - - Shape - Rectangle - Style - - shadow - - Draws - NO - - stroke - - Draws - NO - Width - 2 - - - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1038\cocoasubrtf360 -{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural - -\f0\fs48 \cf0 out} - - Wrap - NO - - - Class - LineGraphic - FontInfo - - Font - Helvetica - Size - 23 - - ID - 9 - Points - - {360, 216} - {441, 216} - - Style - - stroke - - HeadArrow - StickArrow - TailArrow - 0 - Width - 2 - - - - - Bounds - {{151.75, 196.5}, {43, 39}} - Class - ShapedGraphic - FitText - YES - Flow - Resize - FontInfo - - Color - - w - 0 - - Font - Helvetica - Size - 24 - - ID - 8 - Line - - ID - 7 - Position - 0.47222220897674561 - RotationType - 0 - - Shape - Rectangle - Style - - shadow - - Draws - NO - - stroke - - Draws - NO - Width - 2 - - - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1038\cocoasubrtf360 -{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural - -\f0\fs48 \cf0 in0} - - Wrap - NO - - - Class - LineGraphic - FontInfo - - Font - Helvetica - Size - 23 - - ID - 7 - Points - - {135, 216} - {216, 216} - - Style - - stroke - - HeadArrow - StickArrow - TailArrow - 0 - Width - 2 - - - - - Bounds - {{152.75, 160.5}, {41, 39}} - Class - ShapedGraphic - FitText - YES - Flow - Resize - FontInfo - - Color - - w - 0 - - Font - Helvetica - Size - 24 - - ID - 6 - Line - - ID - 5 - Position - 0.47222220897674561 - RotationType - 0 - - Shape - Rectangle - Style - - shadow - - Draws - NO - - stroke - - Draws - NO - Width - 2 - - - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1038\cocoasubrtf360 -{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural - -\f0\fs48 \cf0 sel} - - Wrap - NO - - - Class - LineGraphic - FontInfo - - Font - Helvetica - Size - 23 - - ID - 5 - Points - - {135, 180} - {216, 180} - - Style - - stroke - - HeadArrow - StickArrow - TailArrow - 0 - Width - 2 - - - - - Bounds - {{216, 144}, {144, 144}} - Class - ShapedGraphic - FontInfo - - Font - Helvetica - Size - 23 - - ID - 3 - Shape - Rectangle - Style - - stroke - - Width - 2 - - - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1038\cocoasubrtf360 -{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural - -\f0\fs48 \cf0 Mux2} - - - - GridInfo - - ShowsGrid - YES - SnapsToGrid - YES - - GuidesLocked - NO - GuidesVisible - YES - HPages - 1 - ImageCounter - 1 - KeepToScale - - Layers - - - Lock - NO - Name - Layer 1 - Print - YES - View - YES - - - LayoutInfo - - Animate - NO - circoMinDist - 18 - circoSeparation - 0.0 - layoutEngine - dot - neatoSeparation - 0.0 - twopiSeparation - 0.0 - - LinksVisible - NO - MagnetsVisible - NO - MasterSheets - - ModificationDate - 2012-05-29 22:35:58 -0700 - Modifier - Jonathan Bachrach - NotesVisible - NO - Orientation - 2 - OriginVisible - NO - PageBreaks - YES - PrintInfo - - NSBottomMargin - - float - 41 - - NSLeftMargin - - float - 18 - - NSPaperSize - - coded - BAtzdHJlYW10eXBlZIHoA4QBQISEhAdOU1ZhbHVlAISECE5TT2JqZWN0AIWEASqEhAx7X05TU2l6ZT1mZn2WgWQCgRgDhg== - - NSRightMargin - - float - 18 - - NSTopMargin - - float - 18 - - - PrintOnePage - - QuickLookPreview - - JVBERi0xLjMKJcTl8uXrp/Og0MTGCjUgMCBvYmoKPDwgL0xlbmd0aCA2IDAgUiAvRmls - dGVyIC9GbGF0ZURlY29kZSA+PgpzdHJlYW0KeAGNlE1v2zAMhu/6Fe8xOUQV9WHL1wXr - ocAOQQzsMOwUNMAKt0OWFe3PLyn5Q6njbDAMKwlJiY8f5oQdTjB8hbpC7Rz+POI7XnC3 - PRMOZ1C6zgdsjA6Quwg8wlIF7wPIe7kVZ/OXeOOsB76fcp3tPm1hsN/ybpQ+bOQhGx6e - U5W+QqrEVfZqJ7lWzmDA+xd5NkYEqiXzSwvrcz1+bmyjnXd1QOSDts+4uydtFKE94gdW - 317X0obF6t2u8RPtA762CcD8SOS4qWjAhzNOMwVed2rP0YY7M9xZcaCiEavred5Qo660 - l4rEUSpVHH6JTlfoIPVn5ClYbZm78/AE18grOl7AUcVZqHYpOiSyn/hQ0M410V/w4ReS - +Zwf1yrz6Uo8w6ssNhkbFkziwIBJ1rkNo/6FaZ6XUQueEZNUV12PyVJzCxNJ476J8O4q - JpxYBXGd3RswjRoZbYyxaA8XQlGlDbmqngNTq18vZo32KTt0C5KrTA/J28guFZDEJXXd - JfaYXcqQyrxhnSFNUR3SL+omJJ4NzeORIPkFSNOAsirJJapVnrVFSFWk6ppVq9+vfz9B - Wmg3mRSmgbO87k1aHjhuVgZOYkcDU15vki8GLkWNJoXZwLEbcvFfDYVsEne0aNIEqTfJ - x2HgMiT13yaBTaIJ0u4D9tkpvwplbmRzdHJlYW0KZW5kb2JqCjYgMCBvYmoKNTAyCmVu - ZG9iagozIDAgb2JqCjw8IC9UeXBlIC9QYWdlIC9QYXJlbnQgNCAwIFIgL1Jlc291cmNl - cyA3IDAgUiAvQ29udGVudHMgNSAwIFIgL01lZGlhQm94IFswIDAgNTc2IDczM10KPj4K - ZW5kb2JqCjcgMCBvYmoKPDwgL1Byb2NTZXQgWyAvUERGIC9UZXh0IF0gL0NvbG9yU3Bh - Y2UgPDwgL0NzMiA5IDAgUiAvQ3MxIDggMCBSID4+IC9Gb250IDw8Ci9GMS4wIDEwIDAg - UiA+PiA+PgplbmRvYmoKMTEgMCBvYmoKPDwgL0xlbmd0aCAxMiAwIFIgL04gMSAvQWx0 - ZXJuYXRlIC9EZXZpY2VHcmF5IC9GaWx0ZXIgL0ZsYXRlRGVjb2RlID4+CnN0cmVhbQp4 - AYVST0gUURz+zTYShIhBhXiIdwoJlSmsrKDadnVZlW1bldKiGGffuqOzM9Ob2TXFkwRd - ojx1D6JjdOzQoZuXosCsS9cgqSAIPHXo+83s6iiEb3k73/v9/X7fe0RtnabvOylBVHND - lSulp25OTYuDHylFHdROWKYV+OlicYyx67mSv7vX1mfS2LLex7V2+/Y9tZVlYCHqLba3 - EPohkWYAH5mfKGWAs8Adlq/YPgE8WA6sGvAjogMPmrkw09GcdKWyLZFT5qIoKq9iO0mu - +/m5xr6LtYmD/lyPZtaOvbPqqtFM1LT3RKG8D65EGc9fVPZsNRSnDeOcSEMaKfKu1d8r - TMcRkSsQSgZSNWS5n2pOnXXgdRi7XbqT4/j2EKU+yWCoibXpspkdhX0AdirL7BDwBejx - smIP54F7Yf9bUcOTwCdhP2SHedatH/YXrlPge4Q9NeDOFK7F8dqKH14tAUP3VCNojHNN - xNPXOXOkiO8x1BmY90Y5pgsxd5aqEzeAO2EfWapmCrFd+67qJe57AnfT4zvRmzkLXKAc - SXKxFdkU0DwJWBR9i7BJDjw+zh5V4HeomMAcuYnczSj3HtURG2ejUoFWeo1Xxk/jufHF - +GVsGM+Afqx213t8/+njFXXXtj48+Y163DmuvZ0bVWFWcWUL3f/HMoSP2Sc5psHToVlY - a9h25A+azEywDCjEfwU+l/qSE1Xc1e7tuEUSzFA+LGwluktUbinU6j2DSqwcK9gAdnCS - xCxaHLhTa7o5eHfYInpt+U1XsuuG/vr2evva8h5tyqgpKBPNs0RmlLFbo+TdeNv9ZpER - nzg6vue9ilrJ/klFED+FOVoq8hRV9FZQ1sRvZw5+G7Z+XD+l5/VB/TwJPa2f0a/ooxG+ - DHRJz8JzUR+jSfCwaSHiEqCKgzPUTlRjjQPiKfHytFtkkf0PQBn9ZgplbmRzdHJlYW0K - ZW5kb2JqCjEyIDAgb2JqCjcwNAplbmRvYmoKOSAwIG9iagpbIC9JQ0NCYXNlZCAxMSAw - IFIgXQplbmRvYmoKMTMgMCBvYmoKPDwgL0xlbmd0aCAxNCAwIFIgL04gMyAvQWx0ZXJu - YXRlIC9EZXZpY2VSR0IgL0ZpbHRlciAvRmxhdGVEZWNvZGUgPj4Kc3RyZWFtCngBhVTP - axNBFP42bqnQIghaaw6yeJAiSVmraEXUNv0RYmsM2x+2RZBkM0nWbjbr7ia1pYjk4tEq - 3kXtoQf/gB568GQvSoVaRSjeqyhioRct8c1uTLal6sDOfvPeN+99b3bfAA1y0jT1gATk - DcdSohFpbHxCavyIAI6iCUE0JVXb7E4kBkGDc/l759h6D4FbVsN7+3eyd62a0raaB4T9 - QOBHmtkqsO8XcQpZEgKIPN+hKcd0CN/j2PLsjzlOeXjBtQ8rPcRZInxANS3Of024U80l - 00CDSDiU9XFSPpzXi5TXHQdpbmbGyBC9T5Cmu8zuq2KhnE72DpC9nfR+TrPePsIhwgsZ - rT9GuI2e9YzVP+Jh4aTmxIY9HBg19PhgFbcaqfg1whRfEE0nolRx2S4N8Ziu/VbySoJw - kDjKZGGAc1pIT9dMbvi6hwV9JtcTr+J3VlHheY8TZ97U3e9F2gKvMA4dDBoMmg1IUBBF - BGGYsFBAhjwaMTSycj8jqwYbk3sydSRqu3RiRLFBezbcPbdRpN08/igicZRDtQiS/EH+ - Kq/JT+V5+ctcsNhW95Stm5q68uA7xeWZuRoe19PI43NNXnyV1HaTV0eWrHl6vJrsGj/s - V5cx5oI1j8RzsPvxLV+VzJcpjBTF41Xz6kuEdVoxN9+fbH87PeIuzy611nOtiYs3VpuX - Z/1qSPvuqryT5lX5T1718fxnzcRj4ikxJnaK5yGJl8Uu8ZLYS6sL4mBtxwidlYYp0m2R - +iTVYGCavPUvXT9beL1Gfwz1UZQZzNJUifd/wipkNJ25Dm/6j9vH/Bfk94rnnygCL2zg - yJm6bVNx7xChZaVuc64CF7/RffC2bmujfjj8BFg8qxatUjWfILwBHHaHeh7oKZjTlpbN - OVKHLJ+TuunKYlLMUNtDUlLXJddlSxazmVVi6XbYmdMdbhyhOUL3xKdKZZP6r/ERsP2w - Uvn5rFLZfk4a1oGX+m/AvP1FCmVuZHN0cmVhbQplbmRvYmoKMTQgMCBvYmoKNzM3CmVu - ZG9iago4IDAgb2JqClsgL0lDQ0Jhc2VkIDEzIDAgUiBdCmVuZG9iago0IDAgb2JqCjw8 - IC9UeXBlIC9QYWdlcyAvTWVkaWFCb3ggWzAgMCA2MTIgNzkyXSAvQ291bnQgMSAvS2lk - cyBbIDMgMCBSIF0gPj4KZW5kb2JqCjE1IDAgb2JqCjw8IC9UeXBlIC9DYXRhbG9nIC9P - dXRsaW5lcyAyIDAgUiAvUGFnZXMgNCAwIFIgPj4KZW5kb2JqCjIgMCBvYmoKPDwgL0xh - c3QgMTYgMCBSIC9GaXJzdCAxNyAwIFIgPj4KZW5kb2JqCjE3IDAgb2JqCjw8IC9QYXJl - bnQgMTggMCBSIC9Db3VudCAwIC9EZXN0IFsgMyAwIFIgL1hZWiAwIDczMyAwIF0gL1Rp - dGxlIChDYW52YXMgMSkKPj4KZW5kb2JqCjE4IDAgb2JqCjw8ID4+CmVuZG9iagoxNiAw - IG9iago8PCAvUGFyZW50IDE4IDAgUiAvQ291bnQgMCAvRGVzdCBbIDMgMCBSIC9YWVog - MCA3MzMgMCBdIC9UaXRsZSAoQ2FudmFzIDEpCj4+CmVuZG9iagoxOSAwIG9iago8PCAv - TGVuZ3RoIDIwIDAgUiAvTGVuZ3RoMSA4Mjg0IC9GaWx0ZXIgL0ZsYXRlRGVjb2RlID4+ - CnN0cmVhbQp4Ab1ZC3hU1bVe6zzmzCuTeSYzk5nMTCYzkydJyIOERHIIMwnPGBKEBAkm - gUDCQx6GaKjQaKGWiKhFefmqeosYigyBwgBq0YvFfrUttgoqttUK9vGZy729yFUhM3ed - MyFCvtaPfp9fz5m191r7ufa/1157zz5dq9e0QwL0Agt1c1tXLgL5cYkA6FiwvHVlXDZ+ - RnH/gu4ud1zmMwDYZYtWLl4el5WPAaidi5f1DNc3RQA06R3trQvj+XCV4pIOSojLWERx - esfyrnvisvEQxaXLViwYzjftIDl1ees9w/3DhyS772xd3h4v73JQnL5yxV1dcTlVyhdX - rm4fLo+NpN9vAClVBytABUtBAAb09DYDCH9RO4GjXCmfnoU5mq13JFZ8DgalLN8x42E5 - /rnn5TNftF8NaB5VfkkJqmvlpViRGc0E0CLlD2oeHcmR61Ggi0BDdgSmEFUSFRNlZ0+0 - Qi/uhkeIfkTEQic+CD1Em4h2EnEj3IskHcUHBzileAx7wI5TRQ3nmmW2uaxqjeu3EVQc - etr1vvWT42ij2fsYbQMJoJqoxh/hM7AQXPhj8OFamAwZuOtg5jJXC2W9CCuJeolYOUR8 - cSB1rOtVzAEfh1THD6kcHnb9uSDXdaEgwuCA6/VAhKPotVSSxETXCefTrp85F7teJdob - z+rPpBKHXS86l7m2pkZw14Drh84IUp1H49EaJ1U97Fqeuc21sEDOn74twuwdcJVR/mxR - 4yop9biKneddeYGIEknOdU53ZRX8ypVOFamYmxr1iQaXw7nVNZ6yUp2hwHii49iPT0AW - PjHgm+o6RiwN9+CUzNJtEfzOwckZBb4IrhVLJmdsy5wc8GVOd/kyqwMB4me/KWwQbhcm - CmOFbCFD8AseIUUwK41KvVKn1CrVSqVSiOBPBipdiuO4FyoJlr0HlQolH8GXKJE7jvvk - xH1HlJySUYLSHIl9RMaLYI7g3kN6iSPmsELmFBHcdzCetE90cRLHyRl6RuIpoBAYVDIw - FcL4UEQBG5O6K62VxgmGsurgPwta5JxrYfY/f6zoDG+b1tAY7nc2hcdKTMzZdK249Rrz - T+OuNZTVXpWdPa2+52D3yiWLQu3eUIs31E7UEn6wu8Ma7m1zuw8sWSlluMOsv6VtQYcU - t7aHV3rbg+El3qD7QLdcb1T2Iim72xs8AItCsxoPLBLbgwPdYnfI2xpsOthWtbr5hr42 - jfS1uuof9FUlNbZa6qtNrjeqr2Ypu03qq1nqq1nqq01sk/uSBh/qbKi6q4us0x3qnOYO - ZzSEp8yc2xh2tzYFI7ibEoNrgD8Bev4VyOB7wc7lgQsg9j7RB1IcvS32KX8K9NHlsf9h - y2lSj0rERCsr4AQ8BE/AflDAHuIzYD7sgF/gElrb8+AQnMFUGEO+l4MITIe3MBZ7GxbB - f1D5LngdHocDoKU6y8FCuVvQF1tLskh8G2yIPQfpUArfh1egjFrdAoOxF2MHKbceboN+ - 2Ev1f4le5gBnir0UOw9KmEltbqCct2PTY/vBCDlQBXWUugFeRR/7QawDrFBO2j0Jz8Cz - 8Bp8hvfjoVhHrDt2OvYxmaoVHNBA7zo8hB+z+7nvx56M/S0WJSQyIIt6bYGt8Dy1v5/e - E+RaQ7gUu3ArPs6IzP3MIW4jnxwdIhwyoYbeyeSVf0AIHIWT8Hf4Ei8yVlbPdrFvxIpj - /wsamEajlEbSDt30PkDvFhrTcVRgPk7COlyHj+Hj+Dsmi7mNaWTuZu5hPmVr2XlsD/s7 - 7i5ugN/M71Boop/HjsdOxd6FZHDC7bAa1tPoXofTcAm+QpbacqAPy7EK59Pbi08wR/FZ - PMrU4Qk8zfTjH/ETvIhXGJ7RMhYmm+litjJ7mdeZX7Od7OPsTvaP7OfcBJ7hn+UvKHzC - uWhbdFP017Hy2MexL8jFKsFDM1MFtXAHtNJoV0IRfJdGsY/e/TRrJ+EN+IX8foIOGIQv - CAVAI9pxLM6gtxZvxUXYiU/jMXpflXW5zNBEMCrGwCQzDqaBaWOWM73Mu0wvm8JmsVPZ - uex+et9kz7BX2Cscz5k4C1fDTYHN3HJuF727uT3cAPcbvoyfwNfys/lefhO/mV3Av82f - UaxXbFEMKC4q/pvc4nRhhbCZZucXZLOvkS1//XCYTtqPhTthAQaxDbbRbDyLrdBH1rUQ - f0B4rYSMWDO7nq1h8skaXoXvkLXugnWwiZ0Hz8beY/vhLFnKMmqyF17gqsDJb6fZuR/y - yYqGXzEzKzMj4Pele9M8bnL5jhS7zZqcZDGbjAZ9glajVikFBc+xDEJOyFvd4g77W8Kc - 3zt5cq4ke1spofW6hBZayu5w9Y1lwm6pXitl3VBSpJKLRpUU4yXFkZKod1dARW6OO+R1 - h38V9LojOHdmI/EPBb1N7vCgzM+Q+UdkPoF4j4cquEPWjqA7jC3uULi6u6Mv1BLMzcGj - IsGhzs2RHIcIGqnhMExqXUcOFiZJJUJhuzcYCtu8xFMe6wu1LgzXzWwMBVM8niZKo6T6 - RuojN6czTHrCg9qF3oUPRkRoa5G41nmNYba1Kcy0SG0ZssPJ3mA4ee0F69fiNS60+brM - MOOrbm3vqw6LLQ8SuJLYIkmtm0ma1uCmZpmNTY1h3DishKTjEtJUUje+J/halrjDKm+V - t6NvSQuBC/WNA3bRLjvfMNQ1DthEmyzk5hy1ri/30OiP5k7MnSjF5R7r+nj85+/F0397 - Qoqt609+RPG0+hEAUELAO4X0DLsXyJ14SdlSKWgvhb4FpYQTPU1Iw+wkfSaFGbIZ1hfm - fVNaw70N19ToCMaVa1kSHFDZ7PImVNVE5Vv69ONppqi83uvu+5x26xbv4Gc3prQOpyh8 - +s9BypQmesRWwth6je+WNksfjbrD6u2Q5rdbnlOSvdbQdQkkS9BIOofNtIHXNXrC7iZK - oNNkzrQIqOoaDyBuaYpgbGMEgs6jdEZl75hP2TmSqXUGqX8ScnMoIctD3JgcdzX1XC3Z - irvP3TdlYZ+72t1BxsT55Jgy2vua8gjBhkbCCWZRj2JTygjb3tQ0ntrJk9qhKlS8r4la - WDLcAsVyUt4QFcrPoc2U9dc1zmwM9wZTwmKwiWaBzPdEXWP4BFluUxOVKhjRlDRe12kd - 1nks6VyQRfmF8Vbo7NJLTTT19UltNjR6PeETfX0pfdJ6i8sRhNEJ4nBCBKQiEuQR7K2j - uhR5PSnyHHi8HlKrScK0iEz6mkXRmf2bES4Z0ZtqjiNtS2SES78lhMtuBuHxN4Vw+Yim - NyBcQTqXSwjf8u9DeMINCFd+M8LiiN6k5ETSVpQRrvqWEJ50MwgHbwrh0IimNyBcTTqH - JIRr/n0IT74B4SnfjPDUEb1JyWmk7VQZ4enfEsIzbgbh2ptC+NYRTW9AuI50vlVCeOa/ - D+H6GxBu+GaEZ43oTUreRtrOkhGe/S0hPOdmEG68KYSbRjS9AeG5pHOThPDtIwiLKWG4 - 3g/3jnK78K075nnXQU4nJd4IVdxdIBKdlGJFP2yneDKegg1Em4jfQFROf7irmDJIJr6X - eA1VvXbno6V/Ik+SnA9T5D/iLPH/+kON/ksPP1xaIccChUraseOPmvTTymzCcEoRPAdv - 4iz8iOln3mO+Ymezv+Ze4qJ8I/9DKsHQfwvgTtN/Upbutirj903KPDoUECn1dAF3mkiS - iWc/jABHBMQLH8IxqgEwO/sYtcJTnF9QaPAYAkRV3JbI1T/xr3w1KcLNuEJ3F1RCjL3P - OfgdkEj/AFeJyQ/wWK20FCfyjmIhwVjKrrCWalJrnPruk9Z3BocGoXKwcrAgf1KPWAQp - CX702f0qH+9P0lkzwAzGDExREqdXEJestWSgiaHApnZkgIGjQPo/jlIgP/fRdV1ykkEv - MB53wG8oGmf0GEsMRYw3jTGYk5MKWfHeljnro3+KRtd3VnZjcd/ue/Y9szVv8kv8jgsH - om9FP/xZ9L8+Oo7ll/Zj9VcXvsD6S1gefTf6+3MbfymBjPQvDJh3CU8leA8oMYKFopbj - BC0nbONBXaOSBnXy3aEyqKy89KuCfFPxBBxXaPAaTv7nLv+WE+zlPlPT7q/uZC/LbYk0 - H6n8U5AGu8XaEq6am8Mvdd6ZujZ1Az7AKLOUc21Lbffa7nX81MZDGiZyDp3NIzhsdPfG - uxIT00zqYhPvdq3xpGk93xVKk1ak6QKJ97lK09JrvHFwLw3qPx88D5UVQxWVgwZjWZ4x - uQwpNpaVGSiAZhl2B2fT+gx+jVGXASqzQOByCXp1BiotFBC+er2ML0FbYqzEknElxUV+ - b5qgELzEe8YaLWZBkYgKSvBYPFM3vnbivqL6beuO1vi5I2zVGsy4/ElP9U83tZUutLO6 - q5lH0bhyxbTihqXrtm6etvF49+no5ed/sramfXpJwZwl/TIu2+m2NJns1AS/FJuCOI1l - FKhik9DGnkXehA7WrEnRzsFG9h08x76jOadVc2ouIcR8n+FmMtsZJlOdkVCqLk2oYeYw - 3YzgW5igZlgji4xGa2QVSktysp3j6ILuCTFB7WI1iiEtMkMJLiOlHDaBzdy90ppdq79U - MWPovO1SWRn9rOeHKmr1ofbgp1CZXFFZQTjSFdeBBG0E+w8xyKg1xAwwDPsAP2PM2iFu - 3ckH+HhckA/Nq1fh6uZVJo8KPWQKRSXF6EWLOcli8G5HJ+7G59H+ChdtfiM6l3+Vf+WK - n/vgq0nsgtzTd1/J5M7mlvy+6OpThAsLk2MfcHb6d+6gmxwfasWe7cqd9hdcLK9jEnmz - RWdMtJhFrWhWZtpxmuYwewp/zp5KeU/5vuqM6z3vX5L/4tWcMpwyMvOUvCc9cVeSM71M - IQhJHqdDUDuTND5hu+MFxxHHWQfnS0r0OXibWisYyKacAd4eSB8jBGw2f+Adz+5mugms - vUTo1Oovzxh8Z0i2J7IpMrBmMnxazsSRzeklm5NNrBq8HM/S1QfynMLlN+iNepPerOcU - Wl9aSrof3OD0Y6pTlSz4QWPR+TFB57V7KImnQGlV+4Es0g/xxa6vIJskys7KzroPVzXD - quZmSEqm1+JJxcKx40rGFeqQzFHhTQODHgrRHyCDVQjIHDpTWmLUX73IP7L9oVn55gPC - rQX1PRPr34z+Da1/QpcmY+q+e/fw6OVqlt42c9nU555/o7mkpvzRMXUOPc2ZAhmsivrX - VN9/sA+lDwjk6zaQUygf9qklokO4wJGTULBqFRkZlc8UWLApVf2etioZtIoZJ4cqTtbG - LamyonIGeT6T5CAKLd4NR+jhsq6c4V95S14Hm6jtW+S2M0ULGYCap0apTWBtHH9dk2Sb - ww3GG9t06JDkkK/pxw6SzdjADvPFgiOKUwqGU5gVAXO3okvgzVrGbNU7eQEUVo3aLtjt - oM1U2R04xpppA1uKgz4cHPxa+eEpp+mlea6gqTaUlaE0x9CMzaZCywSCn6ZBsnIJcpoD - HZKEG/ZO7+84X5dzxJm/XsycWpqbcghf4PJ2zK9/Zs5zQzOZ59sqFiYkVRWv6hz6DSlL - tl5Oe4iHq6Udzkq6PyIW7lBu0+9M+jG3R7lb/2JSRPmm8ix3QfdXs3a8UuG0ClqnUWMT - bDYLE0i0p6gCFps9JYKqg57Vw9Y6KBtrXPNrG04ObfV+jUlFlmVg/CgkE8cnEKc2a/2A - egqUSQo/sjoKpP0lvtGQJ0w3FssjVNA6LjSSlTGeNCgmWxOYjzbmTz/2423bnqfL2qvR - //t99Coa/6zowsTd2+Y/dnVg73n2g+hn0UvRoehLmH0VdSjyZEdVsbPsYW4a3e7m4Rjx - 4VLVDn6bcad5h2VHliIj3Rco8VR7atJrArPT5wQWpS/292h7Enp03d6u9C5fl3936p4c - E0tLh8/lxpjAbklJdlgtueYxGYmaTqXfV+JjfGkJai7bZP25w2kSOOeYXdmaPEGl0zMC - 5Hny7C5rkjWQPCHDLwQy7AU6V0A/AQJjbPkFAyPrffDSUJkE4lCZnjha2mVleRSSCUiL - njCl5Z5ctkpe8NMxl/FbaCv36FweUNFnE2Rz6IKTzyLOaaS0FLPVg+7ENA940nQJyoDa - g36fSo25nIe+lVGQanB40JZEgbzs9RW05uXght1esjta+YVjaVcK+POkpV5cVCJZoeCN - L3sL7fsulLyDmRyCP4AXlb7gnoU7bgnc9fCmiV3njv596SSmn/dP2LmoM5RRe/frVZ3v - /+HiKQGPYN3c/Dlzbg+lk6dMy5py346Xt8ztuGVsTa1YnWUzOfNyQo89fPr9HzFf0pJP - jl1kVPxcstb6nyaMUZ/Q0dmgUvRxSWXJrEKnNthp6dINciZYdJZE1sUy7NUkm81+1bN4 - 3bA3bS47KTvN+FrOo/U1Y6hiUD90Xl7U5B/kA8zYknEWHdI4ig3e4sI9h/fu9VsKElLN - rkmB9XMffZSfG31361Co1KRBZotKed9i5o2tsh/ojX3C/oGWVjJpOF8cHzG/aWZUJqXZ - ZrKZMxR3s2cFQQm8Tg2KBDVPa8kqWK2aJBpJplZjt2OmpOxvrzmCGdJikrZHmn7JEwyS - spJBxP0AxhWlc4KBPNs42Q/TrBh8WGrP/97LQd+hfsZbtHjrhYZc3M/lDZXVF7XsmfsU - o7vy9tO3ZM3aWb+Jec8unbXo/M1+zOVRXCydVumbh3Q8ZYkU0jE1TzqN0smYOj5GX0Su - ccphLr/AVJiCySr00g9T/3r5y3PR7djzafRyNHoee7i86APYww9dGTqHP4zeyfgIJmpP - fmLt9B3hHz06SjTRqdRC/wMm0xeHW+l7SD3MhjnQSN8LpAfpSwnKnIK+HUN1/ezqOQ3Z - k9uXdbd3dS5olUvI2RSIRNOJ5hFJ99v3Em0mkv5n/IToZaK3iD4k+ozoKjWvjQ0/JMMI - j6TPjXLBKHnsKHnGKFke73XtdY7KXzZKvnOUvGKUfNcoWf7ufl37a0bl3yPJ/w+Th3v+ - CmVuZHN0cmVhbQplbmRvYmoKMjAgMCBvYmoKNTE5NAplbmRvYmoKMjEgMCBvYmoKPDwg - L1R5cGUgL0ZvbnREZXNjcmlwdG9yIC9Bc2NlbnQgNzcwIC9DYXBIZWlnaHQgNzE3IC9E - ZXNjZW50IC0yMzAgL0ZsYWdzIDMyCi9Gb250QkJveCBbLTk1MSAtNDgxIDE0NDUgMTEy - Ml0gL0ZvbnROYW1lIC9GUlZGV1MrSGVsdmV0aWNhIC9JdGFsaWNBbmdsZSAwCi9TdGVt - ViAwIC9NYXhXaWR0aCAxNTAwIC9YSGVpZ2h0IDU0MCAvRm9udEZpbGUyIDE5IDAgUiA+ - PgplbmRvYmoKMjIgMCBvYmoKWyA1NTYgNTU2IDU1NiAwIDAgMCAwIDAgMCAwIDAgMCAw - IDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgODMzIDAgMAowIDAgMCAwIDAg - MCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCA1NTYgMCAwIDAgMjIyIDAgMCAy - MjIgMCA1NTYgNTU2CjAgMCAwIDUwMCAyNzggNTU2IDAgMCA1MDAgXQplbmRvYmoKMTAg - MCBvYmoKPDwgL1R5cGUgL0ZvbnQgL1N1YnR5cGUgL1RydWVUeXBlIC9CYXNlRm9udCAv - RlJWRldTK0hlbHZldGljYSAvRm9udERlc2NyaXB0b3IKMjEgMCBSIC9XaWR0aHMgMjIg - MCBSIC9GaXJzdENoYXIgNDggL0xhc3RDaGFyIDEyMCAvRW5jb2RpbmcgL01hY1JvbWFu - RW5jb2RpbmcKPj4KZW5kb2JqCjIzIDAgb2JqCihNYWMgT1MgWCAxMC42LjggUXVhcnR6 - IFBERkNvbnRleHQpCmVuZG9iagoyNCAwIG9iagooRDoyMDEyMDUzMDA1MzYwMVowMCcw - MCcpCmVuZG9iagoxIDAgb2JqCjw8IC9Qcm9kdWNlciAyMyAwIFIgL0NyZWF0aW9uRGF0 - ZSAyNCAwIFIgL01vZERhdGUgMjQgMCBSID4+CmVuZG9iagp4cmVmCjAgMjUKMDAwMDAw - MDAwMCA2NTUzNSBmIAowMDAwMDA4OTg3IDAwMDAwIG4gCjAwMDAwMDI3NDAgMDAwMDAg - biAKMDAwMDAwMDYxNyAwMDAwMCBuIAowMDAwMDAyNTkxIDAwMDAwIG4gCjAwMDAwMDAw - MjIgMDAwMDAgbiAKMDAwMDAwMDU5OCAwMDAwMCBuIAowMDAwMDAwNzIxIDAwMDAwIG4g - CjAwMDAwMDI1NTUgMDAwMDAgbiAKMDAwMDAwMTY1OSAwMDAwMCBuIAowMDAwMDA4NzE4 - IDAwMDAwIG4gCjAwMDAwMDA4MzEgMDAwMDAgbiAKMDAwMDAwMTYzOSAwMDAwMCBuIAow - MDAwMDAxNjk1IDAwMDAwIG4gCjAwMDAwMDI1MzUgMDAwMDAgbiAKMDAwMDAwMjY3NCAw - MDAwMCBuIAowMDAwMDAyOTAzIDAwMDAwIG4gCjAwMDAwMDI3ODggMDAwMDAgbiAKMDAw - MDAwMjg4MSAwMDAwMCBuIAowMDAwMDAyOTk2IDAwMDAwIG4gCjAwMDAwMDgyODAgMDAw - MDAgbiAKMDAwMDAwODMwMSAwMDAwMCBuIAowMDAwMDA4NTI2IDAwMDAwIG4gCjAwMDAw - MDg4OTMgMDAwMDAgbiAKMDAwMDAwODk0NSAwMDAwMCBuIAp0cmFpbGVyCjw8IC9TaXpl - IDI1IC9Sb290IDE1IDAgUiAvSW5mbyAxIDAgUiAvSUQgWyA8NDUzMjA5MGYxZWY3MWJm - YjYyZTBlZDY0M2M0ZTgwZmM+Cjw0NTMyMDkwZjFlZjcxYmZiNjJlMGVkNjQzYzRlODBm - Yz4gXSA+PgpzdGFydHhyZWYKOTA2MgolJUVPRgoxIDAgb2JqCjw8L0F1dGhvciAoSm9u - YXRoYW4gQmFjaHJhY2gpL0NyZWF0aW9uRGF0ZSAoRDoyMDEyMDUyOTIwMzkwMFopL0Ny - ZWF0b3IgKE9tbmlHcmFmZmxlIFByb2Zlc3Npb25hbCA1LjMuNikvTW9kRGF0ZSAoRDoy - MDEyMDUzMDA1MzUwMFopL1Byb2R1Y2VyIDIzIDAgUiAvVGl0bGUgKG11eDIpPj4KZW5k - b2JqCnhyZWYKMSAxCjAwMDAwMDk3MTkgMDAwMDAgbiAKdHJhaWxlcgo8PC9JRCBbPDQ1 - MzIwOTBmMWVmNzFiZmI2MmUwZWQ2NDNjNGU4MGZjPiA8NDUzMjA5MGYxZWY3MWJmYjYy - ZTBlZDY0M2M0ZTgwZmM+XSAvSW5mbyAxIDAgUiAvUHJldiA5MDYyIC9Sb290IDE1IDAg - UiAvU2l6ZSAyNT4+CnN0YXJ0eHJlZgo5ODk4CiUlRU9GCg== - - QuickLookThumbnail - - TU0AKgAAA6qAP+BP8AQWDQeEQmFQuGQpvw8AMGJAASRWGxeMRmNRuNQ9vgAaSEACmSRy - TRyBwSTyuNNeXAB8zEADCaSybTecQaXNeYTKaDCc0GU0GiACdz18zOa0WmU2D0eY0mf0 - 6V0OqSyoT6l1euTes1Kt12MVaxRuv0qgWW1WaX1G0WuL2SmtG6AAX3eEOi9AAEX0AObA - AB9YO33DDQyz1PDwpnY1/tjIQgQ5MAA3LUaXjvNABe50ABXQAB06MAErTABd6kAOXWAA - Ba8ACjZAANbXC4vcQXE2HcgC5QtrcEAMbibTbNrkAAI8sAAHnAAvdGENvqQh8dcAP3tb - fe4fd2nu76Bxhw+UAMz0AAf+sAL73AARfEAAX6Xa8Rjv+HF/n9b/wv4/S4QA7r/O7AcA - rLA7cwKhBuwcAAPwiAACQohBmwu+D5OWCKMwUjZVxAAAqRGABiRMAASxSAAMRYjJxRez - CeCPGagw8k5yRwAAOR2k0GIOY8gNW1p6yIAARyOAB+SUADkG0AAzSghCJGCABsytFEVQ - 27iTD5LoACTMAAFfMYACRMzjA0v7AnpNj5vqBc4ABHByAAJs7AAB88ptA7ynDEsThjQI - AL0dDmueYtEAANFFgAClHAAdVIgAV1KTQADGmcx7IoOqZq08AB3VDMszl1UoAUCGIAGf - VYADBVwARAVYAHhWkjSQB1cL4vzFJWTtfAAeVgqQAAWWKAFcAdGIAHHZgACNZ9hucAIA - CJaqgmFbAAUQYoABBbwAA9cIAHBcgAC1c4AFNdQAH3dthr6BAAC/ec/mJZQLXxHUeR8g - zgmsAB7YDLASgAduDAAuhogAGuGX0DkOrarTwJPVZn1BUUU4I14BABbBhAACeQ5BkS3T - mAB/ZROs7gZlk94isGJgAdmZva94e5vS7GgBNh6JGkoM6Az7QrG8cEWUt1eaMsUbMPfj - 95fLelKvpjDacAEHG7CEJQoAiEG9r9LXhiCeaQ3mpKpqi4atIBjyEcoASIetRiQABEbs - AA9bzoQKoQYG/ABTxqgAE/CUbR+k7PtGocQ3NMU0bCEU7T9QnduerwfYJ5AAHXOOU5lY - 2BYTZBQAAFdNNwC6jxKmbSterX9gGBYyAB39rYYO9x0vTvxxezdWovWrVqzDeD36V+Ks - XhwF3uY+MonkK75S1+h5yW+ZAPpLUo/MgADfveqpuZnZyPfMX7KysGfVtUS+nU/AouUH - 8kCRdMBXsaL9/8/0m3z/3/z+iAgADgEAAAMAAAABADYAAAEBAAMAAAABABwAAAECAAMA - AAAEAAAEWAEDAAMAAAABAAUAAAEGAAMAAAABAAIAAAERAAQAAAABAAAACAESAAMAAAAB - AAEAAAEVAAMAAAABAAQAAAEWAAMAAAABABwAAAEXAAQAAAABAAADogEcAAMAAAABAAEA - AAE9AAMAAAABAAIAAAFSAAMAAAABAAEAAAFTAAMAAAAEAAAEYAAAAAAACAAIAAgACAAB - AAEAAQAB - - ReadOnly - NO - RowAlign - 1 - RowSpacing - 36 - SheetTitle - Canvas 1 - SmartAlignmentGuidesActive - YES - SmartDistanceGuidesActive - YES - UniqueID - 1 - UseEntirePage - - VPages - 1 - WindowInfo - - CurrentSheet - 0 - ExpandedCanvases - - - name - Canvas 1 - - - Frame - {{446, 4}, {710, 874}} - ListView - - OutlineWidth - 142 - RightSidebar - - ShowRuler - - Sidebar - - SidebarWidth - 120 - VisibleRegion - {{0, 0}, {561, 705}} - Zoom - 1 - ZoomValues - - - Canvas 1 - 1 - 1 - - - - saveQuickLookFiles - YES - - diff --git a/doc/cs250/figs/mux2.pdf b/doc/cs250/figs/mux2.pdf deleted file mode 100644 index 8db530fc..00000000 Binary files a/doc/cs250/figs/mux2.pdf and /dev/null differ diff --git a/doc/cs250/figs/myfloat.graffle b/doc/cs250/figs/myfloat.graffle deleted file mode 100644 index b9ad6373..00000000 Binary files a/doc/cs250/figs/myfloat.graffle and /dev/null differ diff --git a/doc/cs250/figs/myfloat.pdf b/doc/cs250/figs/myfloat.pdf deleted file mode 100644 index 314d0cc7..00000000 Binary files a/doc/cs250/figs/myfloat.pdf and /dev/null differ diff --git a/doc/cs250/figs/odd-filter.graffle b/doc/cs250/figs/odd-filter.graffle deleted file mode 100644 index 4a8fce22..00000000 Binary files a/doc/cs250/figs/odd-filter.graffle and /dev/null differ diff --git a/doc/cs250/figs/odd-filter.pdf b/doc/cs250/figs/odd-filter.pdf deleted file mode 100644 index c4102359..00000000 Binary files a/doc/cs250/figs/odd-filter.pdf and /dev/null differ diff --git a/doc/cs250/figs/parameterized-filter.graffle b/doc/cs250/figs/parameterized-filter.graffle deleted file mode 100644 index 4d726c6c..00000000 Binary files a/doc/cs250/figs/parameterized-filter.graffle and /dev/null differ diff --git a/doc/cs250/figs/parameterized-filter.pdf b/doc/cs250/figs/parameterized-filter.pdf deleted file mode 100644 index 9d2882ed..00000000 Binary files a/doc/cs250/figs/parameterized-filter.pdf and /dev/null differ diff --git a/doc/cs250/figs/parity.graffle b/doc/cs250/figs/parity.graffle deleted file mode 100644 index 84c9d908..00000000 Binary files a/doc/cs250/figs/parity.graffle and /dev/null differ diff --git a/doc/cs250/figs/parity.pdf b/doc/cs250/figs/parity.pdf deleted file mode 100644 index 80ef3fb2..00000000 Binary files a/doc/cs250/figs/parity.pdf and /dev/null differ diff --git a/doc/cs250/figs/pass-through-filter.graffle b/doc/cs250/figs/pass-through-filter.graffle deleted file mode 100644 index 16a065b1..00000000 Binary files a/doc/cs250/figs/pass-through-filter.graffle and /dev/null differ diff --git a/doc/cs250/figs/pass-through-filter.pdf b/doc/cs250/figs/pass-through-filter.pdf deleted file mode 100644 index 8bcc04c7..00000000 Binary files a/doc/cs250/figs/pass-through-filter.pdf and /dev/null differ diff --git a/doc/cs250/figs/plink-io.graffle b/doc/cs250/figs/plink-io.graffle deleted file mode 100644 index 3f271bdf..00000000 Binary files a/doc/cs250/figs/plink-io.graffle and /dev/null differ diff --git a/doc/cs250/figs/plink-io.pdf b/doc/cs250/figs/plink-io.pdf deleted file mode 100644 index 96610593..00000000 Binary files a/doc/cs250/figs/plink-io.pdf and /dev/null differ diff --git a/doc/cs250/figs/process.graffle b/doc/cs250/figs/process.graffle deleted file mode 100644 index 015465da..00000000 --- a/doc/cs250/figs/process.graffle +++ /dev/null @@ -1,653 +0,0 @@ - - - - - ActiveLayerIndex - 0 - ApplicationVersion - - com.omnigroup.OmniGrafflePro - 138.33.0.157554 - - AutoAdjust - - BackgroundGraphic - - Bounds - {{0, 0}, {576, 733}} - Class - SolidGraphic - ID - 2 - Style - - shadow - - Draws - NO - - stroke - - Draws - NO - - - - CanvasOrigin - {0, 0} - ColumnAlign - 1 - ColumnSpacing - 36 - CreationDate - 2012-05-28 16:29:50 -0700 - Creator - Jonathan Bachrach - DisplayScale - 1 0/72 in = 1 0/72 in - GraphDocumentVersion - 8 - GraphicsList - - - Bounds - {{299.773, 166.5}, {43, 27}} - Class - ShapedGraphic - FitText - YES - Flow - Resize - FontInfo - - Color - - w - 0 - - Font - Helvetica - Size - 14 - - ID - 11 - Line - - ID - 9 - Position - 0.45454546809196472 - RotationType - 0 - - Shape - Rectangle - Style - - shadow - - Draws - NO - - stroke - - Draws - NO - Width - 2 - - - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1038\cocoasubrtf360 -{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural - -\f0\fs28 \cf0 finish} - - Wrap - NO - - - Bounds - {{160.748, 166.5}, {38, 27}} - Class - ShapedGraphic - FitText - YES - Flow - Resize - FontInfo - - Color - - w - 0 - - Font - Helvetica - Size - 14 - - ID - 10 - Line - - ID - 8 - Position - 0.50349652767181396 - RotationType - 0 - - Shape - Rectangle - Style - - shadow - - Draws - NO - - stroke - - Draws - NO - Width - 2 - - - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1038\cocoasubrtf360 -{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural - -\f0\fs28 \cf0 start} - - Wrap - NO - - - Class - LineGraphic - FontInfo - - Font - Helvetica - Size - 13 - - ID - 9 - Points - - {289, 180} - {360, 180} - - Style - - stroke - - HeadArrow - StickArrow - TailArrow - 0 - Width - 2 - - - Tail - - ID - 7 - - - - Class - LineGraphic - FontInfo - - Font - Helvetica - Size - 13 - - Head - - ID - 7 - - ID - 8 - Points - - {144, 180} - {215, 180} - - Style - - stroke - - HeadArrow - StickArrow - TailArrow - 0 - Width - 2 - - - - - Bounds - {{216, 144}, {72, 72}} - Class - ShapedGraphic - FontInfo - - Font - Helvetica - Size - 13 - - ID - 7 - Shape - Rectangle - Style - - stroke - - Width - 2 - - - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1038\cocoasubrtf360 -{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural - -\f0\fs28 \cf0 Process} - - - - GridInfo - - ShowsGrid - YES - SnapsToGrid - YES - - GuidesLocked - NO - GuidesVisible - YES - HPages - 1 - ImageCounter - 1 - KeepToScale - - Layers - - - Lock - NO - Name - Layer 1 - Print - YES - View - YES - - - LayoutInfo - - Animate - NO - circoMinDist - 18 - circoSeparation - 0.0 - layoutEngine - dot - neatoSeparation - 0.0 - twopiSeparation - 0.0 - - LinksVisible - NO - MagnetsVisible - NO - MasterSheets - - ModificationDate - 2012-05-28 16:35:30 -0700 - Modifier - Jonathan Bachrach - NotesVisible - NO - Orientation - 2 - OriginVisible - NO - PageBreaks - YES - PrintInfo - - NSBottomMargin - - float - 41 - - NSLeftMargin - - float - 18 - - NSPaperSize - - coded - BAtzdHJlYW10eXBlZIHoA4QBQISEhAdOU1ZhbHVlAISECE5TT2JqZWN0AIWEASqEhAx7X05TU2l6ZT1mZn2WgWQCgRgDhg== - - NSRightMargin - - float - 18 - - NSTopMargin - - float - 18 - - - PrintOnePage - - QuickLookPreview - - JVBERi0xLjMKJcTl8uXrp/Og0MTGCjUgMCBvYmoKPDwgL0xlbmd0aCA2IDAgUiAvRmls - dGVyIC9GbGF0ZURlY29kZSA+PgpzdHJlYW0KeAGNUstOwzAQvPsr5tgc6nr9TK5UcOiJ - qpE4IA6oagVVW9QGib/lW1g7ThMpQSDHysbZnZn1zgVrXKB4ueARjMF1hyecsVg2hG0D - SqvZYq6kQ9yDxD00eTgKCJofwbV8hC+uWfE+tCjLTSJQ2CyZi9LHPL4i3faUMMjaFiPy - b7AWzK8jvwJzD6q003Au1d3VIJvRLObaSV16MnAssj5h8UBSgUS9xzNmj9ePIvagMdvu - uqhpCrygXuG+Tvcw1hZ1UanAKpWWJGJ8jAKZd8X7MNQ26IhkGNal+NhigIKXVsS+u6zb - n9JIn/G7Kxz03uOXVUY3NvxblXH+pirVZVU5zqr6rCO6rF7VyBbk+U5tybduFUwJHeIE - 93HyWkzMj0IlQ8qfHCIxFZkQpofYfBZsQR7hazfBK5/0Exyp01UldWBNUZ01rK716G/u - Mppy/rQ6L40lQ1mdyBYDW2z2XaA+jIz0B2CV8FQVAUXv2QjInj13Xb53QfM2bHf9A4Vl - yK4KZW5kc3RyZWFtCmVuZG9iago2IDAgb2JqCjM4MwplbmRvYmoKMyAwIG9iago8PCAv - VHlwZSAvUGFnZSAvUGFyZW50IDQgMCBSIC9SZXNvdXJjZXMgNyAwIFIgL0NvbnRlbnRz - IDUgMCBSIC9NZWRpYUJveCBbMCAwIDU3NiA3MzNdCj4+CmVuZG9iago3IDAgb2JqCjw8 - IC9Qcm9jU2V0IFsgL1BERiAvVGV4dCBdIC9Db2xvclNwYWNlIDw8IC9DczIgOSAwIFIg - L0NzMSA4IDAgUiA+PiAvRm9udCA8PAovRjEuMCAxMCAwIFIgPj4gPj4KZW5kb2JqCjEx - IDAgb2JqCjw8IC9MZW5ndGggMTIgMCBSIC9OIDEgL0FsdGVybmF0ZSAvRGV2aWNlR3Jh - eSAvRmlsdGVyIC9GbGF0ZURlY29kZSA+PgpzdHJlYW0KeAGFUk9IFFEc/s02EoSIQYV4 - iHcKCZUprKyg2nZ1WZVtW5XSohhn37qjszPTm9k1xZMEXaI8dQ+iY3Ts0KGbl6LArEvX - IKkgCDx16PvN7OoohG95O9/7/f1+33tEbZ2m7zspQVRzQ5UrpaduTk2Lgx8pRR3UTlim - FfjpYnGMseu5kr+719Zn0tiy3se1dvv2PbWVZWAh6i22txD6IZFmAB+ZnyhlgLPAHZav - 2D4BPFgOrBrwI6IDD5q5MNPRnHSlsi2RU+aiKCqvYjtJrvv5uca+i7WJg/5cj2bWjr2z - 6qrRTNS090ShvA+uRBnPX1T2bDUUpw3jnEhDGinyrtXfK0zHEZErEEoGUjVkuZ9qTp11 - 4HUYu126k+P49hClPslgqIm16bKZHYV9AHYqy+wQ8AXo8bJiD+eBe2H/W1HDk8AnYT9k - h3nWrR/2F65T4HuEPTXgzhSuxfHaih9eLQFD91QjaIxzTcTT1zlzpIjvMdQZmPdGOaYL - MXeWqhM3gDthH1mqZgqxXfuu6iXuewJ30+M70Zs5C1ygHElysRXZFNA8CVgUfYuwSQ48 - Ps4eVeB3qJjAHLmJ3M0o9x7VERtno1KBVnqNV8ZP47nxxfhlbBjPgH6sdtd7fP/p4xV1 - 17Y+PPmNetw5rr2dG1VhVnFlC93/xzKEj9knOabB06FZWGvYduQPmsxMsAwoxH8FPpf6 - khNV3NXu7bhFEsxQPixsJbpLVG4p1Oo9g0qsHCvYAHZwksQsWhy4U2u6OXh32CJ6bflN - V7Lrhv769nr72vIebcqoKSgTzbNEZpSxW6Pk3Xjb/WaREZ84Or7nvYpayf5JRRA/hTla - KvIUVfRWUNbEb2cOfhu2flw/pef1Qf08CT2tn9Gv6KMRvgx0Sc/Cc1Efo0nwsGkh4hKg - ioMz1E5UY40D4inx8rRbZJH9D0AZ/WYKZW5kc3RyZWFtCmVuZG9iagoxMiAwIG9iago3 - MDQKZW5kb2JqCjkgMCBvYmoKWyAvSUNDQmFzZWQgMTEgMCBSIF0KZW5kb2JqCjEzIDAg - b2JqCjw8IC9MZW5ndGggMTQgMCBSIC9OIDMgL0FsdGVybmF0ZSAvRGV2aWNlUkdCIC9G - aWx0ZXIgL0ZsYXRlRGVjb2RlID4+CnN0cmVhbQp4AYVUz2sTQRT+Nm6p0CIIWmsOsniQ - IklZq2hF1Db9EWJrDNsftkWQZDNJ1m426+4mtaWI5OLRKt5F7aEH/4AeevBkL0qFWkUo - 3qsoYqEXLfHNbky2perAzn7z3jfvfW923wANctI09YAE5A3HUqIRaWx8Qmr8iACOoglB - NCVV2+xOJAZBg3P5e+fYeg+BW1bDe/t3snetmtK2mgeE/UDgR5rZKrDvF3EKWRICiDzf - oSnHdAjf49jy7I85Tnl4wbUPKz3EWSJ8QDUtzn9NuFPNJdNAg0g4lPVxUj6c14uU1x0H - aW5mxsgQvU+QprvM7qtioZxO9g6QvZ30fk6z3j7CIcILGa0/RriNnvWM1T/iYeGk5sSG - PRwYNfT4YBW3Gqn4NcIUXxBNJ6JUcdkuDfGYrv1W8kqCcJA4ymRhgHNaSE/XTG74uocF - fSbXE6/id1ZR4XmPE2fe1N3vRdoCrzAOHQwaDJoNSFAQRQRhmLBQQIY8GjE0snI/I6sG - G5N7MnUkart0YkSxQXs23D23UaTdPP4oInGUQ7UIkvxB/iqvyU/lefnLXLDYVveUrZua - uvLgO8XlmbkaHtfTyONzTV58ldR2k1dHlqx5erya7Bo/7FeXMeaCNY/Ec7D78S1flcyX - KYwUxeNV8+pLhHVaMTffn2x/Oz3iLs8utdZzrYmLN1abl2f9akj77qq8k+ZV+U9e9fH8 - Z83EY+IpMSZ2iuchiZfFLvGS2EurC+JgbccInZWGKdJtkfok1WBgmrz1L10/W3i9Rn8M - 9VGUGczSVIn3f8IqZDSduQ5v+o/bx/wX5PeK558oAi9s4MiZum1Tce8QoWWlbnOuAhe/ - 0X3wtm5ro344/ARYPKsWrVI1nyC8ARx2h3oe6CmY05aWzTlShyyfk7rpymJSzFDbQ1JS - 1yXXZUsWs5lVYul22JnTHW4coTlC98SnSmWT+q/xEbD9sFL5+axS2X5OGtaBl/pvwLz9 - RQplbmRzdHJlYW0KZW5kb2JqCjE0IDAgb2JqCjczNwplbmRvYmoKOCAwIG9iagpbIC9J - Q0NCYXNlZCAxMyAwIFIgXQplbmRvYmoKNCAwIG9iago8PCAvVHlwZSAvUGFnZXMgL01l - ZGlhQm94IFswIDAgNjEyIDc5Ml0gL0NvdW50IDEgL0tpZHMgWyAzIDAgUiBdID4+CmVu - ZG9iagoxNSAwIG9iago8PCAvVHlwZSAvQ2F0YWxvZyAvT3V0bGluZXMgMiAwIFIgL1Bh - Z2VzIDQgMCBSID4+CmVuZG9iagoyIDAgb2JqCjw8IC9MYXN0IDE2IDAgUiAvRmlyc3Qg - MTcgMCBSID4+CmVuZG9iagoxNyAwIG9iago8PCAvUGFyZW50IDE4IDAgUiAvQ291bnQg - MCAvRGVzdCBbIDMgMCBSIC9YWVogMCA3MzMgMCBdIC9UaXRsZSAoQ2FudmFzIDEpCj4+ - CmVuZG9iagoxOCAwIG9iago8PCA+PgplbmRvYmoKMTYgMCBvYmoKPDwgL1BhcmVudCAx - OCAwIFIgL0NvdW50IDAgL0Rlc3QgWyAzIDAgUiAvWFlaIDAgNzMzIDAgXSAvVGl0bGUg - KENhbnZhcyAxKQo+PgplbmRvYmoKMTkgMCBvYmoKPDwgL0xlbmd0aCAyMCAwIFIgL0xl - bmd0aDEgODUwNCAvRmlsdGVyIC9GbGF0ZURlY29kZSA+PgpzdHJlYW0KeAHdWnt4VNW1 - X/s85px5ZDIzmfcjMycnM5PJ+0FChkQyhJkQXjEkCBkkmgQCCUKNEFKhlUaFViKiiASE - flarBYQqQ0hhAsVL+VDovbZSq/iofVjR2n7Nh7dXW1tI5q5zJomEr/Xyh1//uGd/e++1 - 9tqPtX977bXn7DPda9e3Qwr0Ag31S1q7VoD8eAoBCL9sTWtXkjd8jHzZsp5uT5JnswDo - 1Su6Vq5J8vwTACrXytUbxtobKwHUT3S0ty5PyuEa5mUdWJDkyRTMMzvWdN+b5A2DmE9Z - ffeyMbnRg7xzTeu9Y+PDe8h7vta6ph1zidRgktl197pumQX3Rcwru9a2j9UnTajfa0Cw - NAXuBiXcBRxQoMPQDMB9rHIBg1JJjs/yXPXOO1MrPwM9L/N3zn9Uzl8Rfnzp8/ZrfvUO - /u9YoByvL+WKwGgAQENQPqzeMSGR22GSEofGnDjMxliFsRRjTs4MK/SS/fAYxqcx0tBJ - HoYNGLdifBIjM0E9j9wQeXiA4UMnyQawkzkhNeNeaLS5rSq1+/U4UQw+5X7H+sEpYsMZ - vk9sAymgnKEiT5PvwXJwkx+Al2yEWsgie48FVrtbUPQ8dGHsxUjLKSHPD6QXu18iueBl - CLbxQTpDjrv/UJTn/rAoTpEB91l/nMHsJ+nIhVLdZ1xPuf/DtdL9EsbDSdGhANY47n7e - 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 - Tam0m6boa2abzX5NWDl2+o40B8/Jh0PSyRSgl0HvN6wbuSx7GvQzepzIxO8NX6leLC05 - ePzwYZ+pKCXd6J7p37Rkxw52yeibO0ci5WlqQm1X8vevpF7eiT6Jlt4T6HvZ1/GLgQO/ - bLSGyhwf2oBzKVQumqQagy5zisKtVwmopSM9YHVrU/QBi4EzpGrdWkp7zWjzCK8LK5Ne - ef6EqpfwMBvziZVVlZK+VcNvoCGQokKD5J4n7F/SHkNpSam3tMTEoeP8kVg1qM+0OG3q - Bs/A4MCuXVTaID5s9ZSlFPUcRW57cfu15fR3tx90v/rq+auXZL+KCX6VasdvJ//sScHC - EghDDX6Dkb6yLJC/syyCxXjXL51IBozSo8Bv5bAgUt20cEZObfvqnvbuzmWtcg1ZjEkl - xlqMTRg7MN6L8SGMuFHxaxfgNy2ACxjfxvgxxs8TYw/SMEETfA+bzEujXC9fdgMvz+u6 - 9h03yDtv4L92A3/3DfzaG/h1N/Dyfwy+GO+qjM//AsN/drYKZW5kc3RyZWFtCmVuZG9i - agoyMCAwIG9iago1MjQ2CmVuZG9iagoyMSAwIG9iago8PCAvVHlwZSAvRm9udERlc2Ny - aXB0b3IgL0FzY2VudCA3NzAgL0NhcEhlaWdodCA3MTcgL0Rlc2NlbnQgLTIzMCAvRmxh - Z3MgMzIKL0ZvbnRCQm94IFstOTUxIC00ODEgMTQ0NSAxMTIyXSAvRm9udE5hbWUgL1FF - QlhUQStIZWx2ZXRpY2EgL0l0YWxpY0FuZ2xlIDAKL1N0ZW1WIDAgL01heFdpZHRoIDE1 - MDAgL1hIZWlnaHQgNjM3IC9Gb250RmlsZTIgMTkgMCBSID4+CmVuZG9iagoyMiAwIG9i - agpbIDY2NyAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDU1NiAwIDUwMCAw - IDU1NiAwIDAgNTU2IDIyMiAwIDAgMCAwCjU1NiA1NTYgMCAwIDMzMyA1MDAgMjc4IDAg - MCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAKMCAw - IDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAg - MCAwIDAgMCAwIDAgMCAwIDAgMAowIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAw - IDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwCjAgMCAwIDAg - MCAwIDUwMCBdCmVuZG9iagoxMCAwIG9iago8PCAvVHlwZSAvRm9udCAvU3VidHlwZSAv - VHJ1ZVR5cGUgL0Jhc2VGb250IC9RRUJYVEErSGVsdmV0aWNhIC9Gb250RGVzY3JpcHRv - cgoyMSAwIFIgL1dpZHRocyAyMiAwIFIgL0ZpcnN0Q2hhciA4MCAvTGFzdENoYXIgMjIy - IC9FbmNvZGluZyAvTWFjUm9tYW5FbmNvZGluZwo+PgplbmRvYmoKMjMgMCBvYmoKKE1h - YyBPUyBYIDEwLjYuOCBRdWFydHogUERGQ29udGV4dCkKZW5kb2JqCjI0IDAgb2JqCihE - OjIwMTIwNTI4MjMzNTUzWjAwJzAwJykKZW5kb2JqCjEgMCBvYmoKPDwgL1Byb2R1Y2Vy - IDIzIDAgUiAvQ3JlYXRpb25EYXRlIDI0IDAgUiAvTW9kRGF0ZSAyNCAwIFIgPj4KZW5k - b2JqCnhyZWYKMCAyNQowMDAwMDAwMDAwIDY1NTM1IGYgCjAwMDAwMDkwNTggMDAwMDAg - biAKMDAwMDAwMjYyMSAwMDAwMCBuIAowMDAwMDAwNDk4IDAwMDAwIG4gCjAwMDAwMDI0 - NzIgMDAwMDAgbiAKMDAwMDAwMDAyMiAwMDAwMCBuIAowMDAwMDAwNDc5IDAwMDAwIG4g - CjAwMDAwMDA2MDIgMDAwMDAgbiAKMDAwMDAwMjQzNiAwMDAwMCBuIAowMDAwMDAxNTQw - IDAwMDAwIG4gCjAwMDAwMDg3ODkgMDAwMDAgbiAKMDAwMDAwMDcxMiAwMDAwMCBuIAow - MDAwMDAxNTIwIDAwMDAwIG4gCjAwMDAwMDE1NzYgMDAwMDAgbiAKMDAwMDAwMjQxNiAw - MDAwMCBuIAowMDAwMDAyNTU1IDAwMDAwIG4gCjAwMDAwMDI3ODQgMDAwMDAgbiAKMDAw - MDAwMjY2OSAwMDAwMCBuIAowMDAwMDAyNzYyIDAwMDAwIG4gCjAwMDAwMDI4NzcgMDAw - MDAgbiAKMDAwMDAwODIxMyAwMDAwMCBuIAowMDAwMDA4MjM0IDAwMDAwIG4gCjAwMDAw - MDg0NTkgMDAwMDAgbiAKMDAwMDAwODk2NCAwMDAwMCBuIAowMDAwMDA5MDE2IDAwMDAw - IG4gCnRyYWlsZXIKPDwgL1NpemUgMjUgL1Jvb3QgMTUgMCBSIC9JbmZvIDEgMCBSIC9J - RCBbIDw0ZGUwM2RhNTBjOGJiODUxYWYwOTc2NWI2MWY1YTk2Yz4KPDRkZTAzZGE1MGM4 - YmI4NTFhZjA5NzY1YjYxZjVhOTZjPiBdID4+CnN0YXJ0eHJlZgo5MTMzCiUlRU9GCjEg - MCBvYmoKPDwvQXV0aG9yIChKb25hdGhhbiBCYWNocmFjaCkvQ3JlYXRpb25EYXRlIChE - OjIwMTIwNTI4MjMyOTAwWikvQ3JlYXRvciAoT21uaUdyYWZmbGUgUHJvZmVzc2lvbmFs - IDUuMy42KS9Nb2REYXRlIChEOjIwMTIwNTI4MjMzNTAwWikvUHJvZHVjZXIgMjMgMCBS - ID4+CmVuZG9iagp4cmVmCjEgMQowMDAwMDA5NzkwIDAwMDAwIG4gCnRyYWlsZXIKPDwv - SUQgWzw0ZGUwM2RhNTBjOGJiODUxYWYwOTc2NWI2MWY1YTk2Yz4gPDRkZTAzZGE1MGM4 - YmI4NTFhZjA5NzY1YjYxZjVhOTZjPl0gL0luZm8gMSAwIFIgL1ByZXYgOTEzMyAvUm9v - dCAxNSAwIFIgL1NpemUgMjU+PgpzdGFydHhyZWYKOTk1NgolJUVPRgo= - - QuickLookThumbnail - - TU0AKgAAAfiAP+BP8AQWDQeEQmFQuGQZkQ8APWJQ2KRWFg+MAAaRuLR2PQaBwSPyOOqe - TAAhymSSuBgBfS8AFmZSuaQmQzWcQhVTsAFafTmOv6hABWUWez+gTSb0mcTtVUcrUyKU - J/USjT6o1KR0utSSnVCuwuqVZWWCwx2uWeO1+sWqEWOi2W226KM67P9s3mEDC+AATX8A - O7BAAHYUAAXEAB04sABjHABS5EABXKAAQZcANDNWBdZ0AC7QAAL6MAS2WgHUQjUAGES1 - Pa8AAzZaLSC3bAB7bkABveRGJgfgAB38PG49eccAXlsgAT83Sy2KLbpAB5dUAAnsABxd - sABrvAAp+EAOfyABa+fJ5V8+uwJz3ACMA/0hUANz7AAU/kALn+AAav+AB7wEAAOQKAAc - QQsizIMZUGsUxhqQiAASQoADVgAbEMgAPkOIQN0PgAA0ROegSKnHE7ruydkVsOxIIReA - AJRlCzUoWtifnjHIAAFHgAH5H4AHpIUSSDIYGyOACxgXJcYxmuMFoLIR6AAfcqgA9Z8x - o1kBHuADgAOAAMzEiy0rohsbqzMy4KupEzIXMs3IVNE4zWuU2zi1roTxGyeLnNShyfP0 - 9pBPVBp1Ps7rdOsoUNOFDAATtIsszFBnJSwAC/TNH0JEtN09T6PUdUFR1IgIAA4BAAAD - AAAAAQAmAAABAQADAAAAAQAQAAABAgADAAAABAAAAqYBAwADAAAAAQAFAAABBgADAAAA - AQACAAABEQAEAAAAAQAAAAgBEgADAAAAAQABAAABFQADAAAAAQAEAAABFgADAAAAAQAQ - AAABFwAEAAAAAQAAAfABHAADAAAAAQABAAABPQADAAAAAQACAAABUgADAAAAAQABAAAB - UwADAAAABAAAAq4AAAAAAAgACAAIAAgAAQABAAEAAQ== - - ReadOnly - NO - RowAlign - 1 - RowSpacing - 36 - SheetTitle - Canvas 1 - SmartAlignmentGuidesActive - YES - SmartDistanceGuidesActive - YES - UniqueID - 1 - UseEntirePage - - VPages - 1 - WindowInfo - - CurrentSheet - 0 - ExpandedCanvases - - - name - Canvas 1 - - - Frame - {{365, 4}, {710, 874}} - ListView - - OutlineWidth - 142 - RightSidebar - - ShowRuler - - Sidebar - - SidebarWidth - 120 - VisibleRegion - {{0, 0}, {561, 705}} - Zoom - 1 - ZoomValues - - - Canvas 1 - 1 - 1 - - - - saveQuickLookFiles - YES - - diff --git a/doc/cs250/figs/process.pdf b/doc/cs250/figs/process.pdf deleted file mode 100644 index 2a1cdbed..00000000 Binary files a/doc/cs250/figs/process.pdf and /dev/null differ diff --git a/doc/cs250/figs/rd.pdf b/doc/cs250/figs/rd.pdf deleted file mode 100644 index 70788541..00000000 Binary files a/doc/cs250/figs/rd.pdf and /dev/null differ diff --git a/doc/cs250/figs/reg-in.graffle b/doc/cs250/figs/reg-in.graffle deleted file mode 100644 index 6687aac4..00000000 Binary files a/doc/cs250/figs/reg-in.graffle and /dev/null differ diff --git a/doc/cs250/figs/reg-in.pdf b/doc/cs250/figs/reg-in.pdf deleted file mode 100644 index 97662909..00000000 Binary files a/doc/cs250/figs/reg-in.pdf and /dev/null differ diff --git a/doc/cs250/figs/rising-edge.graffle b/doc/cs250/figs/rising-edge.graffle deleted file mode 100644 index 83fc445e..00000000 Binary files a/doc/cs250/figs/rising-edge.graffle and /dev/null differ diff --git a/doc/cs250/figs/rising-edge.pdf b/doc/cs250/figs/rising-edge.pdf deleted file mode 100644 index ba6a64c6..00000000 Binary files a/doc/cs250/figs/rising-edge.pdf and /dev/null differ diff --git a/doc/cs250/figs/rocket-coprocessor.graffle b/doc/cs250/figs/rocket-coprocessor.graffle deleted file mode 100644 index 69a1c046..00000000 Binary files a/doc/cs250/figs/rocket-coprocessor.graffle and /dev/null differ diff --git a/doc/cs250/figs/rocket-coprocessor.pdf b/doc/cs250/figs/rocket-coprocessor.pdf deleted file mode 100644 index ecd330b8..00000000 Binary files a/doc/cs250/figs/rocket-coprocessor.pdf and /dev/null differ diff --git a/doc/cs250/figs/rom.graffle b/doc/cs250/figs/rom.graffle deleted file mode 100644 index 90d45dff..00000000 Binary files a/doc/cs250/figs/rom.graffle and /dev/null differ diff --git a/doc/cs250/figs/rom.pdf b/doc/cs250/figs/rom.pdf deleted file mode 100644 index 0a7acbfb..00000000 Binary files a/doc/cs250/figs/rom.pdf and /dev/null differ diff --git a/doc/cs250/figs/router.graffle b/doc/cs250/figs/router.graffle deleted file mode 100644 index 4734cc7c..00000000 --- a/doc/cs250/figs/router.graffle +++ /dev/null @@ -1,1888 +0,0 @@ - - - - - ActiveLayerIndex - 0 - ApplicationVersion - - com.omnigroup.OmniGrafflePro - 138.33.0.157554 - - AutoAdjust - - BackgroundGraphic - - Bounds - {{0, 0}, {576, 733}} - Class - SolidGraphic - ID - 2 - Style - - shadow - - Draws - NO - - stroke - - Draws - NO - - - - CanvasOrigin - {0, 0} - ColumnAlign - 1 - ColumnSpacing - 36 - CreationDate - 2012-05-29 16:31:24 -0700 - Creator - Jonathan Bachrach - DisplayScale - 1 0/72 in = 1.0000 in - GraphDocumentVersion - 8 - GraphicsList - - - Class - Group - Graphics - - - Class - LineGraphic - FontInfo - - Font - Helvetica - Size - 27 - - ID - 50 - Points - - {72, 225} - {108, 225} - - Style - - stroke - - HeadArrow - 0 - TailArrow - 0 - Width - 3 - - - - - Class - LineGraphic - FontInfo - - Font - Helvetica - Size - 27 - - ID - 51 - Points - - {72, 207} - {108, 207} - - Style - - stroke - - HeadArrow - 0 - TailArrow - 0 - Width - 3 - - - - - Class - LineGraphic - FontInfo - - Font - Helvetica - Size - 27 - - ID - 52 - Points - - {99, 207} - {99, 225} - - Style - - stroke - - HeadArrow - 0 - TailArrow - 0 - Width - 3 - - - - - Class - LineGraphic - FontInfo - - Font - Helvetica - Size - 27 - - ID - 53 - Points - - {90, 207} - {90, 225} - - Style - - stroke - - HeadArrow - 0 - TailArrow - 0 - Width - 3 - - - - - Class - LineGraphic - FontInfo - - Font - Helvetica - Size - 27 - - ID - 54 - Points - - {81, 207} - {81, 225} - - Style - - stroke - - HeadArrow - 0 - TailArrow - 0 - Width - 3 - - - - - ID - 49 - - - Class - Group - Graphics - - - Class - LineGraphic - FontInfo - - Font - Helvetica - Size - 27 - - ID - 44 - Points - - {486, 281} - {522, 281} - - Style - - stroke - - HeadArrow - 0 - TailArrow - 0 - Width - 3 - - - - - Class - LineGraphic - FontInfo - - Font - Helvetica - Size - 27 - - ID - 45 - Points - - {486, 263} - {522, 263} - - Style - - stroke - - HeadArrow - 0 - TailArrow - 0 - Width - 3 - - - - - Class - LineGraphic - FontInfo - - Font - Helvetica - Size - 27 - - ID - 46 - Points - - {513, 263} - {513, 281} - - Style - - stroke - - HeadArrow - 0 - TailArrow - 0 - Width - 3 - - - - - Class - LineGraphic - FontInfo - - Font - Helvetica - Size - 27 - - ID - 47 - Points - - {504, 263} - {504, 281} - - Style - - stroke - - HeadArrow - 0 - TailArrow - 0 - Width - 3 - - - - - Class - LineGraphic - FontInfo - - Font - Helvetica - Size - 27 - - ID - 48 - Points - - {495, 263} - {495, 281} - - Style - - stroke - - HeadArrow - 0 - TailArrow - 0 - Width - 3 - - - - - ID - 43 - - - Class - Group - Graphics - - - Class - LineGraphic - FontInfo - - Font - Helvetica - Size - 27 - - ID - 38 - Points - - {486, 244} - {522, 244} - - Style - - stroke - - HeadArrow - 0 - TailArrow - 0 - Width - 3 - - - - - Class - LineGraphic - FontInfo - - Font - Helvetica - Size - 27 - - ID - 39 - Points - - {486, 226} - {522, 226} - - Style - - stroke - - HeadArrow - 0 - TailArrow - 0 - Width - 3 - - - - - Class - LineGraphic - FontInfo - - Font - Helvetica - Size - 27 - - ID - 40 - Points - - {513, 226} - {513, 244} - - Style - - stroke - - HeadArrow - 0 - TailArrow - 0 - Width - 3 - - - - - Class - LineGraphic - FontInfo - - Font - Helvetica - Size - 27 - - ID - 41 - Points - - {504, 226} - {504, 244} - - Style - - stroke - - HeadArrow - 0 - TailArrow - 0 - Width - 3 - - - - - Class - LineGraphic - FontInfo - - Font - Helvetica - Size - 27 - - ID - 42 - Points - - {495, 226} - {495, 244} - - Style - - stroke - - HeadArrow - 0 - TailArrow - 0 - Width - 3 - - - - - ID - 37 - - - Class - Group - Graphics - - - Class - LineGraphic - FontInfo - - Font - Helvetica - Size - 27 - - ID - 32 - Points - - {486, 207} - {522, 207} - - Style - - stroke - - HeadArrow - 0 - TailArrow - 0 - Width - 3 - - - - - Class - LineGraphic - FontInfo - - Font - Helvetica - Size - 27 - - ID - 33 - Points - - {486, 189} - {522, 189} - - Style - - stroke - - HeadArrow - 0 - TailArrow - 0 - Width - 3 - - - - - Class - LineGraphic - FontInfo - - Font - Helvetica - Size - 27 - - ID - 34 - Points - - {513, 189} - {513, 207} - - Style - - stroke - - HeadArrow - 0 - TailArrow - 0 - Width - 3 - - - - - Class - LineGraphic - FontInfo - - Font - Helvetica - Size - 27 - - ID - 35 - Points - - {504, 189} - {504, 207} - - Style - - stroke - - HeadArrow - 0 - TailArrow - 0 - Width - 3 - - - - - Class - LineGraphic - FontInfo - - Font - Helvetica - Size - 27 - - ID - 36 - Points - - {495, 189} - {495, 207} - - Style - - stroke - - HeadArrow - 0 - TailArrow - 0 - Width - 3 - - - - - ID - 31 - - - Class - Group - Graphics - - - Class - LineGraphic - FontInfo - - Font - Helvetica - Size - 27 - - ID - 26 - Points - - {486, 170} - {522, 170} - - Style - - stroke - - HeadArrow - 0 - TailArrow - 0 - Width - 3 - - - - - Class - LineGraphic - FontInfo - - Font - Helvetica - Size - 27 - - ID - 27 - Points - - {486, 152} - {522, 152} - - Style - - stroke - - HeadArrow - 0 - TailArrow - 0 - Width - 3 - - - - - Class - LineGraphic - FontInfo - - Font - Helvetica - Size - 27 - - ID - 28 - Points - - {513, 152} - {513, 170} - - Style - - stroke - - HeadArrow - 0 - TailArrow - 0 - Width - 3 - - - - - Class - LineGraphic - FontInfo - - Font - Helvetica - Size - 27 - - ID - 29 - Points - - {504, 152} - {504, 170} - - Style - - stroke - - HeadArrow - 0 - TailArrow - 0 - Width - 3 - - - - - Class - LineGraphic - FontInfo - - Font - Helvetica - Size - 27 - - ID - 30 - Points - - {495, 152} - {495, 170} - - Style - - stroke - - HeadArrow - 0 - TailArrow - 0 - Width - 3 - - - - - ID - 25 - - - Bounds - {{395.5, 254}, {67, 32}} - Class - ShapedGraphic - FitText - YES - Flow - Resize - FontInfo - - Color - - w - 0 - - Font - Helvetica - Size - 18 - - ID - 14 - Line - - ID - 13 - Position - 0.47222220897674561 - RotationType - 0 - - Shape - Rectangle - Style - - shadow - - Draws - NO - - stroke - - Draws - NO - Width - 3 - - - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1038\cocoasubrtf360 -{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural - -\f0\fs36 \cf0 outs(3)} - - Wrap - NO - - - Class - LineGraphic - FontInfo - - Font - Helvetica - Size - 17 - - ID - 13 - Points - - {378, 270} - {486, 270} - - Style - - stroke - - HeadArrow - StickArrow - TailArrow - 0 - Width - 3 - - - - - Bounds - {{395.5, 218}, {67, 32}} - Class - ShapedGraphic - FitText - YES - Flow - Resize - FontInfo - - Color - - w - 0 - - Font - Helvetica - Size - 18 - - ID - 12 - Line - - ID - 11 - Position - 0.47222220897674561 - RotationType - 0 - - Shape - Rectangle - Style - - shadow - - Draws - NO - - stroke - - Draws - NO - Width - 3 - - - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1038\cocoasubrtf360 -{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural - -\f0\fs36 \cf0 outs(2)} - - Wrap - NO - - - Class - LineGraphic - FontInfo - - Font - Helvetica - Size - 17 - - ID - 11 - Points - - {378, 234} - {486, 234} - - Style - - stroke - - HeadArrow - StickArrow - TailArrow - 0 - Width - 3 - - - - - Bounds - {{395.5, 182}, {67, 32}} - Class - ShapedGraphic - FitText - YES - Flow - Resize - FontInfo - - Color - - w - 0 - - Font - Helvetica - Size - 18 - - ID - 10 - Line - - ID - 9 - Position - 0.47222220897674561 - RotationType - 0 - - Shape - Rectangle - Style - - shadow - - Draws - NO - - stroke - - Draws - NO - Width - 3 - - - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1038\cocoasubrtf360 -{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural - -\f0\fs36 \cf0 outs(1)} - - Wrap - NO - - - Class - LineGraphic - FontInfo - - Font - Helvetica - Size - 17 - - ID - 9 - Points - - {378, 198} - {486, 198} - - Style - - stroke - - HeadArrow - StickArrow - TailArrow - 0 - Width - 3 - - - - - Bounds - {{395.5, 146}, {67, 32}} - Class - ShapedGraphic - FitText - YES - Flow - Resize - FontInfo - - Color - - w - 0 - - Font - Helvetica - Size - 18 - - ID - 8 - Line - - ID - 7 - Position - 0.47222220897674561 - RotationType - 0 - - Shape - Rectangle - Style - - shadow - - Draws - NO - - stroke - - Draws - NO - Width - 3 - - - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1038\cocoasubrtf360 -{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural - -\f0\fs36 \cf0 outs(0)} - - Wrap - NO - - - Class - LineGraphic - FontInfo - - Font - Helvetica - Size - 17 - - ID - 7 - Points - - {378, 162} - {486, 162} - - Style - - stroke - - HeadArrow - StickArrow - TailArrow - 0 - Width - 3 - - - - - Bounds - {{146, 199}, {26, 34}} - Class - ShapedGraphic - FitText - YES - Flow - Resize - FontInfo - - Color - - w - 0 - - Font - Helvetica - Size - 20 - - ID - 6 - Line - - ID - 5 - Position - 0.47222220897674561 - RotationType - 0 - - Shape - Rectangle - Style - - shadow - - Draws - NO - - stroke - - Draws - NO - Width - 3 - - - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1038\cocoasubrtf360 -{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural - -\f0\fs40 \cf0 in} - - Wrap - NO - - - Class - LineGraphic - FontInfo - - Font - Helvetica - Size - 19 - - ID - 5 - Points - - {108, 216} - {216, 216} - - Style - - stroke - - HeadArrow - StickArrow - TailArrow - 0 - Width - 3 - - - - - Bounds - {{216, 135}, {162, 162}} - Class - ShapedGraphic - FontInfo - - Font - Helvetica - Size - 19 - - ID - 3 - Shape - Rectangle - Style - - stroke - - Width - 2 - - - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1038\cocoasubrtf360 -{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural - -\f0\fs56 \cf0 Router} - - - - GridInfo - - ShowsGrid - YES - SnapsToGrid - YES - - GuidesLocked - NO - GuidesVisible - YES - HPages - 1 - ImageCounter - 1 - KeepToScale - - Layers - - - Lock - NO - Name - Layer 1 - Print - YES - View - YES - - - LayoutInfo - - Animate - NO - circoMinDist - 18 - circoSeparation - 0.0 - layoutEngine - dot - neatoSeparation - 0.0 - twopiSeparation - 0.0 - - LinksVisible - NO - MagnetsVisible - NO - MasterSheets - - ModificationDate - 2012-05-30 10:12:30 -0700 - Modifier - Jonathan Bachrach - NotesVisible - NO - Orientation - 2 - OriginVisible - NO - PageBreaks - YES - PrintInfo - - NSBottomMargin - - float - 41 - - NSLeftMargin - - float - 18 - - NSPaperSize - - coded - BAtzdHJlYW10eXBlZIHoA4QBQISEhAdOU1ZhbHVlAISECE5TT2JqZWN0AIWEASqEhAx7X05TU2l6ZT1mZn2WgWQCgRgDhg== - - NSRightMargin - - float - 18 - - NSTopMargin - - float - 18 - - - PrintOnePage - - QuickLookPreview - - JVBERi0xLjMKJcTl8uXrp/Og0MTGCjUgMCBvYmoKPDwgL0xlbmd0aCA2IDAgUiAvRmls - dGVyIC9GbGF0ZURlY29kZSA+PgpzdHJlYW0KeAGtlsFu2zAMhu96Ch6TQ1yKkizrumI7 - 9JbFwA7rTkELrGhatGmx1x9JybHb2E5TFIFhJv75i/wkS3mCNTwB8ifEGqJz8HwDv+AB - Li73FrZ7sPrZb2GFVQC5BsJbIFuDdzXYmuQynM0/wj/OuuLrLvtcbnQIhM0lj2b1y0pu - MuB2py7Whc5FatiYteSS1IDA4w/yKEUINkrmt5ZrQkSCdgvUZGe+rzxVSBi4fGvaHVz8 - sBXyyO0tLH4+vr7cPC+hvYPvLffvuNyB+6Eqi41WxvUhVlZicw8bzkBuDrm5sSyytnLv - 8+D+4GGrBqRjVhmhd3hCWBF/E/8j+NYHIc9lBKAanBdEtz0g8xaQDWkckEw0wor4ilVs - HKGDCMqHeSkfs/j70LPppnGsUxcbnbEd+Ch8ZA284WPGsnwjfET7Nq94hKh8etV9dje2 - rqf5uMR0gjCqIzh6R+fd8vHEdKI1efnYsmj4vqKmQovRd0xct2Z+w+JxKa8AweK1C16W - vPb4h/31ApcmP7xeLuEPtFd5ZZ2kl2QtlM45VnpmbnUVLkd5nYcb0ksNr9f8hJBO0LPp - DHoufCU9+zl6xK9BR0/ij9I7ziuMKA3osaqn55p5er5xH6fnU/pKevRJehF7ehx/mN5R - XqFXhyG9iD296E/Q8/EMerX7SnrufHqeNxsbdP+SqGMHT+b4ZAvoi1ajXjtyCgbL+6L6 - cmQGviNa3/CZm7XEJy9Heecd2XGNanXWgmhna9DemiQrg3sjjBO+MgXakWolmtbKOa29 - ZS13Oa0VX603a6VejiZ7U6248QisPeErHfHpWXrzZccYPcW1I9VqNKlVDtJR1ko0qRUO - 0lvRSr2cNd5bx0HcSm/zvtJb7breGjvjqx2pVqNJbTdv2VdmkCa1h3qzr/TG0XhvBw7s - Vnqb9eWHeYoloDDjmrAoJZhUSq0pdUoOJpVSaczLagf6d3D2hRApexXpwXX9H3XWVxQK - ZW5kc3RyZWFtCmVuZG9iago2IDAgb2JqCjczNwplbmRvYmoKMyAwIG9iago8PCAvVHlw - ZSAvUGFnZSAvUGFyZW50IDQgMCBSIC9SZXNvdXJjZXMgNyAwIFIgL0NvbnRlbnRzIDUg - MCBSIC9NZWRpYUJveCBbMCAwIDU3NiA3MzNdCj4+CmVuZG9iago3IDAgb2JqCjw8IC9Q - cm9jU2V0IFsgL1BERiAvVGV4dCBdIC9Db2xvclNwYWNlIDw8IC9DczIgOSAwIFIgL0Nz - MSA4IDAgUiA+PiAvRm9udCA8PAovRjEuMCAxMCAwIFIgL0YzLjAgMTIgMCBSIC9GMi4w - IDExIDAgUiA+PiA+PgplbmRvYmoKMTMgMCBvYmoKPDwgL0xlbmd0aCAxNCAwIFIgL04g - MSAvQWx0ZXJuYXRlIC9EZXZpY2VHcmF5IC9GaWx0ZXIgL0ZsYXRlRGVjb2RlID4+CnN0 - cmVhbQp4AYVST0gUURz+zTYShIhBhXiIdwoJlSmsrKDadnVZlW1bldKiGGffuqOzM9Ob - 2TXFkwRdojx1D6JjdOzQoZuXosCsS9cgqSAIPHXo+83s6iiEb3k73/v9/X7fe0Rtnabv - OylBVHNDlSulp25OTYuDHylFHdROWKYV+OlicYyx67mSv7vX1mfS2LLex7V2+/Y9tZVl - YCHqLba3EPohkWYAH5mfKGWAs8Adlq/YPgE8WA6sGvAjogMPmrkw09GcdKWyLZFT5qIo - Kq9iO0mu+/m5xr6LtYmD/lyPZtaOvbPqqtFM1LT3RKG8D65EGc9fVPZsNRSnDeOcSEMa - KfKu1d8rTMcRkSsQSgZSNWS5n2pOnXXgdRi7XbqT4/j2EKU+yWCoibXpspkdhX0AdirL - 7BDwBejxsmIP54F7Yf9bUcOTwCdhP2SHedatH/YXrlPge4Q9NeDOFK7F8dqKH14tAUP3 - VCNojHNNxNPXOXOkiO8x1BmY90Y5pgsxd5aqEzeAO2EfWapmCrFd+67qJe57AnfT4zvR - mzkLXKAcSXKxFdkU0DwJWBR9i7BJDjw+zh5V4HeomMAcuYnczSj3HtURG2ejUoFWeo1X - xk/jufHF+GVsGM+Afqx213t8/+njFXXXtj48+Y163DmuvZ0bVWFWcWUL3f/HMoSP2Sc5 - psHToVlYa9h25A+azEywDCjEfwU+l/qSE1Xc1e7tuEUSzFA+LGwluktUbinU6j2DSqwc - K9gAdnCSxCxaHLhTa7o5eHfYInpt+U1XsuuG/vr2evva8h5tyqgpKBPNs0RmlLFbo+Td - eNv9ZpERnzg6vue9ilrJ/klFED+FOVoq8hRV9FZQ1sRvZw5+G7Z+XD+l5/VB/TwJPa2f - 0a/ooxG+DHRJz8JzUR+jSfCwaSHiEqCKgzPUTlRjjQPiKfHytFtkkf0PQBn9ZgplbmRz - dHJlYW0KZW5kb2JqCjE0IDAgb2JqCjcwNAplbmRvYmoKOSAwIG9iagpbIC9JQ0NCYXNl - ZCAxMyAwIFIgXQplbmRvYmoKMTUgMCBvYmoKPDwgL0xlbmd0aCAxNiAwIFIgL04gMyAv - QWx0ZXJuYXRlIC9EZXZpY2VSR0IgL0ZpbHRlciAvRmxhdGVEZWNvZGUgPj4Kc3RyZWFt - CngBhVTPaxNBFP42bqnQIghaaw6yeJAiSVmraEXUNv0RYmsM2x+2RZBkM0nWbjbr7ia1 - pYjk4tEq3kXtoQf/gB568GQvSoVaRSjeqyhioRct8c1uTLal6sDOfvPeN+99b3bfAA1y - 0jT1gATkDcdSohFpbHxCavyIAI6iCUE0JVXb7E4kBkGDc/l759h6D4FbVsN7+3eyd62a - 0raaB4T9QOBHmtkqsO8XcQpZEgKIPN+hKcd0CN/j2PLsjzlOeXjBtQ8rPcRZInxANS3O - f024U80l00CDSDiU9XFSPpzXi5TXHQdpbmbGyBC9T5Cmu8zuq2KhnE72DpC9nfR+TrPe - PsIhwgsZrT9GuI2e9YzVP+Jh4aTmxIY9HBg19PhgFbcaqfg1whRfEE0nolRx2S4N8Ziu - /VbySoJwkDjKZGGAc1pIT9dMbvi6hwV9JtcTr+J3VlHheY8TZ97U3e9F2gKvMA4dDBoM - mg1IUBBFBGGYsFBAhjwaMTSycj8jqwYbk3sydSRqu3RiRLFBezbcPbdRpN08/igicZRD - tQiS/EH+Kq/JT+V5+ctcsNhW95Stm5q68uA7xeWZuRoe19PI43NNXnyV1HaTV0eWrHl6 - vJrsGj/sV5cx5oI1j8RzsPvxLV+VzJcpjBTF41Xz6kuEdVoxN9+fbH87PeIuzy611nOt - iYs3VpuXZ/1qSPvuqryT5lX5T1718fxnzcRj4ikxJnaK5yGJl8Uu8ZLYS6sL4mBtxwid - lYYp0m2R+iTVYGCavPUvXT9beL1Gfwz1UZQZzNJUifd/wipkNJ25Dm/6j9vH/Bfk94rn - nygCL2zgyJm6bVNx7xChZaVuc64CF7/RffC2bmujfjj8BFg8qxatUjWfILwBHHaHeh7o - KZjTlpbNOVKHLJ+TuunKYlLMUNtDUlLXJddlSxazmVVi6XbYmdMdbhyhOUL3xKdKZZP6 - r/ERsP2wUvn5rFLZfk4a1oGX+m/AvP1FCmVuZHN0cmVhbQplbmRvYmoKMTYgMCBvYmoK - NzM3CmVuZG9iago4IDAgb2JqClsgL0lDQ0Jhc2VkIDE1IDAgUiBdCmVuZG9iago0IDAg - b2JqCjw8IC9UeXBlIC9QYWdlcyAvTWVkaWFCb3ggWzAgMCA2MTIgNzkyXSAvQ291bnQg - MSAvS2lkcyBbIDMgMCBSIF0gPj4KZW5kb2JqCjE3IDAgb2JqCjw8IC9UeXBlIC9DYXRh - bG9nIC9PdXRsaW5lcyAyIDAgUiAvUGFnZXMgNCAwIFIgPj4KZW5kb2JqCjIgMCBvYmoK - PDwgL0xhc3QgMTggMCBSIC9GaXJzdCAxOSAwIFIgPj4KZW5kb2JqCjE5IDAgb2JqCjw8 - IC9QYXJlbnQgMjAgMCBSIC9Db3VudCAwIC9EZXN0IFsgMyAwIFIgL1hZWiAwIDczMyAw - IF0gL1RpdGxlIChDYW52YXMgMSkKPj4KZW5kb2JqCjIwIDAgb2JqCjw8ID4+CmVuZG9i - agoxOCAwIG9iago8PCAvUGFyZW50IDIwIDAgUiAvQ291bnQgMCAvRGVzdCBbIDMgMCBS - IC9YWVogMCA3MzMgMCBdIC9UaXRsZSAoQ2FudmFzIDEpCj4+CmVuZG9iagoyMSAwIG9i - ago8PCAvTGVuZ3RoIDIyIDAgUiAvTGVuZ3RoMSA2NjYwIC9GaWx0ZXIgL0ZsYXRlRGVj - b2RlID4+CnN0cmVhbQp4Ab1Ze3QT15n/7jw0I8sPSZZsSbYsibEkP/ELjI2deDCSMW9j - A5EIJpKxjU1wcRzjAl1YJ4VuMISFEJwAbVqahgBewmB7qQwN6+RAIWe3DUkT8tjsNmkg - yfbEh+4udNOCpf1mZLuYk+TwBydz/c39Xvfe7/7uN3c0150dG5ogDrqBhpoVwfZmUC5z - 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 - WbUp2qeeGWTyhooPUfQ5mjrZMfq8vPMlR65TanYFIl/7z3FTY4bjSYhUiE4mqTSZVsXH - 6CzJyRY8+cgEY7wxgbbRFH07yWy23Has2TKWwfWl5+UHXLvI2+T5DPIqKuRNYEQ7erUg - P7FIV2QUdIbkpKLC4hnGeIzJNV0nTC86erqvz2UsiEsz2Ga7t67Yu5ddEX5336i3JFFD - qN1q/ok11IV9yh7WHfmU/k98XpMxwlXizJDhkoFSJ/IGc6LZkKH6Pv0ex/HAxseAKi6G - xbwwcSaTJglnkhmrsVhIphzs246GymiwcmJgeFcRrmhuVODGFIUOd6NooDOKp+uKdMIM - JffdGK+TlFjyf/grj3PwOCVMW7PvWl0uOcnkjZbWTgscXfETKv7WWy88kLX0QO0O6n2L - vO8qV6QJz6K+7pJ38Ol4niWfVj0EPpQInq5F3zcq/H8D1C14qG6pP7u6aV1XU2fr6qDi - Md5TOjL5SCJSDVIAqR2pOzJ2IQ8TPFHeZ3fKSkx32Nff5d9xl6z8v+QO/w2y/f8Bhv3i - DAplbmRzdHJlYW0KZW5kb2JqCjIyIDAgb2JqCjQwMTYKZW5kb2JqCjIzIDAgb2JqCjw8 - IC9UeXBlIC9Gb250RGVzY3JpcHRvciAvQXNjZW50IDc3MCAvQ2FwSGVpZ2h0IDcxNyAv - RGVzY2VudCAtMjMwIC9GbGFncyAzMgovRm9udEJCb3ggWy05NTEgLTQ4MSAxNDQ1IDEx - MjJdIC9Gb250TmFtZSAvU0xXU1RZK0hlbHZldGljYSAvSXRhbGljQW5nbGUgMAovU3Rl - bVYgMCAvTWF4V2lkdGggMTUwMCAvWEhlaWdodCA2MzcgL0ZvbnRGaWxlMiAyMSAwIFIg - Pj4KZW5kb2JqCjI0IDAgb2JqClsgNzIyIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAg - MCAwIDAgMCAwIDU1NiAwIDAgMCAwIDAgMCAwIDAgMCA1NTYgMCAwIDMzMwowIDI3OCA1 - NTYgXQplbmRvYmoKMTAgMCBvYmoKPDwgL1R5cGUgL0ZvbnQgL1N1YnR5cGUgL1RydWVU - eXBlIC9CYXNlRm9udCAvU0xXU1RZK0hlbHZldGljYSAvRm9udERlc2NyaXB0b3IKMjMg - MCBSIC9XaWR0aHMgMjQgMCBSIC9GaXJzdENoYXIgODIgL0xhc3RDaGFyIDExNyAvRW5j - b2RpbmcgL01hY1JvbWFuRW5jb2RpbmcKPj4KZW5kb2JqCjI1IDAgb2JqCjw8IC9MZW5n - dGggMjYgMCBSIC9MZW5ndGgxIDc2ODAgL0ZpbHRlciAvRmxhdGVEZWNvZGUgPj4Kc3Ry - ZWFtCngBxVl5eFRFtj91l77d6Sy9b0mn+6bTSzayh4QguYTuBEiIIUFIR8F0oCFhkQgh - AiMYHBiHgBEN5gVceT55LCJNQOyAOtHBEb8ZR3TEXQcVdN585uHzAW6k+53bHSLhG/34 - w89X9Z2qc+rUcupX51bdW7d9xSo/xEEn0FDb6GtbCJFgtmJ2Zv4yX1tUVp3B/Mj8jnZr - VGZdAPTShW2LlkVl6XaAGPOipWtG2qufApAZWvy+BVE9XMa8qAULojIpwDy1ZVn76qis - OoJ55tLl80f0auwPDMt8q0fGhw9Rtt7mW+aP1k8S+0ttW76yfUQ+gXlx2wr/SH3SgPa9 - DgRL5bAcZLAEOKBAgXEuAPePGDMwqBX1GBZkyntuTZh4EZTSiHzrjPsi+Z/4597+1n/Z - Kb9f+h0WyK7UF3NJWigNIJagfkh+/6gm0g4TeRDqM4IwDakMqRApI2OyATrJbtiG9DgS - Da1kC6xB2oy0A4kZ5faiNEC29DNS4RhZAyYyXZAzllkao8UQI7e8GSSSI49a3jN8dpwY - cfU+Icb+OJBNjiGPk8dgAVjIk2Ana2EquMjOw2lLLU2o2gttSJ1IdCQlZG9/cp7lBZIJ - doZgGwckM+So5YvcLMu53CBF+i0vOYMMZi8moyQkWAbNj1r+YF5keQFpf1S1Lw1rHLXs - NS+19CQHyc5+ywPmIME290ezVWZsetSyLK3XsiA3oq/uDVL7+y0lqJ8tyC1Fxbyl0HzW - ku0MSgnKWeZqS3rua5ZUbIjVrNipXVBaksw9lgmoSjZ7nBOQjpN95CFIJw/126dbjiGL - 0z08La24N0h+c3iqK9ceJGuFoqmu3rSpTntatcWeVuF0Ij/7JLeRu5mbzOVxGZyLc3A8 - l8hppCqpQhovjZXGSKVSLkie6i+zSI6T/VCGsOw/LJVI2SB5GguZ4+RApPDAs1JGSklB - qgmGz6DzEtAEyf4jCpFD5qgkwkmC5MDhaNEBwcKIHBNRKCiRxwRToIiUgukQIPcGJbBJ - 11FmKFNNUpZUuH8qaYporqQZPx0MxBzorapvCOwzewN5IhM2e69UN1xhfjJvX4Uqf3lG - RlXdmsMdbYsXevw2T5PN40dqCmzpaDEEOput1kOL20SFNUA7mprnt4i5zx9os/ndgcU2 - t/VQR6TdNeqForrD5j4ECz2zGg4tFPzu/g6hw2Pzub2Hm8tXzB0z1ubRsVaU/4uxysXO - VohjNUfaXTPWXFHdLI41VxxrrjhWs9AcGUucvKe1vnxlO3qn1dNaZQ246gPTZjY2BKw+ - rztIdmOhexWwg6BgnwcX2wkmJhssAOH3kN4X89BN4c/ZV0ARWhb+H7oUF3VAJCpUNhEG - 4V54CA6CBPYg74J50AevksX4bN8CR+BtkgzjcO9lIAjV8BcSDr8BC+E/sH47vAQPwiGI - xTbLQIvabmIPr0VZQL4ZNob/HVKhGH4Hz0MJ9toNQ+G94cOorYObYB/sx/Z/JjbqEKMO - Px0+C1KYiX1uRM0b4erwQVBBJpRDLZZuhBeInX4/3AIGKEXrHobHYBe8CF+Su8mRcEu4 - I3wq/Am6qgGSoB7jOnKEfEIfZH4Xfjj8z3AIkXBBOo7aBD3wBPZ/EOMgbq0esoS0kx7y - ICVQd1NHmE2sPjSMOKRBJcapuCv/HhEYgBPwNXxHzlMGWkG30y+HC8P/i3t2Fc5SnIkf - OjDeg7Eb53ScSEgOmUJqyTqynTxI/kalUzdRDdQd1Grqc7qGvoVeQ/+NWcn0s1vZPok8 - dDF8PPxK+DTowQw3wwpYj7N7CU7BBfie0NhXErGTUlJO5mHsJA9RA2QXGaBqySA5Re0j - fyefkfPkB4qlYiktlUG1Uz3Ufuol6q90K/0gvYP+O32RmcRS7C72nMTOfRBqDm0O/TVc - Gv4k/C1usVLgcWXKoQZuBR/Otg0K4C6cxQGMB3HVTsDL8GokfkaSYAi+RRSAqIiJ5JEZ - GGvIjWQhaSWPkmMYX4jYconChaBklJLSU0lUPdVMLaM6qdNUJ51Ip9PT6Ub6IMaT9Nv0 - D/QPDMuoGS1TyUyDrcwyZifG3cwepp95nS1hJ7E17Gy2k93MbqXns2+wb0vWS7ol/ZLz - kq9wW6zmlnNbcXVeRZ99EX35x8CQVLQ+D26D+cRNmqEXV2MX8UEXetcC8nvEqw1c4bn0 - erqSykFveAF+g966E9bBZvoW2BV+l94H76CnLMUuO+E/mXIws/+Gq3M35KAXjUQhLT3N - 5XTYU20pvBW3/KREk9Gg12k1apVSERcrj5FJOQnL0BSBTI+toskacDQFGIdt6tQsUbb5 - sMB3VUETPsrWQMXYOgGr2M6HqjE1Bay58JqaQrSmMFqTKKwTYWJWptVjswZec9usQdI4 - swH5e902rzUwFOFnRPhtET4OeZ7HBlaPocVtDZAmqydQ0dHS5WlyZ2WSAQHhiMnKFDcO - AeRixwGY4luHGyxMEWt4Aiab2xMw2pBHHW33+BYEamc2eNyJPO/FMiyqa8AxsjJbA2gn - bIldYFuwJShAc5PI+W5pCNA+b4BqEvtSZgT0NndAv/ac4UfxCufZepUyQNkrfP6uioDQ - tAXBFcUmUfJtRamq3ordUpu8DQGyacQI0cbFaKlobvRMsDcttgZktnJbS9fiJgQX6hr6 - TYIpsvkGoLah3ygYI0JW5oBhfSmPsx/Impw1WcxLecP6aP7Fb6Plbw6KuWH9iTOYV9WN - AkBEBGzT0M6AdX5kEBsaWywm/mLoml+MOGHwEpxmK9ozJUChz9D2AGuf5gt01l8xo8Ud - Na5psbtfZjRFDqFyL9Zv6lJMwJXC+gqbtesintZNtqEvx5b4RkokdsVFEJXiQo/6SoD4 - rvAd4mFpx1m3GGwt4vp2RNYUZZvBc1UByiI0os0BDR7gtQ18wOrFAnybzKwKgqy24RAh - 3d4gCW8Kgts8gO+o9K3zUJ0pulqrG8dHISsTC9J55MZlWitw5ArRV6xd1q5pC7qsFdYW - dCbGHslR4e/yZiOC9Q2IE8zCEQVv4ijr93onYD/ZYj/YBKt3ebGHxSM9YB4pyh7GSjmZ - eJjSjtqGmQ2BTndiQHB7cRXQfQdrGwKD6LleL9bKHbUULV7XahixOQ9tzk1HfX60F3x3 - 6cQuvF1dYp/1DTY+MNjVldglPm9ROUjg2gJhpCAIYhUR8iDprMW2mNn4xMga8DYezfKK - mBagS1/xKHxn/3mEi0btxpbj0dqiCMLFvxDCJdeD8ITrQrh01NIxCE9Em0tFhG/49RCe - NAbhsp9HWBi1G42cjNYKEYTLfyGEp1wPwu7rQtgzaukYhCvQZo+IcOWvh/DUMQhP+3mE - p4/ajUZWobXTIwhX/0IIz7gehGuuC+EbRy0dg3At2nyjiPDMXw/hujEI1/88wrNG7UYj - b0JrZ0UQnv0LITznehBuuC6EvaOWjkG4EW32igjfPIqwkBiAq/fhzmu2XfjFN+ZbroIc - 35RYFZRT+6Abyc2sBAHpxEiei3kpfmiXUyWgR74Tq1+554nFr4/dKLvwnTz68Y3CSKDx - G4xF/f9P4EaGleL5HRPhC+BO/C7LJHXkY6qLpuhPmTxmK778lwMwp/A7lMb7rLLoHZM0 - G18EkKSKIMApJFFGnv4wCAwSIM99CMewBcDsjGPYC4t5Tm6+klc6kcqZ7uDlT9nnv58S - ZGb8gPcViE53aB7lY0+DBiYJMo1Sptbp9SbZcfIwftdoyMNCvACdTLXCqNV9wy+tMwS5 - vE0ZGTUXZgyZPjINvTVU4/G7P4eystwcQnESpUKvU9vGEafD6ShUjC9SU/Meya6cmdez - 5oGKtGKdfG7pcfZ06PVtH4Q+CX381fbQP8+uX7p9z5wbieuLHmKP2ONGe/RojxqKhFip - EtRatIepTlCLJuHVHJokkxo12m/4st/gxYZoyVtDH11lh1o1vkipcDro/GSiTyZaBSeh - Kx8bVyFasXOyIydtXumx0DxS1P0O4Qn/1Xaiu7TSv+7C7aF3//Fg6GMcggIh/B6TxPZB - An4J3y7o72FJhVRbmMAmFXJxqmJ6uaFYnlxpVnScMLw1NDwEZUNlQ7k5U9YIBZAY5yB2 - k0NmZx26eIMLUVW5SKIUOYUEOX2s1kXUFCbGmCQXKBlMxHsJIiaRsAGvLfU6pYKjeKvT - oSwYr+JVRcoCypZCKTV6XT4t3Nk0Z33o01BofWtZByns2r36wGM92VOfZvvOHQr9JfTh - H0L/feY4Kb1wkFR8f+5bUneBlIZOhz76YNOfcWq43idwgqfZB3B1bYekJEjyhViG4WIZ - rpeFmEqZOKkTp4dLcEkvvJaboy6cRMbnK23KE3/c6egepC91qb27v7+NvhTpS0AfTWYf - gRTYLdQUMRXMHHaJ+bbktckbyT2UNF3aaFxivNN4Z9IzRhZSSAKTFG/kuSQj3kGyloSE - FHVMoZq1WlbxKbH8XVyxbnlKvDNhg6U4JbXSFgX3wpDi4tBZKJs4PLFsSKkqyVbpSwjm - qpISJSYwNwJ7EmOMtSsdclW8C2QaDsFl4hQxLiLVYoL4KhQRfBHaIlUZKRpfVFjgsKVw - Es6GPJ+n0mo4SQKRYAGv5advenFwQ0Fd77qBSgfzLF2+irgufbam4pnNzcULTHT85bQB - ompbXlVYv2Rdz9aqTcc7ToUuPfHU2kp/dVHunMX7Irjkov+Y2J2QCycEy7TY+ix/2vys - VWmrsiS9DlIlzYgxZGji6O9yNYVx+EFpEzTKQsVdcXG5iYWpLFeYG2fodbqVQbwJTogp - HrecsqRZN9BOKr8y7ypUhi5EHQ9BuTD8uWJIIeIjYhOBpCg7x+gAGesw21McEqBdwNDS - HIQjyWZxgclucBGGcAhXNibJfCJi5sBk1BkVE0Vv3LABMSNzGaowX4e+lxcFTsIVJpP8 - vKtgLBBhxK92RBAfOA3YiO7cc7Guime7n3pml8quTnLo/JNX9PmPeBxsv3Ab0X7wVWVm - xe13hb7+1kn0J7eU3d63ensHIY/RlLV425L21eVrH287+ceBjXX5ZsuhztdCIYQVd8JS - xJVnavBuzABG2Cbk90l7FTt0TzJ7pLsVe3VB6UnpO8y5+P/SxE6QSswGLtaskhs5o1FL - ORNMiTKn1mhKDBLZYX7F3JGto0ZxacYQQojufuUhzsTjxCFXyxwASspBOD1ybBxyMZpY - BxAFJlKdxEHoeExElKIPLyKVqioscKJnSbQaXb4KlAqKT4FCBeRz1JlNOdXHnuztfQIv - Ai+HvvkodJmovpC0k4TdvfO2X+7ff5Z+P/Rl6EJoOPQ0ybhM4onAimdA+B36KFOFN4fZ - ZJxwX7Gsj+1V7dD0afvSJa5Uu7OIr+ArUyuds1PnOBemLnKsiV0Ttya+w9ae2m5vd+xO - 3pOppkGuZbOYcWowaRP1SQZtlmacK0HeKnXYi+yUPSUuhslQG/6UZFZzjHnczgx5NieL - V1AcZPPZJotBZ3DqJ7kcnNNlyo23OBWTwDnOmJPbz+++guCF4RIRxOESBXLofiUl2Zgq - S8QdZAgxRbfUl9weccpqkkU5tLg98vEWHmR4JU/oTLw8Y9ORM6uwLFFj4Ik1IYUHPiU+ - TuqM4YnDLoshWQyP/2EwSVYm8cSowyTiqoqJ6KiRZMwOij6Lx1jUYZ2ObCKeRgVF+Xl6 - HWdDPrJCep2FYB2tRmJLcTjJeandvWdB3w3Olfdtntz+wcDXS6ZQ+1jHpB0LWz2umjte - Km997+Pzr3DkWVLbmDNnzs2eVJ05NSV92oa+57obW27Iq6wRKtKNanN2pmf7fafee5z6 - Dvdaffg8JWMb0VvrnokbFzMYj/ttmWBndCV6WhIfozTh0Ya3k2mgjdcm0BY8/S/rjEbT - ZX7Ruqh/Ds8tOZGNm58iesxml5VNnDE8cUgxfBa35nxlvtYWORTyisZr4wnOo1BpK8zf - c3T/foc2Ny5ZY5niXN94//1sY+h0z7CnWC0nVLdMumER9XIPPk8UdIY/oz/GW0M9WjhP - mBDUnNRQMrVUY1QbNS7JHfQ7HCcFNj4GJHExLD5LBs5gkOtwJmmxcpOJpInGvsk3l//4 - MKF5Z3H5o89T2UTRIXJzxD2ERA3FTUOJx8l43GxtKbgqSjspNuX89jm3/cg+ylawqOdc - fRY5yGQPl9QVNO1pfISK/+GNR29In7WjbjP1rkm0ORLCfrwv/ldBjoVy3B/UePJqQYc3 - y7NhDuA/QlwNFZIYJPhvEG6sqqyfNS1jqn9ph7+9db4vUiOixqQASUCqRWpCakPqRNqG - 9DhSAGkQ6VR4JCAPozzB986xMv4/HKPPuUbOvUbOu0bOv0Zefo288ho58q/0KntWifr/ - A9iD96AKZW5kc3RyZWFtCmVuZG9iagoyNiAwIG9iago0NzQ0CmVuZG9iagoyNyAwIG9i - ago8PCAvVHlwZSAvRm9udERlc2NyaXB0b3IgL0FzY2VudCA3NzAgL0NhcEhlaWdodCA3 - MTcgL0Rlc2NlbnQgLTIzMCAvRmxhZ3MgMzIKL0ZvbnRCQm94IFstOTUxIC00ODEgMTQ0 - NSAxMTIyXSAvRm9udE5hbWUgL09LR1NUSStIZWx2ZXRpY2EgL0l0YWxpY0FuZ2xlIDAK - L1N0ZW1WIDAgL01heFdpZHRoIDE1MDAgL1hIZWlnaHQgNjM3IC9Gb250RmlsZTIgMjUg - MCBSID4+CmVuZG9iagoyOCAwIG9iagpbIDMzMyAzMzMgMCAwIDAgMCAwIDAgNTU2IDU1 - NiA1NTYgNTU2IDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwCjAgMCAw - IDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAg - MCAwIDAgMCAwIDAgMCAwIDAKMCAwIDAgMCA1NTYgMCAwIDAgNTAwIDI3OCA1NTYgXQpl - bmRvYmoKMTIgMCBvYmoKPDwgL1R5cGUgL0ZvbnQgL1N1YnR5cGUgL1RydWVUeXBlIC9C - YXNlRm9udCAvT0tHU1RJK0hlbHZldGljYSAvRm9udERlc2NyaXB0b3IKMjcgMCBSIC9X - aWR0aHMgMjggMCBSIC9GaXJzdENoYXIgNDAgL0xhc3RDaGFyIDExNyAvRW5jb2Rpbmcg - L01hY1JvbWFuRW5jb2RpbmcKPj4KZW5kb2JqCjI5IDAgb2JqCjw8IC9MZW5ndGggMzAg - MCBSIC9MZW5ndGgxIDUzNjQgL0ZpbHRlciAvRmxhdGVEZWNvZGUgPj4Kc3RyZWFtCngB - vVh/cBNVHv++/ZGkPzjTUmj6I+zGJW3Tprbl17W0R5eQlJb+sFDABCkkaVPTSqUHJSd6 - cBkPPAnI6SGcgqOidyrtIUvagS0cXGXw0Dl/oI7c6TmjnKA3N3a8H+KoSPe+u0kjZZTp - H4z75u3353vv8z7v5e1uetdtCMAkCAMNzSt8PR2gXRmDKMS2bl9PzE4fRjm9LdTLx2y2 - AIBe09FzR3fMNjwCkGy+Y83GePv0TwHIz4MBX3ssDt+gnBNER8wms1BOD3b33h2z09Xx - UtesbYvH0y+gbej23R0fH95Hm7/L1x2I5Wc8hHJ6z9r1vXE7iLKgZ10gnk/ciO8NIOil - YS0kwZ2gBwqMWFoB9P9MNgODUTWOV7s9Zdfqm6ouQZpBs1c3/lqTf7b88dyXgW/yUx42 - fIWOpLF8VepsozaETDA+kvJwIqK1wxstQ0uRDHVYq7HOxlpUNN8EYfIsPIT1Kaw0dJLt - sBHrNqyPYWUS2gG0hsj2KGMQj5GNkE0WiSkMtzQjizMlp3BvyUQ3+AT3rumj4yQLV+88 - yYpOgqT5yeQp8iS0A0d+D1ZyD9RCAdk7YFvDeTF0AHqwhrHS2p2QA9FpM7iTxA5WhmCb - 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 - aHQgNjg0IC9EZXNjZW50IC0yMzAgL0ZsYWdzIDMyCi9Gb250QkJveCBbLTk1MSAtNDgx - IDE0NDUgMTEyMl0gL0ZvbnROYW1lIC9CRUJWQlYrSGVsdmV0aWNhIC9JdGFsaWNBbmds - ZSAwCi9TdGVtViAwIC9NYXhXaWR0aCAxNTAwIC9YSGVpZ2h0IDUxMyAvRm9udEZpbGUy - IDI5IDAgUiA+PgplbmRvYmoKMzIgMCBvYmoKWyAyMjIgMCAwIDAgMCA1NTYgXQplbmRv - YmoKMTEgMCBvYmoKPDwgL1R5cGUgL0ZvbnQgL1N1YnR5cGUgL1RydWVUeXBlIC9CYXNl - Rm9udCAvQkVCVkJWK0hlbHZldGljYSAvRm9udERlc2NyaXB0b3IKMzEgMCBSIC9XaWR0 - aHMgMzIgMCBSIC9GaXJzdENoYXIgMTA1IC9MYXN0Q2hhciAxMTAgL0VuY29kaW5nIC9N - YWNSb21hbkVuY29kaW5nCj4+CmVuZG9iagozMyAwIG9iagooTWFjIE9TIFggMTAuNi44 - IFF1YXJ0eiBQREZDb250ZXh0KQplbmRvYmoKMzQgMCBvYmoKKEQ6MjAxMjA1MzAxNzEy - MzRaMDAnMDAnKQplbmRvYmoKMSAwIG9iago8PCAvUHJvZHVjZXIgMzMgMCBSIC9DcmVh - dGlvbkRhdGUgMzQgMCBSIC9Nb2REYXRlIDM0IDAgUiA+PgplbmRvYmoKeHJlZgowIDM1 - CjAwMDAwMDAwMDAgNjU1MzUgZiAKMDAwMDAxNjk1MCAwMDAwMCBuIAowMDAwMDAzMDAx - IDAwMDAwIG4gCjAwMDAwMDA4NTIgMDAwMDAgbiAKMDAwMDAwMjg1MiAwMDAwMCBuIAow - MDAwMDAwMDIyIDAwMDAwIG4gCjAwMDAwMDA4MzMgMDAwMDAgbiAKMDAwMDAwMDk1NiAw - MDAwMCBuIAowMDAwMDAyODE2IDAwMDAwIG4gCjAwMDAwMDE5MjAgMDAwMDAgbiAKMDAw - MDAwNzcxMyAwMDAwMCBuIAowMDAwMDE2NjgwIDAwMDAwIG4gCjAwMDAwMTMxNjQgMDAw - MDAgbiAKMDAwMDAwMTA5MiAwMDAwMCBuIAowMDAwMDAxOTAwIDAwMDAwIG4gCjAwMDAw - MDE5NTYgMDAwMDAgbiAKMDAwMDAwMjc5NiAwMDAwMCBuIAowMDAwMDAyOTM1IDAwMDAw - IG4gCjAwMDAwMDMxNjQgMDAwMDAgbiAKMDAwMDAwMzA0OSAwMDAwMCBuIAowMDAwMDAz - MTQyIDAwMDAwIG4gCjAwMDAwMDMyNTcgMDAwMDAgbiAKMDAwMDAwNzM2MyAwMDAwMCBu - IAowMDAwMDA3Mzg0IDAwMDAwIG4gCjAwMDAwMDc2MDkgMDAwMDAgbiAKMDAwMDAwNzg4 - OCAwMDAwMCBuIAowMDAwMDEyNzIyIDAwMDAwIG4gCjAwMDAwMTI3NDMgMDAwMDAgbiAK - MDAwMDAxMjk2OCAwMDAwMCBuIAowMDAwMDEzMzM5IDAwMDAwIG4gCjAwMDAwMTYzOTgg - MDAwMDAgbiAKMDAwMDAxNjQxOSAwMDAwMCBuIAowMDAwMDE2NjQ0IDAwMDAwIG4gCjAw - MDAwMTY4NTYgMDAwMDAgbiAKMDAwMDAxNjkwOCAwMDAwMCBuIAp0cmFpbGVyCjw8IC9T - aXplIDM1IC9Sb290IDE3IDAgUiAvSW5mbyAxIDAgUiAvSUQgWyA8ZDVjZDdhYmY5Y2Y1 - MmI4M2U5MzNiM2E0YjVhMjc4MjM+CjxkNWNkN2FiZjljZjUyYjgzZTkzM2IzYTRiNWEy - NzgyMz4gXSA+PgpzdGFydHhyZWYKMTcwMjUKJSVFT0YKMSAwIG9iago8PC9BdXRob3Ig - KEpvbmF0aGFuIEJhY2hyYWNoKS9DcmVhdGlvbkRhdGUgKEQ6MjAxMjA1MjkyMzMxMDBa - KS9DcmVhdG9yIChPbW5pR3JhZmZsZSBQcm9mZXNzaW9uYWwgNS4zLjYpL01vZERhdGUg - KEQ6MjAxMjA1MzAxNzEyMDBaKS9Qcm9kdWNlciAzMyAwIFIgL1RpdGxlIChyb3V0ZXIp - Pj4KZW5kb2JqCnhyZWYKMSAxCjAwMDAwMTc4ODMgMDAwMDAgbiAKdHJhaWxlcgo8PC9J - RCBbPGQ1Y2Q3YWJmOWNmNTJiODNlOTMzYjNhNGI1YTI3ODIzPiA8ZDVjZDdhYmY5Y2Y1 - MmI4M2U5MzNiM2E0YjVhMjc4MjM+XSAvSW5mbyAxIDAgUiAvUHJldiAxNzAyNSAvUm9v - dCAxNyAwIFIgL1NpemUgMzU+PgpzdGFydHhyZWYKMTgwNjQKJSVFT0YK - - QuickLookThumbnail - - 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 - - ReadOnly - NO - RowAlign - 1 - RowSpacing - 36 - SheetTitle - Canvas 1 - SmartAlignmentGuidesActive - YES - SmartDistanceGuidesActive - YES - UniqueID - 1 - UseEntirePage - - VPages - 1 - WindowInfo - - CurrentSheet - 0 - ExpandedCanvases - - Frame - {{77, 4}, {1160, 874}} - ListView - - OutlineWidth - 142 - RightSidebar - - ShowRuler - - Sidebar - - SidebarWidth - 120 - VisibleRegion - {{63, 0}, {505.5, 352.5}} - Zoom - 2 - ZoomValues - - - Canvas 1 - 2 - 1 - - - - saveQuickLookFiles - YES - - diff --git a/doc/cs250/figs/router.pdf b/doc/cs250/figs/router.pdf deleted file mode 100644 index 273be523..00000000 Binary files a/doc/cs250/figs/router.pdf and /dev/null differ diff --git a/doc/cs250/figs/schematic-capture.graffle/data.plist b/doc/cs250/figs/schematic-capture.graffle/data.plist deleted file mode 100644 index 268ccc6f..00000000 Binary files a/doc/cs250/figs/schematic-capture.graffle/data.plist and /dev/null differ diff --git a/doc/cs250/figs/schematic-capture.graffle/image1.pdf b/doc/cs250/figs/schematic-capture.graffle/image1.pdf deleted file mode 100644 index ce233477..00000000 Binary files a/doc/cs250/figs/schematic-capture.graffle/image1.pdf and /dev/null differ diff --git a/doc/cs250/figs/schematic-capture.pdf b/doc/cs250/figs/schematic-capture.pdf deleted file mode 100644 index df5d1110..00000000 Binary files a/doc/cs250/figs/schematic-capture.pdf and /dev/null differ diff --git a/doc/cs250/figs/sel.graffle b/doc/cs250/figs/sel.graffle deleted file mode 100644 index 608e3705..00000000 Binary files a/doc/cs250/figs/sel.graffle and /dev/null differ diff --git a/doc/cs250/figs/sel.pdf b/doc/cs250/figs/sel.pdf deleted file mode 100644 index 324ef5c0..00000000 Binary files a/doc/cs250/figs/sel.pdf and /dev/null differ diff --git a/doc/cs250/figs/skin-sim.png b/doc/cs250/figs/skin-sim.png deleted file mode 100644 index 40d31b02..00000000 Binary files a/doc/cs250/figs/skin-sim.png and /dev/null differ diff --git a/doc/cs250/figs/small-odds.graffle b/doc/cs250/figs/small-odds.graffle deleted file mode 100644 index 58b1e696..00000000 Binary files a/doc/cs250/figs/small-odds.graffle and /dev/null differ diff --git a/doc/cs250/figs/small-odds.pdf b/doc/cs250/figs/small-odds.pdf deleted file mode 100644 index 364d1f5d..00000000 Binary files a/doc/cs250/figs/small-odds.pdf and /dev/null differ diff --git a/doc/cs250/figs/testing.graffle b/doc/cs250/figs/testing.graffle deleted file mode 100644 index 63a9554d..00000000 --- a/doc/cs250/figs/testing.graffle +++ /dev/null @@ -1,464 +0,0 @@ - - - - - ActiveLayerIndex - 0 - ApplicationVersion - - com.omnigroup.OmniGrafflePro - 139.7.0.167456 - - AutoAdjust - - BackgroundGraphic - - Bounds - {{0, 0}, {756, 553}} - Class - SolidGraphic - ID - 2 - Style - - shadow - - Draws - NO - - stroke - - Draws - NO - - - - BaseZoom - 0 - CanvasOrigin - {0, 0} - ColumnAlign - 1 - ColumnSpacing - 36 - CreationDate - 2012-06-05 23:04:25 -0700 - Creator - Jonathan Bachrach - DisplayScale - 1 0/72 in = 1 0/72 in - GraphDocumentVersion - 8 - GraphicsList - - - Bounds - {{240, 231.5}, {96, 41}} - Class - ShapedGraphic - FitText - YES - Flow - Resize - FontInfo - - Color - - w - 0 - - Font - Helvetica - Size - 26 - - ID - 10 - Line - - ID - 6 - Position - 0.5 - RotationType - 0 - - Shape - Rectangle - Style - - shadow - - Draws - NO - - stroke - - Draws - NO - - - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1038\cocoasubrtf360 -{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural - -\f0\fs52 \cf0 outputs} - - Wrap - NO - - - Bounds - {{248, 159.5}, {80, 41}} - Class - ShapedGraphic - FitText - YES - Flow - Resize - FontInfo - - Color - - w - 0 - - Font - Helvetica - Size - 26 - - ID - 9 - Line - - ID - 5 - Position - 0.5 - RotationType - 0 - - Shape - Rectangle - Style - - shadow - - Draws - NO - - stroke - - Draws - NO - - - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1038\cocoasubrtf360 -{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural - -\f0\fs52 \cf0 inputs} - - Wrap - NO - - - Class - LineGraphic - FontInfo - - Font - Helvetica - Size - 25 - - ID - 6 - Points - - {216, 252} - {360, 252} - - Style - - stroke - - HeadArrow - 0 - Legacy - - TailArrow - StickArrow - Width - 2 - - - - - Class - LineGraphic - FontInfo - - Font - Helvetica - Size - 25 - - ID - 5 - Points - - {216, 180} - {360, 180} - - Style - - stroke - - HeadArrow - StickArrow - Legacy - - TailArrow - 0 - Width - 2 - - - - - Bounds - {{360, 144}, {144, 144}} - Class - ShapedGraphic - FontInfo - - Font - Helvetica - Size - 25 - - ID - 4 - Shape - Rectangle - Style - - stroke - - Width - 2 - - - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1038\cocoasubrtf360 -{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural - -\f0\fs52 \cf0 CUT} - - - - Bounds - {{72, 144}, {144, 144}} - Class - ShapedGraphic - FontInfo - - Font - Helvetica - Size - 25 - - ID - 3 - Shape - Rectangle - Style - - stroke - - Width - 2 - - - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1038\cocoasubrtf360 -{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural - -\f0\fs52 \cf0 Chisel} - - - - GridInfo - - ShowsGrid - YES - SnapsToGrid - YES - - GuidesLocked - NO - GuidesVisible - YES - HPages - 1 - ImageCounter - 1 - KeepToScale - - Layers - - - Lock - NO - Name - Layer 1 - Print - YES - View - YES - - - LayoutInfo - - Animate - NO - circoMinDist - 18 - circoSeparation - 0.0 - layoutEngine - dot - neatoSeparation - 0.0 - twopiSeparation - 0.0 - - LinksVisible - NO - MagnetsVisible - NO - MasterSheets - - ModificationDate - 2012-06-05 23:07:13 -0700 - Modifier - Jonathan Bachrach - NotesVisible - NO - Orientation - 2 - OriginVisible - NO - PageBreaks - YES - PrintInfo - - NSBottomMargin - - float - 41 - - NSLeftMargin - - float - 18 - - NSOrientation - - int - 1 - - NSPaperSize - - size - {792, 612} - - NSRightMargin - - float - 18 - - NSTopMargin - - float - 18 - - - PrintOnePage - - ReadOnly - NO - RowAlign - 1 - RowSpacing - 36 - SheetTitle - Canvas 1 - SmartAlignmentGuidesActive - YES - SmartDistanceGuidesActive - YES - UniqueID - 1 - UseEntirePage - - VPages - 1 - WindowInfo - - CurrentSheet - 0 - ExpandedCanvases - - - name - Canvas 1 - - - Frame - {{1005, 627}, {710, 871}} - ListView - - OutlineWidth - 142 - RightSidebar - - ShowRuler - - Sidebar - - SidebarWidth - 120 - VisibleRegion - {{0, -82}, {575, 718}} - Zoom - 1 - ZoomValues - - - Canvas 1 - 1 - 1 - - - - - diff --git a/doc/cs250/figs/traditional-generator-design-process.graffle b/doc/cs250/figs/traditional-generator-design-process.graffle deleted file mode 100644 index 2da6f3e7..00000000 Binary files a/doc/cs250/figs/traditional-generator-design-process.graffle and /dev/null differ diff --git a/doc/cs250/figs/traditional-generator-design-process.pdf b/doc/cs250/figs/traditional-generator-design-process.pdf deleted file mode 100644 index fbd52035..00000000 Binary files a/doc/cs250/figs/traditional-generator-design-process.pdf and /dev/null differ diff --git a/doc/cs250/figs/traditional-static-design-process.graffle b/doc/cs250/figs/traditional-static-design-process.graffle deleted file mode 100644 index 340543fe..00000000 Binary files a/doc/cs250/figs/traditional-static-design-process.graffle and /dev/null differ diff --git a/doc/cs250/figs/traditional-static-design-process.pdf b/doc/cs250/figs/traditional-static-design-process.pdf deleted file mode 100644 index 586e45c0..00000000 Binary files a/doc/cs250/figs/traditional-static-design-process.pdf and /dev/null differ diff --git a/doc/cs250/figs/transactors-network.graffle b/doc/cs250/figs/transactors-network.graffle deleted file mode 100644 index af8bf7a2..00000000 Binary files a/doc/cs250/figs/transactors-network.graffle and /dev/null differ diff --git a/doc/cs250/figs/transactors-network.pdf b/doc/cs250/figs/transactors-network.pdf deleted file mode 100644 index 8f447b9d..00000000 Binary files a/doc/cs250/figs/transactors-network.pdf and /dev/null differ diff --git a/doc/cs250/figs/transactors.graffle b/doc/cs250/figs/transactors.graffle deleted file mode 100644 index 129d6f5f..00000000 --- a/doc/cs250/figs/transactors.graffle +++ /dev/null @@ -1,1321 +0,0 @@ - - - - - ActiveLayerIndex - 0 - ApplicationVersion - - com.omnigroup.OmniGrafflePro - 139.16.0.171715 - - AutoAdjust - - BackgroundGraphic - - Bounds - {{0, 0}, {756, 553}} - Class - SolidGraphic - ID - 2 - Style - - shadow - - Draws - NO - - stroke - - Draws - NO - - - - BaseZoom - 0 - CanvasOrigin - {0, 0} - ColumnAlign - 1 - ColumnSpacing - 36 - CreationDate - 2012-05-03 17:47:55 +0000 - Creator - Jonathan Bachrach - DisplayScale - 1 0/72 in = 1.0000 in - GraphDocumentVersion - 8 - GraphicsList - - - Class - LineGraphic - Head - - ID - 4 - - ID - 75 - Points - - {378, 215.5} - {378, 261.5} - - Style - - stroke - - HeadArrow - 0 - Legacy - - TailArrow - 0 - - - Tail - - ID - 20 - - - - Class - LineGraphic - Head - - ID - 4 - - ID - 73 - Points - - {144, 324} - {205.40437779812248, 307.59925806674079} - - Style - - stroke - - HeadArrow - FilledArrow - Legacy - - TailArrow - 0 - - - - - Class - LineGraphic - Head - - ID - 4 - - ID - 72 - Points - - {144, 225} - {199.37403229929427, 233.63740247403521} - - Style - - stroke - - HeadArrow - FilledArrow - Legacy - - TailArrow - 0 - - - Tail - - ID - 47 - - - - Class - LineGraphic - Head - - ID - 4 - - ID - 71 - Points - - {594, 324} - {549.10408093522597, 311.00928267801675} - - Style - - stroke - - HeadArrow - 0 - Legacy - - TailArrow - FilledArrow - - - - - Class - LineGraphic - Head - - ID - 4 - - ID - 70 - Points - - {594, 225} - {556.05865005510407, 231.41138552309584} - - Style - - stroke - - HeadArrow - 0 - Legacy - - TailArrow - FilledArrow - - - - - Bounds - {{589.5, 157}, {82, 14}} - Class - ShapedGraphic - FitText - YES - Flow - Resize - ID - 68 - Shape - Rectangle - Style - - fill - - Draws - NO - - shadow - - Draws - NO - - stroke - - Draws - NO - - - Text - - Pad - 0 - Text - {\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf340 -\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc - -\f0\fs24 \cf0 Output Queues} - VerticalPad - 0 - - Wrap - NO - - - Bounds - {{54.5, 164}, {73, 14}} - Class - ShapedGraphic - FitText - YES - Flow - Resize - ID - 67 - Shape - Rectangle - Style - - fill - - Draws - NO - - shadow - - Draws - NO - - stroke - - Draws - NO - - - Text - - Pad - 0 - Text - {\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf340 -\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc - -\f0\fs24 \cf0 Input Queues} - VerticalPad - 0 - - Wrap - NO - - - Class - Group - Graphics - - - Class - LineGraphic - Head - - ID - 66 - Position - 0.5 - - ID - 61 - Points - - {675, 324} - {648, 324} - - Style - - stroke - - HeadArrow - 0 - Legacy - - TailArrow - FilledArrow - Width - 2 - - - - - Class - LineGraphic - ID - 62 - Points - - {612, 306} - {612, 342} - - Style - - stroke - - HeadArrow - 0 - Legacy - - TailArrow - 0 - Width - 2 - - - - - Class - LineGraphic - ID - 63 - Points - - {621, 306} - {621, 342} - - Style - - stroke - - HeadArrow - 0 - Legacy - - TailArrow - 0 - Width - 2 - - - - - Class - LineGraphic - ID - 64 - Points - - {630.00000040233135, 306} - {630, 342} - - Style - - stroke - - HeadArrow - 0 - Legacy - - TailArrow - 0 - Width - 2 - - - Tail - - ID - 66 - Position - 0.21428573131561279 - - - - Class - LineGraphic - ID - 65 - Points - - {639.00000187754631, 306} - {639, 342} - - Style - - stroke - - HeadArrow - 0 - Legacy - - TailArrow - 0 - Width - 2 - - - Tail - - ID - 66 - Position - 0.28571432828903198 - - - - Class - LineGraphic - ID - 66 - Points - - {603, 306} - {648, 306} - {648, 342} - {603, 342} - - Style - - stroke - - HeadArrow - 0 - Legacy - - TailArrow - 0 - Width - 2 - - - - - ID - 60 - - - Class - Group - Graphics - - - Class - LineGraphic - Head - - ID - 59 - Position - 0.5 - - ID - 54 - Points - - {675, 225} - {648, 225} - - Style - - stroke - - HeadArrow - 0 - Legacy - - TailArrow - FilledArrow - Width - 2 - - - - - Class - LineGraphic - ID - 55 - Points - - {612, 207} - {612, 243} - - Style - - stroke - - HeadArrow - 0 - Legacy - - TailArrow - 0 - Width - 2 - - - - - Class - LineGraphic - ID - 56 - Points - - {621, 207} - {621, 243} - - Style - - stroke - - HeadArrow - 0 - Legacy - - TailArrow - 0 - Width - 2 - - - - - Class - LineGraphic - ID - 57 - Points - - {630.00000040233135, 207} - {630, 243} - - Style - - stroke - - HeadArrow - 0 - Legacy - - TailArrow - 0 - Width - 2 - - - Tail - - ID - 59 - Position - 0.21428573131561279 - - - - Class - LineGraphic - ID - 58 - Points - - {639.00000187754631, 207} - {639, 243} - - Style - - stroke - - HeadArrow - 0 - Legacy - - TailArrow - 0 - Width - 2 - - - Tail - - ID - 59 - Position - 0.28571432828903198 - - - - Class - LineGraphic - ID - 59 - Points - - {603, 207} - {648, 207} - {648, 243} - {603, 243} - - Style - - stroke - - HeadArrow - 0 - Legacy - - TailArrow - 0 - Width - 2 - - - - - ID - 53 - - - Class - Group - Graphics - - - Class - LineGraphic - Head - - ID - 52 - Position - 0.5 - - ID - 47 - Points - - {144, 225} - {117, 225} - - Style - - stroke - - HeadArrow - 0 - Legacy - - TailArrow - FilledArrow - Width - 2 - - - - - Class - LineGraphic - ID - 48 - Points - - {81, 207} - {81, 243} - - Style - - stroke - - HeadArrow - 0 - Legacy - - TailArrow - 0 - Width - 2 - - - - - Class - LineGraphic - ID - 49 - Points - - {90, 207} - {90, 243} - - Style - - stroke - - HeadArrow - 0 - Legacy - - TailArrow - 0 - Width - 2 - - - - - Class - LineGraphic - ID - 50 - Points - - {99.000000402331352, 207} - {99, 243} - - Style - - stroke - - HeadArrow - 0 - Legacy - - TailArrow - 0 - Width - 2 - - - Tail - - ID - 52 - Position - 0.21428573131561279 - - - - Class - LineGraphic - ID - 51 - Points - - {108.00000187754631, 207} - {108, 243} - - Style - - stroke - - HeadArrow - 0 - Legacy - - TailArrow - 0 - Width - 2 - - - Tail - - ID - 52 - Position - 0.28571432828903198 - - - - Class - LineGraphic - ID - 52 - Points - - {72, 207} - {117, 207} - {117, 243} - {72, 243} - - Style - - stroke - - HeadArrow - 0 - Legacy - - TailArrow - 0 - Width - 2 - - - - - ID - 46 - - - Class - Group - Graphics - - - Class - LineGraphic - Head - - ID - 45 - Position - 0.5 - - ID - 40 - Points - - {144, 324} - {117, 324} - - Style - - stroke - - HeadArrow - 0 - Legacy - - TailArrow - FilledArrow - Width - 2 - - - - - Class - LineGraphic - ID - 41 - Points - - {81, 306} - {81, 342} - - Style - - stroke - - HeadArrow - 0 - Legacy - - TailArrow - 0 - Width - 2 - - - - - Class - LineGraphic - ID - 42 - Points - - {90, 306} - {90, 342} - - Style - - stroke - - HeadArrow - 0 - Legacy - - TailArrow - 0 - Width - 2 - - - - - Class - LineGraphic - ID - 43 - Points - - {99.000000402331352, 306} - {99, 342} - - Style - - stroke - - HeadArrow - 0 - Legacy - - TailArrow - 0 - Width - 2 - - - Tail - - ID - 45 - Position - 0.21428573131561279 - - - - Class - LineGraphic - ID - 44 - Points - - {108.00000187754631, 306} - {108, 342} - - Style - - stroke - - HeadArrow - 0 - Legacy - - TailArrow - 0 - Width - 2 - - - Tail - - ID - 45 - Position - 0.28571432828903198 - - - - Class - LineGraphic - ID - 45 - Points - - {72, 306} - {117, 306} - {117, 342} - {72, 342} - - Style - - stroke - - HeadArrow - 0 - Legacy - - TailArrow - 0 - Width - 2 - - - - - ID - 39 - - - Bounds - {{306, 179}, {144, 36}} - Class - ShapedGraphic - ID - 20 - Shape - Rectangle - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf340 -\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc - -\f0\fs24 \cf0 Transactions} - - - - Class - Group - Graphics - - - Class - LineGraphic - ID - 24 - Points - - {459, 333} - {450, 351} - {459, 369} - - Style - - stroke - - HeadArrow - 0 - Legacy - - TailArrow - 0 - - - - - Bounds - {{315, 333}, {144, 36}} - Class - ShapedGraphic - ID - 25 - Shape - Rectangle - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf340 -\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc - -\f0\fs24 \cf0 Architectural State} - - - - ID - 23 - - - Bounds - {{261, 243}, {144, 54}} - Class - ShapedGraphic - ID - 18 - Shape - Circle - Style - - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf340 -\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc - -\f0\fs24 \cf0 Scheduler} - - - - Bounds - {{315, 170}, {144, 36}} - Class - ShapedGraphic - ID - 22 - Shape - Rectangle - - - Bounds - {{324, 162}, {144, 36}} - Class - ShapedGraphic - ID - 21 - Shape - Rectangle - - - Bounds - {{196.5, 117}, {363, 289}} - Class - ShapedGraphic - ID - 4 - Shape - Circle - Style - - - - GridInfo - - ShowsGrid - YES - SnapsToGrid - YES - - GuidesLocked - NO - GuidesVisible - YES - HPages - 1 - ImageCounter - 1 - KeepToScale - - Layers - - - Lock - NO - Name - Layer 1 - Print - YES - View - YES - - - LayoutInfo - - Animate - NO - circoMinDist - 18 - circoSeparation - 0.0 - layoutEngine - dot - neatoSeparation - 0.0 - twopiSeparation - 0.0 - - LinksVisible - NO - MagnetsVisible - NO - MasterSheets - - ModificationDate - 2012-05-03 18:11:11 +0000 - Modifier - Jonathan Bachrach - NotesVisible - NO - Orientation - 2 - OriginVisible - NO - PageBreaks - YES - PrintInfo - - NSBottomMargin - - float - 41 - - NSHorizonalPagination - - coded - BAtzdHJlYW10eXBlZIHoA4QBQISEhAhOU051bWJlcgCEhAdOU1ZhbHVlAISECE5TT2JqZWN0AIWEASqEhAFxlwCG - - NSLeftMargin - - float - 18 - - NSOrientation - - coded - BAtzdHJlYW10eXBlZIHoA4QBQISEhAhOU051bWJlcgCEhAdOU1ZhbHVlAISECE5TT2JqZWN0AIWEASqEhAFxlwGG - - NSPaperSize - - size - {792, 612} - - NSPrintReverseOrientation - - int - 0 - - NSRightMargin - - float - 18 - - NSTopMargin - - float - 18 - - - PrintOnePage - - ReadOnly - NO - RowAlign - 1 - RowSpacing - 36 - SheetTitle - Canvas 1 - SmartAlignmentGuidesActive - YES - SmartDistanceGuidesActive - YES - UniqueID - 1 - UseEntirePage - - VPages - 1 - WindowInfo - - CurrentSheet - 0 - ExpandedCanvases - - - name - Canvas 1 - - - Frame - {{28, 316}, {1153, 549}} - ListView - - OutlineWidth - 142 - RightSidebar - - ShowRuler - - Sidebar - - SidebarWidth - 120 - VisibleRegion - {{-131, 0}, {1018, 410}} - Zoom - 1 - ZoomValues - - - Canvas 1 - 1 - 1 - - - - - diff --git a/doc/cs250/figs/transactors.pdf b/doc/cs250/figs/transactors.pdf deleted file mode 100644 index 5a2e036f..00000000 Binary files a/doc/cs250/figs/transactors.pdf and /dev/null differ diff --git a/doc/cs250/figs/two-phase-rtl-semantics.graffle b/doc/cs250/figs/two-phase-rtl-semantics.graffle deleted file mode 100644 index 5564b833..00000000 Binary files a/doc/cs250/figs/two-phase-rtl-semantics.graffle and /dev/null differ diff --git a/doc/cs250/figs/two-phase-rtl-semantics.pdf b/doc/cs250/figs/two-phase-rtl-semantics.pdf deleted file mode 100644 index 9a646d12..00000000 Binary files a/doc/cs250/figs/two-phase-rtl-semantics.pdf and /dev/null differ diff --git a/doc/cs250/figs/ufix.graffle b/doc/cs250/figs/ufix.graffle deleted file mode 100644 index 74bef829..00000000 Binary files a/doc/cs250/figs/ufix.graffle and /dev/null differ diff --git a/doc/cs250/figs/ufix.pdf b/doc/cs250/figs/ufix.pdf deleted file mode 100644 index 5e9b5ed6..00000000 Binary files a/doc/cs250/figs/ufix.pdf and /dev/null differ diff --git a/doc/cs250/figs/vec-3-dynamic.graffle b/doc/cs250/figs/vec-3-dynamic.graffle deleted file mode 100644 index 09ccc2dc..00000000 Binary files a/doc/cs250/figs/vec-3-dynamic.graffle and /dev/null differ diff --git a/doc/cs250/figs/vec-3-dynamic.pdf b/doc/cs250/figs/vec-3-dynamic.pdf deleted file mode 100644 index 92fa5199..00000000 Binary files a/doc/cs250/figs/vec-3-dynamic.pdf and /dev/null differ diff --git a/doc/cs250/figs/vec-3-fix.graffle b/doc/cs250/figs/vec-3-fix.graffle deleted file mode 100644 index 19823295..00000000 Binary files a/doc/cs250/figs/vec-3-fix.graffle and /dev/null differ diff --git a/doc/cs250/figs/vec-3-fix.pdf b/doc/cs250/figs/vec-3-fix.pdf deleted file mode 100644 index 73d43cbf..00000000 Binary files a/doc/cs250/figs/vec-3-fix.pdf and /dev/null differ diff --git a/doc/cs250/figs/vec-3-static.graffle b/doc/cs250/figs/vec-3-static.graffle deleted file mode 100644 index 7dca4543..00000000 Binary files a/doc/cs250/figs/vec-3-static.graffle and /dev/null differ diff --git a/doc/cs250/figs/vec-3-static.pdf b/doc/cs250/figs/vec-3-static.pdf deleted file mode 100644 index 6049cda9..00000000 Binary files a/doc/cs250/figs/vec-3-static.pdf and /dev/null differ diff --git a/doc/cs250/figs/workflow.graffle b/doc/cs250/figs/workflow.graffle deleted file mode 100644 index bdfa7602..00000000 Binary files a/doc/cs250/figs/workflow.graffle and /dev/null differ diff --git a/doc/cs250/figs/workflow.pdf b/doc/cs250/figs/workflow.pdf deleted file mode 100644 index 25c8501e..00000000 Binary files a/doc/cs250/figs/workflow.pdf and /dev/null differ diff --git a/doc/cs250/figs/wr.pdf b/doc/cs250/figs/wr.pdf deleted file mode 100644 index d5d62a93..00000000 Binary files a/doc/cs250/figs/wr.pdf and /dev/null differ diff --git a/doc/cs250/figs/zedboardfuns.jpg b/doc/cs250/figs/zedboardfuns.jpg deleted file mode 100644 index c6867927..00000000 Binary files a/doc/cs250/figs/zedboardfuns.jpg and /dev/null differ diff --git a/doc/getting-started/basics-guts.tex b/doc/getting-started/basics-guts.tex deleted file mode 100644 index 7bccb920..00000000 --- a/doc/getting-started/basics-guts.tex +++ /dev/null @@ -1,440 +0,0 @@ -\subsection{The Chisel Directory Structure} - -Once you have acquired the tutorial files you should see the following Chisel tutorial directory structure under \verb+$TUT_DIR+: - -\begin{bash} -chisel-tutorial/ - Makefile - examples/ # chisel examples - Makefile # for running examples - build.sbt # project description - Accumulator.scala ... - problems/ # skeletal files for tutorial problems - Makefile # for running / testing problems - build.sbt # project description - Counter.scala ... - solutions/ # solutions to problems - Makefile # for running solutions - build.sbt # project description - Counter.scala ... -\end{bash} - -Chisel source files are distributed between \verb+examples+, \verb+problems+, and \verb+solutions+ directories. -The tutorial contains the files that you will be modifying under \verb+problems/+ while the \verb+solutions/+ folder contains the reference implementations for each of the problems. Finally, \verb+examples/+ contains source to the complete examples given in this tutorial. - -Finally, the \verb+build.sbt+ files contain the build configuration information used to specify what version of Chisel to make your project with. - -\section{Running Your First Chisel Build} - -In this section, we explain how to run your first build to explore what Chisel has to offer. We will go through a simple example for a GCD module and familiarize ourselves with the source files, simulation, and Verilog generation. More comprehensive details will follow in subsequent sections of the tutorial. - -\subsection{The Chisel Source Code} - -Now that you are more familiar with what your Chisel directory structure contains, let's start by exploring one of the Chisel files. Change directory into the \verb+examples/+ directory and open up the \verb+GCD.scala+ file with your favorite text editor. - -You will notice that file is already filled out for you to perform the well known GCD algorithm and should look like: - -\begin{scala} -package TutorialExamples - -import Chisel._ - -class GCD extends Module { - val io = new Bundle { - val a = UInt(INPUT, 16) - val b = UInt(INPUT, 16) - val e = Bool(INPUT) - val z = UInt(OUTPUT, 16) - val v = Bool(OUTPUT) - } - val x = Reg(UInt()) - val y = Reg(UInt()) - when (x > y) { x := x - y } - unless (x > y) { y := y - x } - when (io.e) { x := io.a; y := io.b } - io.z := x - io.v := y === UInt(0) -} ... -\end{scala} - -The first thing you will notice is the \verb+import Chisel._+ declaration; this imports the Chisel library files that allow us to leverage Scala as a hardware construction language. After the import declarations you will see the Scala class definition for the Chisel component you are implementing. You can think of this as almost the same thing as a module declaration in Verilog. - -Next we see the I/O specification for this component in the \verb+val io = new Bundle{...}+ definition. You will notice that the bundle takes several arguments as part of its construction, each with a specified type (UInt, Bool, etc.), a direction (either INPUT or OUTPUT), and a bit width. If a bit width is not specified, Chisel will infer the appropriate bit width for you (in this case default to 1). The \verb+io+ Bundle is essentially a constructor for the component that we are constructing. - -The next section of code performs the actual GCD computation for the module. The register declarations for \verb+x+ and \verb+y+ tell Chisel to treat \verb+x+ and \verb+y+ as a register of type UInt(). - -\begin{scala} -val x = Reg(UInt()) // declares x as UInt register -val y = Reg(UInt()) // declares y as UInt register -\end{scala} - -The \verb+when+ statement tells Chisel to perform the operation on a positive clock edge if the condition is true, treating the left hand assignments as synchronous. This is similar to how Verilog uses \verb+always @ (posedge clk)+ to specify synchronous logic. - -Finally we see the output assignments for the computation for \verb+io.z+ and \verb+io.v+. One particular thing to notice is that, we do not have to specify the width of \verb+x+ and \verb+y+ in this example. This is because Chisel does the bit width inference for you and sets these values to their appropriate widths based on the computation they are storing. - -\subsection{Running the Chisel Simulation} - -Now that we are familiar with the Chisel code for the \verb+GCD.scala+ file, let's try to simulate it by generating the C++ models. Change directory into the \verb+$DIR/examples/+ directory. Here you will see one lonely Makefile which we will call with: - -\begin{bash} -make GCD.out -\end{bash} - -\noindent -This will fire off the Chisel emulator that will run the simulation for the component defined in \verb+GCD.scala+. If the simulation succeeds, you should see some debug output followed by: -\begin{footnotesize} -\begin{bash} -PASSED -[success] Total time: 2 s, completed Feb 28, 2013 \ - 8:14:37 PM -\end{bash} -\end{footnotesize} - -The debug output is generated by the test harness which composes the second half of the GCD.scala file. We will talk about this more later. In addition to the debug output, the build also creates C++ models which can be used to simulate and debug more complicated designs. - -\subsection{Generating the Verilog} - -One of the most powerful features of Chisel is its ability to generate FPGA and ASIC Verilog from the Scala sources that you construct. To do this, change directory into the \verb+$DIR/examples/verilog/+ directory and again run: -\begin{bash} -make GCD.v -\end{bash} -This will start the Verilog generation for the GCD Chisel file. When the Verilog generation finishes, you should see a [success] message similar to the one you saw in the emulator and a new \verb+GCD.v+ file. If you open up \verb+GCD.v+, you will find that Chisel has compiled \verb+GCD.scala+ into its equivalent Verilog source. - -You will find that the Chisel compiler has generated an equivalent Verilog module that performs the GCD computation. - -The Verilog source is roughly divided into three parts: -\begin{enumerate} -\item Module declaration with input and outputs -\item Temporary wire and register declaration used for holding intermediate values -\item Register assignments in \verb+always @ (posedge clk)+ -\end{enumerate} - -\section{Combinational Logic} - -\subsection{The Scala Node: Declaring Wires} - -Constructing combinational logic blocks in Chisel is fairly straightforward; when you declare a \verb+val+ in Scala, it creates a node that represents the data that it is assigned to. As long as the value is not assigned to be a register type (explained later), this tells the Chisel compiler to treat the value as wire. Thus any number of these values can be connected and manipulated to produce the value that we want. - -Suppose we want to construct a single full adder. A full adder takes two inputs \verb+a+ and \verb+b+, and a carry in \verb+cin+ and produces a \verb+sum+ and carry out \verb+cout+. The Chisel source code for our full adder will look something like: - -\begin{scala} -class FullAdder extends Module { - val io = new Bundle { - val a = UInt(INPUT, 1) - val b = UInt(INPUT, 1) - val cin = UInt(INPUT, 1) - val sum = UInt(OUTPUT, 1) - val cout = UInt(OUTPUT, 1) - } - // Generate the sum - val a_xor_b = io.a ^ io.b - io.sum := a_xor_b ^ io.cin - // Generate the carry - val a_and_b = io.a & io.b - val b_and_cin = io.b & io.cin - val a_and_cin = io.a & io.cin - io.cout := a_and_b | b_and_cin | a_and_cin -} -\end{scala} - -\noindent -where \verb+cout+ is defined as a combinational function of inputs \verb+a+, \verb+b+, and \verb+cin+. - -You will notice that in order to access the input values from the \verb+io+ bundle, you need to first reference \verb+io+ since the input and output values belong to the \verb+io+ bundle. The |, \&, and \^\ operators correspond to bitwise OR, AND, and XOR operations respectively. - -The corresponding wires for each of these values is shown below in Figure~\ref{fig:full-adder}. You will notice that each \verb+val+ corresponds to exactly one of the wires. - -\begin{figure}[ht!] -\centering -\includegraphics[width=80mm]{figs/Full_Adder.jpg} -\caption{Full Adder Circuit} -\label{fig:full-adder} -\end{figure} - - -\subsection{Bit Width Inference} - -If you don't explicitly specify the width of a value in Chisel, the Chisel compiler will infer the bit width for you based on the inputs that define the value. Notice in the \verb+FullAdder+ definition, the widths for \verb+a_xor_b, a_and_b, b_and_cin,+ and \verb+a_and_cin+ are never specified anywhere. However, based on how the input is computed, Chisel will correctly infer each of these values are one bit wide since each of their inputs are the results of bitwise operations applied to one bit operands. - -A quick inspection of the generated Verilog shows these values are indeed one bit wide: - -\begin{bash} -module FullAdder( - input io_a, - input io_b, - input io_cin, - output io_sum, - output io_cout); - - wire T0; - wire a_and_cin; - wire T1; - wire b_and_cin; - wire a_and_b; - wire T2; - wire a_xor_b; - - assign io_cout = T0; - assign T0 = T1 | a_and_cin; - assign a_and_cin = io_a & io_cin; - assign T1 = a_and_b | b_and_cin; - assign b_and_cin = io_b & io_cin; - assign a_and_b = io_a & io_b; - assign io_sum = T2; - assign T2 = a_xor_b ^ io_cin; - assign a_xor_b = io_a ^ io_b; -endmodule -\end{bash} - -Suppose we change the widths of the \verb+FullAdder+ to be 2 bits wide each instead such that the Chisel source now looks like: - -\begin{scala} -class FullAdder extends Module { - val io = new Bundle { - val a = UInt(INPUT, 2) - val b = UInt(INPUT, 2) - val cin = UInt(INPUT, 2) - val sum = UInt(OUTPUT, 2) - val cout = UInt(OUTPUT, 2) - } - // Generate the sum - val a_xor_b = io.a ^ io.b - io.sum := a_xor_b ^ io.cin - // Generate the carry - val a_and_b = io.a & io.b - val b_and_cin = io.b & io.cin - val a_and_cin = io.a & io.cin - io.cout := a_and_b | b_and_cin | a_and_cin -} -\end{scala} - -As a result, the Chisel compiler should infer each of the intermediate values \verb+a_xor_b, a_and_b, b_and_cin,+ and \verb+a_and_cin+ are two bits wide. An inspection of the Verilog code correctly shows that Chisel inferred each of the intermediate wires in the calculation to be 2 bits wide. - -\begin{bash} -module FullAdder( - input [1:0] io_a, - input [1:0] io_b, - input [1:0] io_cin, - output[1:0] io_sum, - output[1:0] io_cout); - - wire[1:0] T0; - wire[1:0] a_and_cin; - wire[1:0] T1; - wire[1:0] b_and_cin; - wire[1:0] a_and_b; - wire[1:0] T2; - wire[1:0] a_xor_b; - - assign io_cout = T0; - assign T0 = T1 | a_and_cin; - assign a_and_cin = io_a & io_cin; - assign T1 = a_and_b | b_and_cin; - assign b_and_cin = io_b & io_cin; - assign a_and_b = io_a & io_b; - assign io_sum = T2; - assign T2 = a_xor_b ^ io_cin; - assign a_xor_b = io_a ^ io_b; -endmodule -\end{bash} - -\section{Using Registers} - -Unlike Verilog, specifying a register in Chisel tells the compiler to actually generate a positive edge triggered register. In this section we explore how to instantiate registers in Chisel by constructing a shift register. - -In Chisel, when you instantiate a register there are several ways to specify the connection of the input to a register. As shown in the GCD example, you can "declare" the register and assign what it's input is connected to in a \verb+when...+ block or you can simply pass the value that the register is clocking as a parameter to the register. - -If you choose to pass a next value to the register on construction using the \verb+next+ named parameter, it will clock the new value every cycle unconditionally: - -\begin{scala} -// Clock the new register value on every cycle -val y = io.x -val z = Reg(next = y) -\end{scala} - -If we only want to update if certain conditions are met we use a \verb+when+ block to indicate that the registers are only updated when the condition is satisfied: - -\begin{scala} -// Clock the new register value when the condition a > b -val x = Reg(UInt()) -when (a > b) { x := y } -.elsewhen ( b > a) {x := z} -.otherwise { x := w} -\end{scala} - -It is important to note that when using the conditional method, the values getting assigned to the input of the register match the type and bitwidth of the register you declared. In the unconditional register assignment, you do not need to do this as Chisel will infer the type and width from the type and width of the input value. - -The following sections show how these can be used to construct a shift register. - -\subsection{Unconditional Register Update} - -Suppose we want to construct a basic 4 bit shift register that takes a serial input \verb+in+ and generates a serial output \verb+out+. For this first example we won't worry about a parallel load signal and will assume the shift register is always enabled. We also will forget about the register reset signal. - -If we instantiate and connect each of these 4 registers explicitly, our Chisel code will look something like: - -\begin{scala} -class ShiftRegister extends Module { - val io = new Bundle { - val in = UInt(INPUT, 1) - val out = UInt(OUTPUT, 1) - } - val r0 = Reg(next = io.in) - val r1 = Reg(next = r0) - val r2 = Reg(next = r1) - val r3 = Reg(next = r2) - io.out := r3 -} -\end{scala} - -If we take a look at the generated Verilog, we will see that Chisel did indeed map our design to a shift register. One thing to notice is that the clock signal and reset signals are implicitly attached to our design. - -\begin{bash} -module ShiftRegister(input clk, input reset, - input io_in, - output io_out); - - reg[0:0] r3; - reg[0:0] r2; - reg[0:0] r1; - reg[0:0] r0; - - assign io_out = r3; - always @(posedge clk) begin - r3 <= r2; - r2 <= r1; - r1 <= r0; - r0 <= io_in; - end -endmodule -\end{bash} - -\subsection{Conditional Register Update} - -As mentioned earlier, Chisel allows you to conditionally update a register (use an enable signal) using the \verb+when+, \verb+.elsewhen+, \verb+.otherwise+ block. Suppose we add an enable signal to our shift register, that allows us to control whether data is shift in and out on a given cycle depending on an \verb+enable+ input signal. The new shift register now looks like: - -\begin{scala} -class ShiftRegister extends Module { - val io = new Bundle { - val in = UInt(INPUT, 1) - val enable = Bool(INPUT) - val out = UInt(OUTPUT, 1) - } - - val r0 = Reg(UInt()) - val r1 = Reg(UInt()) - val r2 = Reg(UInt()) - val r3 = Reg(UInt()) - - when (io.enable) { - r0 := io.in - r1 := r0 - r2 := r1 - r3 := r2 - } - io.out := r3 -} -\end{scala} - -Notice that it is not necessary to specify an \verb+.otherwise+ condition as Chisel will correctly infer that the old register value should be preserved otherwise. - -\subsection{Register Reset} - -Chisel allows you to specify a synchronous reset to a certain value by specifying an additional parameter when you first declare them. In our shift register, let's add a reset capability that resets all the register values to zero synchronously. To do this we need to provide our register declarations a little more information using the \verb+init+ parameter with what value we want on a synchronous reset: - -\begin{scala} -class ShiftRegister extends Module { - val io = new Bundle { - val in = UInt(INPUT, 1) - val enable = Bool(INPUT) - val out = UInt(OUTPUT, 1) - } - // Register reset to zero - val r0 = Reg(init = UInt(0, width = 1)) - val r1 = Reg(init = UInt(0, width = 1)) - val r2 = Reg(init = UInt(0, width = 1)) - val r3 = Reg(init = UInt(0, width = 1)) - when (io.enable) { - r0 := io.in - r1 := r0 - r2 := r1 - r3 := r2 - } - io.out := r3 -} -\end{scala} - -Notice that reset value can actually be any value, simply replace the zeros and width to appropriate values. - -Chisel also has an implict global \verb+reset+ signal that you can use in a \verb+when+ block. The reset signal is conveniently called \verb+reset+ and does not have to be declared. The shift register using this implict global reset now looks like: - -\begin{scala} -class ShiftRegister extends Module { - val io = new Bundle { - val in = UInt(INPUT, 1) - val enable = Bool(INPUT) - val out = UInt(OUTPUT, 1) - } - val r0 = Reg(UInt()) - val r1 = Reg(UInt()) - val r2 = Reg(UInt()) - val r3 = Reg(UInt()) - when(reset) { - r0 := UInt(0) - r1 := UInt(0) - r2 := UInt(0) - r3 := UInt(0) - } .elsewhen(io.enable) { - r0 := io.in - r1 := r0 - r2 := r1 - r3 := r2 - } - io.out := r3 -} -\end{scala} - -This will generate slightly different looking Verilog source code but will still function the same as the previous implementation of the shift register with reset. - -\subsection{\problem{Sequential Circuit}} - -The following exercises can be found in your -\verb+$TUT_DIR/problems/+ folder. You will find that some parts of -the tutorial files have been completed for you and the section that -you need to will need to complete is indicated in the file. The -solutions to each of these exercises can be found in the -\verb+$TUT_DIR/solutions/+ folder. - -The first tutorial problem is to write write a sequential circuit that sums \verb+in+ values. -You can find the template in \verb+$TUT_DIR/problems/Accumulator.scala+ including a stubbed out version of the circuit: -\begin{scala} -class Accumulator extends Module { - val io = new Bundle { - val in = UInt(INPUT, 1) - val out = UInt(OUTPUT, 8) - } - - // flush this out ... - - io.out := UInt(0) -} -\end{scala} - -\noindent -and a complete tester that confirms that you have successfully designed the circuit. Run - -\begin{bash} -make Accumulator.out -\end{bash} - -\noindent -until your circuit passes the tests. - - -%\subsection{Creating a Two Input Multiplexor} -% -% -% -%\subsection{Creating a Simple FIFO} -% -% -% diff --git a/doc/getting-started/basics.tex b/doc/getting-started/basics.tex deleted file mode 100644 index 7c129bec..00000000 --- a/doc/getting-started/basics.tex +++ /dev/null @@ -1,58 +0,0 @@ -\documentclass[twocolumn, 10pt]{article} -\setlength\textwidth{6.875in} -\setlength\textheight{8.875in} -% set both margins to 2.5 pc -\setlength{\oddsidemargin}{-0.1875in}% 1 - (8.5 - 6.875)/2 -\setlength{\evensidemargin}{-0.1875in} -\setlength{\marginparwidth}{0pc} -\setlength{\marginparsep}{0pc}% -\setlength{\topmargin}{0in} \setlength{\headheight}{0pt} -\setlength{\headsep}{0pt} -\setlength{\footskip}{37pt}% -%\setlength{\columnsep}{0.3125in} -%\setlength{\columnwidth}{3.28125in}% (6.875 - 0.3125)/2 = 3.28125in -\setlength{\parindent}{1pc} -\newcommand{\myMargin}{1.00in} -\usepackage[top=\myMargin, left=\myMargin, right=\myMargin, bottom=\myMargin, nohead]{geometry} -\usepackage{epsfig,graphicx} -\usepackage{palatino} -\usepackage{fancybox} -\usepackage{hyperref} -\usepackage[procnames]{listings} - -\input{../style/scala.tex} - -\lstset{basicstyle={\footnotesize\ttfamily}} - -\newenvironment{commentary} -{ \vspace{-0.1in} - \begin{quotation} - \noindent - \small \em - \rule{\linewidth}{1pt}\\ -} -{ - \end{quotation} -} - -\title{Getting Started: Tutorial 01 - The Basics} -\author{Jonathan Bachrach, Vincent Lee \\ -EECS Department, UC Berkeley\\ -{\tt \{jrb\}@eecs.berkeley.edu} -} -\date{\today} - -\newenvironment{example}{\VerbatimEnvironment\begin{footnotesize}\begin{Verbatim}}{\end{Verbatim}\end{footnotesize}} -\newcommand{\kode}[1]{\begin{footnotesize}{\tt #1}\end{footnotesize}} - -\def\code#1{{\tt #1}} - -\def\note#1{\noindent{\bf [Note: #1]}} -%\def\note#1{} - -\begin{document} -\maketitle{} - -\input{basics-guts} - -\end{document} diff --git a/doc/getting-started/bits-guts.tex b/doc/getting-started/bits-guts.tex deleted file mode 100644 index 1bfb26d9..00000000 --- a/doc/getting-started/bits-guts.tex +++ /dev/null @@ -1,320 +0,0 @@ -\section{Chisel Assignments and Reassignments} - -When you first define a value in Chisel, we use the \verb+=+ operator in order to tell Chisel to allocate the value for the first time. On every subsequent reassignment to the value, we must use a \verb+:=+ when reassigning the value. - -Since we are constructing a digital circuit, the notion of reassignment does not make much sense since connections between circuit nodes only need to be specified once. However, there are some cases when we will need to perform reassignment to a value in Chisel since it is compiled sequentially unlike Verilog. Thus it may be necessary to perform reassignment when a value or connection is not known until later in the Chisel source. - -A simple example of when reassignment is necessary is in the construction of the top level I/O for your module; the values of the output are not immediately known at the time of declaration. - -Consider the simple \verb+FullAdder+ circuit from previous tutorial that determines the sum \verb+sum+ and carry out \verb+cout+ given two values \verb+a+ and \verb+b+, and a carry in \verb+cin+. - -\begin{scala} -class FullAdder extends Module { - val io = new Bundle { - // first definition of io values so use = - val a = UInt(INPUT, 1) - val b = UInt(INPUT, 1) - val cin = UInt(INPUT, 1) - val sum = UInt(OUTPUT, 1) - val cout = UInt(OUTPUT, 1) - } - // Generate the sum - val a_xor_b = io.a ^ io.b - // Reassignment to io.sum so use := - io.sum := a_xor_b ^ io.cin - // Generate the carry - val a_and_b = io.a & io.b - val b_and_cin = io.b & io.cin - val a_and_cin = io.a & io.cin - // reassignment to io.cout so use := - io.cout := a_and_b | b_and_cin | a_and_cin -} -\end{scala} - -In this example we make sure to use the \verb+:=+ reassignment for the \verb+io.sum+ and \verb+io.cout+ output values because we only know what they're values are later in the code and not at the time of construction of the \verb+io+ Bundle. All other values in this example use the \verb+=+ assignment operator since they need to be created. - -In general, the rule of thumb is to use the reassignment operator \verb+:=+ if the value already has been assigned by the \verb+=+ operator, otherwise the \verb+=+ operator should be used. Note that if you do not use the \verb+=+ or \verb+:=+ operators correctly you will get an error when you try and compile your design. - -\section{The Chisel UInt Class} - -In the previous examples we have been using the UInt type which is an unsigned integer as the type for all of our values. For many of the basic computations in Chisel the UInt class is sufficient.\footnote{The UInt class definition for Chisel can be found in the /chisel/src/main folder in the compiler source repository, not the chisel-tutorial. You can obtain the Chisel source by cloning https://github.com/ucb-bar/chisel.git} The following example shows some of the commonly used UInt operations in the context of a simple \verb+ALU+\footnote{We ignore overflow and underflow in this example.}: - -\begin{scala} -class BasicALU extends Module { - val io = new Bundle { - val a = UInt(INPUT, 4) - val b = UInt(INPUT, 4) - val opcode = UInt(INPUT, 4) - val output = UInt(OUTPUT, 4) - } - io.output := UInt(0) - when (io.opcode === UInt(0)) { - io.output := io.a // pass A - } .elsewhen (io.opcode === UInt(1)) { - io.output := io.b // pass B - } .elsewhen (io.opcode === UInt(2)) { - io.output := io.a + UInt(1) // inc A by 1 - } .elsewhen (io.opcode === UInt(3)) { - io.output := io.a - UInt(1) // inc B by 1 - } .elsewhen (io.opcode === UInt(4)) { - io.output := io.a + UInt(4) // inc A by 4 - } .elsewhen (io.opcode === UInt(5)) { - io.output := io.a - UInt(4) // dec A by 4 - } .elsewhen (io.opcode === UInt(6)) { - io.output := io.a + io.b // add A and B - } .elsewhen (io.opcode === UInt(7)) { - io.output := io.a - io.b // sub B from A - } .elsewhen (io.opcode === UInt(8)) { - io.output := (io.a < io.b) // set on A < B - } .otherwise { - io.output := (io.a === io.b) // set on A == B - } -} -\end{scala} - -You will notice that there are multiple reassignments to \verb+io.output+ inside a \verb+when+ block which indicates that the value of \verb+io.output+ can take many different values depending on the \verb+io.opcode+ in this example. Also notice that in order to specify constants to add to our operands, we must also specify them as a UInt type as UInt operations on different type operands is not allowed. - -\begin{scala} -// Specify that 1 is a UInt type -io.output := io.a + UInt(1) -\end{scala} - -A list of commonly used UInt operations is given in the table below: - -\begin{center} -\begin{tabular}{| l | l | l | } -\hline -{\bf Operand} & {\bf Operation} & {\bf Output Type} \\ \hline -+ & Add & UInt \\ \hline -- & Subtract & UInt \\ \hline -$\ast$ & Multiply & UInt \\ \hline -/ & UInt Divide & UInt \\ \hline -% & Modulo & UInt \\ \hline -\~\ & Bitwise Negation & UInt \\ \hline -\^\ & Bitwise XOR & UInt\\ \hline -\& & Bitwise AND & UInt \\ \hline - | & Bitwise OR & Bool \\ \hline -=== & Equal & Bool \\ \hline -!= & Not Equal & Bool \\ \hline -> & Greater & Bool \\ \hline -< & Less & Bool \\ \hline ->= & Greater or Equal & Bool \\ \hline -<= & Less or Equal & Bool \\ \hline -\end{tabular} -\end{center} - -% Notice that the comparisons for the UInt type give you a Bool type back. In order to be able to assign the output of a comparison to a UInt type, we will need to cast the Bool to a UInt before the assignment. This is shown in the \verb+BasicALU+ example in the \verb+.otherwise+ block: -% -% \begin{scala} -% io.output := (io.a === io.b).toUInt() // set on A == B -% \end{scala} -% -% If we you do not cast the resulting Bool to a UInt the Chisel compiler will return an error. - -\subsection{Bit Extraction} - -The UInt class allows you to extract bits based on their index of their representation. Given an \verb+n+ bit wide value \verb+value+ we can extract the bits \verb+x+ through \verb+y+ (n > x > y >= 0) by simply doing the following: - -\begin{scala} -// extracts the x through y bits of value -val x_to_y = value(x, y) -\end{scala} - -Note that the higher index is specified first in the argument list when extraction the bits. Also notice that the bits in the UInt are zero indexed so the highest bit that can be extracted from an \verb+n+ bit wide value is \verb+n-1+. - -If you just want to extract a single bit from the value, say bit \verb+x+ we simply need to specify a single index instead as follows: -\begin{scala} -// extract the x-th bit from value -val x_of_value = value(x) -\end{scala} - -A more concrete example of bit extraction in action is shown below. In this example, based on the value of the offset, we would like to select a byte from a word which is a common operation when loading a byte from word addressed memories: - -\begin{scala} -class ByteSelector extends Module { - val io = new Bundle { - val in = UInt(INPUT, 32) - val offset = UInt(INPUT, 2) - val out = UInt(OUTPUT, 8) - } - io.out := UInt(0, width = 8) - when (io.offset === UInt(0)) { - io.out := io.in(7,0) // pull out lowest byte - } .elsewhen (io.offset === UInt(1)) { - io.out := io.in(15,8) // pull out second byte - } .elsewhen (io.offset === UInt(2)) { - io.out := io.in(23,16) // pull out third byte - } .otherwise { - io.out := io.in(31,24) // pull out highest byte - } -} -\end{scala} - -\subsection{Bit Concatenation} - -Chisel also allows you to easily concatenate bits together using \verb+Cat+. Suppose you have a data bus that you would like to drive with two seperate words \verb+A+ and \verb+B+. In order to concatenate these two values together we simply say: - -\begin{scala} -val A = UInt(width = 32) -val B = UInt(width = 32) -val bus = Cat(A, B) // concatenate A and B -\end{scala} - -Again, the first argument to \verb+Cat+ will be placed in the high part while the second argument gets the low part of \verb+bus+. Thus for this example bits 0 to 31 of \verb+bus+ correspond to \verb+B+, while bits 32 to 63 correspond to \verb+A+. - -\subsection{\problem{LFSR16}} - -In this assignment, write the \verb+LFSR16+ circuit as shown below: - -\begin{center} -\includegraphics[width=0.9\columnwidth]{../bootcamp/figs/LFSR16.pdf} -\end{center} - -\noindent -by filling in the following module: - -\begin{scala} -class LFSR16 extends Module { - val io = new Bundle { - val inc = Bool(INPUT) - val out = UInt(OUTPUT, 16) - } - // ... - io.out := UInt(0) -} -\end{scala} - -\noindent -found in \verb+$TUT_DIR/problems/LFSR16.scala+. -Make sure to define and initialize an internal register to one and -update it when \verb+inc+ is asserted. -Use bit concatentation and bit extraction -in conjunction with the xor operator \verb+^+. Run - -\begin{bash} -make LFSR16.out -\end{bash} - -\noindent -until your circuit passes the tests. - -\subsection{UInt Operation Bit Inference} - -Note that for some operations such as addition and multiplication, that number of resulting bits of the computation can be greater than the number of bits for the operands. - -Consider the following example where we multiply two 16 bit numbers \verb+A+ and \verb+B+ together. Note that the product of two 16 bit numbers is at worst 32 bits wide. - -\begin{scala} -class HiLoMultiplier() extends Module { - val io = new Bundle { - val A = UInt(INPUT, 16) - val B = UInt(INPUT, 16) - val Hi = UInt(OUTPUT, 16) - val Lo = UInt(OUTPUT, 16) - } - val mult = io.A * io.B - io.Lo := mult(15, 0) - io.Hi := mult(31, 16) -} - -\end{scala} - -Notice that we never specify the width of the value \verb+mult+ anywhere in the Chisel source. Normally if we performed this in Verilog we would have had to specify the width beforehand. But a look at the generated Verilog for this example shows that Chisel correctly inferred the \verb+mult+ value to be 32 bits wide: - -\begin{scala} -module HiLoMultiplier( - input [15:0] io_A, - input [15:0] io_B, - output[15:0] io_Hi, - output[15:0] io_Lo); - - wire[15:0] T0; - wire[31:0] mult; // Chisel infers this to be 32 bits - wire[15:0] T1; - - assign io_Lo = T0; - assign T0 = mult[4'hf:1'h0]; - assign mult = io_A * io_B; - assign io_Hi = T1; - assign T1 = mult[5'h1f:5'h10]; -endmodule - -\end{scala} - -As we get to more complicate designs, it will become more clear that bit inference in Chisel is a very powerful feature that makes constructing hardware more efficient. A list of common bit inferences is shown below for commonly used operations: - -\begin{center} -\begin{tabular}{| l | l | l | } -\hline -{\bf Operation} & {\bf Result Bit Width} \\ \hline -\verb!Z = X + Y! & max(Width(X), Width(Y)) \\ \hline -\verb+Z = X - Y+ & max(Width(X), Width(Y)) \\ \hline -\verb+Z = X & Y+ & max(Width(X), Width(Y)) \\ \hline -\verb+Z = X | Y+ & max(Width(X), Width(Y)) \\ \hline -\verb+Z = X ^ Y+ & max(Width(X), Width(Y)) \\ \hline -\verb+Z = ~X+ & Width(X) \\ \hline -\verb+Z = Mux(C, X, Y)+ & max(Width(X), Width (Y)) \\ \hline -\verb+Z = X * Y+ & Width(X) + Width(Y) \\ \hline -\verb+Z = X << n+ & Width(X) + n \\ \hline -\verb+Z = X >> n+ & Width(X) - n \\ \hline -\verb+Z = Cat(X, Y)+ & Width(X) + Width(Y) \\ \hline -\verb+Z = Fill(n, x)+ & Width(X) + n \\ \hline -\end{tabular} -\end{center} - -\section{The Chisel Bool Class} - -The Bool class in Chisel is used to represent the result of logical expressions and takes either the values \verb+true+ or \verb+false+. These can be used in conditional statements such as \verb+when+ blocks. - -\begin{scala} -val change = io.a === io.b // change gets Bool type -when (change) { // exec if change is true - ... -} .otherwise { - ... -} -\end{scala} - -You can instantiate a Bool value like this: - -\begin{scala} -val true_value = Bool(true) -val false_value = Bool(false) -\end{scala} - -% As shown in the \verb+BasicALU+ example, in order to use a Bool value as a UInt type and assign it to an output, a cast to UInt is required. - -\section{Casting Between Types} - -When assigning values, it is required that you assign a value of the same type. For instance, if you try to assign a Bool type to an output value that is expecting a UInt type, you will get an error. - -\begin{scala} - ... - val io = new Bundle { - val in = UInt(INPUT, 2) - val out = UInt(OUTPUT, 1) - } - // attempted Bool assignment to UInt - io.out := (in === UInt(0)) - ... -\end{scala} - -The correct way to perform the intended operation is to cast the resulting Bool type to a UInt using the \verb+toUInt()+ cast. The correct Chisel code will look like: - -\begin{scala} - ... - val io = new Bundle { - val in = UInt(INPUT, 2) - val out = UInt(OUTPUT, 1) - } - io.out := (in === UInt(0)).toUInt() // UInt cast - ... -\end{scala} - -Some of the common casts that you may use are: - -\begin{itemize} -\item toUInt() -\item toSInt() -\item toBool() -\end{itemize} diff --git a/doc/getting-started/bits.tex b/doc/getting-started/bits.tex deleted file mode 100644 index f6e04ffd..00000000 --- a/doc/getting-started/bits.tex +++ /dev/null @@ -1,60 +0,0 @@ -\documentclass[twocolumn, 10pt]{article} -\setlength\textwidth{6.875in} -\setlength\textheight{8.875in} -% set both margins to 2.5 pc -\setlength{\oddsidemargin}{-0.1875in}% 1 - (8.5 - 6.875)/2 -\setlength{\evensidemargin}{-0.1875in} -\setlength{\marginparwidth}{0pc} -\setlength{\marginparsep}{0pc}% -\setlength{\topmargin}{0in} \setlength{\headheight}{0pt} -\setlength{\headsep}{0pt} -\setlength{\footskip}{37pt}% -%\setlength{\columnsep}{0.3125in} -%\setlength{\columnwidth}{3.28125in}% (6.875 - 0.3125)/2 = 3.28125in -\setlength{\parindent}{1pc} -\newcommand{\myMargin}{1.00in} -\usepackage[top=\myMargin, left=\myMargin, right=\myMargin, bottom=\myMargin, nohead]{geometry} -\usepackage{epsfig,graphicx} -\usepackage{palatino} -\usepackage{fancybox} -\usepackage{hyperref} -\usepackage[procnames]{listings} - -\input{../style/scala.tex} - -\lstset{basicstyle={\footnotesize\ttfamily}} - -\newenvironment{commentary} -{ \vspace{-0.1in} - \begin{quotation} - \noindent - \small \em - \rule{\linewidth}{1pt}\\ -} -{ - \end{quotation} -} - -\title{Getting Started - Tutorial 02: Basic Types and Operations} -\author{Jonathan Bachrach, Vincent Lee \\ -EECS Department, UC Berkeley\\ -{\tt \{jrb\}@eecs.berkeley.edu} -} -\date{\today} - -\newenvironment{example}{\VerbatimEnvironment\begin{footnotesize}\begin{Verbatim}}{\end{Verbatim}\end{footnotesize}} -\newcommand{\kode}[1]{\begin{footnotesize}{\tt #1}\end{footnotesize}} - -\def\code#1{{\tt #1}} - -\def\note#1{\noindent{\bf [Note: #1]}} -%\def\note#1{} - -\begin{document} -\maketitle{} - -% Bits has been deprecated and therefore section has been removed from this document. Older commits may have Bits section somewhere. - -\input{bits-guts} - -\end{document} diff --git a/doc/getting-started/debugging-guts.tex b/doc/getting-started/debugging-guts.tex deleted file mode 100644 index a22f30fe..00000000 --- a/doc/getting-started/debugging-guts.tex +++ /dev/null @@ -1,82 +0,0 @@ -\section{Debugging Designs} - -Chisel provides a number of mechanisms for debugging your designs. -A designer can format and print out strings to display signals over time. -Runtime assertions can be declared with the \verb+assert+ construct. -Circuits can be displayed with the dot backend. -Complete signal values can be dumped over time in VCD format. -Finally, circuits can be interacted with the debug API. - -\section{Printf and Sprintf} - -Chisel provides the ability to format and print strings for debugging -purposes. The \code{printf} and \code{sprintf} construct are similar to their -C namesakes: they take a format string and a variable number of arguments, -then print or return a string, respectively. During simulation, \code{printf} -prints the formatted string to the console on rising clock edges. -\code{sprintf}, on the other hand, returns the formatted string as a bit -vector. - -Supported format specifiers are \code{\%b} (binary number), \code{\%d} -(decimal number), \code{\%x} (hexadecimal number), and \code{\%s} (string -consisting of a sequence of 8-bit extended ASCII characters). (\code{\%\%} -specifies a literal \code{\%}.) Unlike in C, there are no width modifiers: the -bit width of the corresponding argument determines the width in the string -representation. - -The following example prints the line \code{"0x4142 16706 AB"} on cycles when -\code{c} is true: - -\begin{scala} -val x = Bits(0x4142) -val s1 = sprintf("%x %s", x, x); -when (c) { printf("%d %s\n", x, s1); } -\end{scala} - -\section{Assert} - -Runtime assertions are provided by the \code{assert} construct. During -simulation, if an assertion's argument is false on a rising clock edge, -an error is printed and simulation terminates. For example, the following -will terminate simulation after ten clock cycles: - -\begin{scala} -val x = Reg(init = UInt(0, 4)) -x := x + UInt(1) -assert(x < UInt(10)) -\end{scala} - -\section{Circuit Graph Visualization} - -In Chisel, circuits are constructed using a textual program. -Sometimes it is useful to see the constructed circuit graph. -Users can produce at dot graph file viewable by vizgraph using the dot backend. - -\todo{finish examples below} - -\begin{scala} -chiselMain ... --backend dot ... -\end{scala} - -\begin{bash} -vizgraph -pdf test.dot -\end{bash} - -\section{VCD Dumps} - -One powerfully way of debugging is by saved the values of all signals and state over time. -Chisel supports this by running circuits under test while -dumping \verb+VCD+ (Value Change Dump) files using the \verb+--vcd+ option: - -\begin{bash} -chiselMainTest ... --vcd ... -\end{bash} - -These VCD files can then viewed using either commercial waveform viewers like \verb+VCS+ or open source ones like \verb+gtkwave+. - -\todo{picture of waveform} - -% \section{Debug API} -% -% For those that want lower level control over their designs, -% they can drive their circuits through a low level debug API. diff --git a/doc/getting-started/figs/4_Bit_Adder.jpg b/doc/getting-started/figs/4_Bit_Adder.jpg deleted file mode 100644 index 547960ef..00000000 Binary files a/doc/getting-started/figs/4_Bit_Adder.jpg and /dev/null differ diff --git a/doc/getting-started/figs/Full_Adder.jpg b/doc/getting-started/figs/Full_Adder.jpg deleted file mode 100644 index 146b565c..00000000 Binary files a/doc/getting-started/figs/Full_Adder.jpg and /dev/null differ diff --git a/doc/getting-started/getting-started.tex b/doc/getting-started/getting-started.tex deleted file mode 100644 index 18cb457d..00000000 --- a/doc/getting-started/getting-started.tex +++ /dev/null @@ -1,85 +0,0 @@ -\documentclass[twocolumn, 10pt]{book} -\setlength\textwidth{6.875in} -\setlength\textheight{8.5in} -% set both margins to 2.5 pc -\setlength{\oddsidemargin}{-0.1875in}% 1 - (8.5 - 6.875)/2 -\setlength{\evensidemargin}{-0.1875in} -\setlength{\marginparwidth}{0pc} -\setlength{\marginparsep}{0pc}% -\setlength{\footskip}{37pt}% -\setlength{\columnsep}{0.25in} -%\setlength{\columnwidth}{3.28125in}% (6.875 - 0.3125)/2 = 3.28125in -\setlength{\parindent}{1pc} -\newcommand{\myMargin}{1.00in} -\setlength{\topmargin}{0pt} -\setlength{\headheight}{22pt} -\setlength{\headsep}{20pt} -\usepackage[top=\myMargin, left=\myMargin, right=\myMargin, bottom=\myMargin]{geometry} -\usepackage{epsfig,graphicx} -\usepackage{palatino} -\usepackage{fancybox} -\usepackage{hyperref} -\usepackage[svgnames]{xcolor} -\usepackage[procnames]{listings} - -\input{../style/scala.tex} - -\lstset{basicstyle={\footnotesize\ttfamily}} - -\newenvironment{commentary} -{ \vspace{-0.1in} - \begin{quotation} - \noindent - \small \em - \rule{\linewidth}{1pt}\\ -} -{ - \end{quotation} -} - -\title{Getting Started with Chisel} -\author{Jonathan Bachrach, Vincent Lee \\ -EECS Department, UC Berkeley\\ -{\tt \{jrb\}@eecs.berkeley.edu} -} -\date{\today} - -\newenvironment{example}{\VerbatimEnvironment\begin{footnotesize}\begin{Verbatim}}{\end{Verbatim}\end{footnotesize}} -\newcommand{\kode}[1]{\begin{footnotesize}{\tt #1}\end{footnotesize}} - -\definecolor{RED}{rgb}{1,0,0} -\def\red#1{{\color{red}#1}} -\def\problem#1{{\red{#1 Problem}}} -\def\code#1{{\tt #1}} - -\def\note#1{\noindent{\bf [Note: #1]}} -%\def\note#1{} - -\begin{document} -\maketitle{} - -\chapter{Chisel Installation} -\input{installation-guts} - -\chapter{The Basics} -\input{basics-guts} - -\chapter{Basic Types and Operations} -\input{bits-guts} - -\chapter{Instantiating Modules} -\input{modules-guts} - -\chapter{Writing Scala Testbenches} -\input{testing-guts} - -\chapter{Creating Your Own Project} -\input{projects-guts} - -\chapter{Conditional Assignments and Memories} -\input{state-guts} - -\chapter{Scripting Hardware Generation} -\input{scripting-guts} - -\end{document} diff --git a/doc/getting-started/installation-guts.tex b/doc/getting-started/installation-guts.tex deleted file mode 100644 index bc96261a..00000000 --- a/doc/getting-started/installation-guts.tex +++ /dev/null @@ -1,101 +0,0 @@ -\section{Introduction} - -This chapter is an installation guide for {\em Chisel} (Constructing -Hardware In a Scala Embedded Language) and is intended to prepare your system for subsequent tutorials. Chisel is a hardware -construction language embedded in the high-level programming language -Scala. - -\subsection{Development Tool Installation} - -If you are running Mac or a variant of Linux, you will need to install the appropriate tools for your OS, which are described in the following sections: - -\subsubsection{MacOSX} - -\begin{enumerate} -\item Install XCODE, including console tools. -\end{enumerate} - -\subsubsection{Linux} - -Install the following packages: - -\begin{enumerate} -\item \verb|g++-4.8| -\item \verb+openjdk-7-jre+ -\end{enumerate} - -\noindent -using - -\begin{bash} -sudo apt-get install -\end{bash} - -\section{Setting Up the Tutorial} - -In subsequent tutorials, you will be using the files distributed in the chisel-tutorial repository. To obtain these tutorials files, \verb+cd+ to the directory = \verb+$DIR+ where you want to place the Chisel tutorial and type: - -\begin{bash} -cd $DIR -git clone https://github.com/ucb-bar/chisel-tutorial.git -\end{bash} - -\noindent -Your copy of the Chisel Tutorial repository will then be in \verb+$DIR/chisel-tutorial+. Define this as a variable in your bash environment named \verb+$TUT_DIR+. - -This is the Chisel tutorial directory structure you should see, which is explained more in the next tutorial: - -\begin{bash} -chisel-tutorial/ - Makefile - examples/ - Makefile - build.sbt - Accumulator.scala ... - problems/ - Makefile - build.sbt - Counter.scala ... - solutions/ - Makefile - build.sbt - Counter.scala ... -\end{bash} - -\noindent - -The following tutorials will explain features of Chisel by presenting source code examples. The repository is split into examples, problems, and solutions, where the problems have some piece of the design for you to fill out and where the examples and solutions are meant to be complete designs that should pass the given tests. In order to run either, you simply need to change directory into the appropriate subdirectory and type \verb+make+ of the particular lesson name. We will use the repository to first test out if your machine is set up to use Chisel. - -To test your Chisel distribution and verify that your system contains all the correct tools, run the following commands: - -\begin{bash} -cd $TUT_DIR/examples -make Parity.out -\end{bash} - -This will run a test build and will take a minute before it completes. If your system is set up correctly, you should see a messsage \verb+[success]+ followed by the total time of the run, and date and time of completion. If you see a success than your system has been set up correctly and you can continute to the next tutorial where we will explain more about the basics of Chisel. - -\section{The Tutorials} - -For these tutorials, we assume basic knowledge of digital circuits and blocks. -Tutorial 1 will guide you through a quick compilation of the emulator and Verilog generation, and explain some basic constructs such as register and combinational logic. -Tutorial 2 will explain the basics of Chisel. -Tutorial 3 will explain how to use basic primitive types and logical operations that are used in Chisel and how to use them in context of several examples. -Tutorial 4 will explain how to instantiate components and apply parametrization. -Tutorial 5 will explain how to use the Chisel test harness. -Tutorial 6 will explain how to set up your own Chisel project and how to build it. -Tutorial 7 will revisit conditional register updates and explain how to construct memories. -Finally, tutorial 8 will introduce how to use Scala constructs such as \verb+if...else+ and \verb+for+ loops. - -Along the way there are assignments highlighted with \red{red} titles. -These assignments are built around files in the tutorial problems directory. -In order to check successful completion of the entire set of getting started assignments run: -\begin{bash} -cd $TUT_DIR/problems -make getting-started -\end{bash} - -\noindent -until no error appears. - -The following set of tutorials were written using the build settings Scala version 2.11 and Chisel version 2.2. diff --git a/doc/getting-started/installation.tex b/doc/getting-started/installation.tex deleted file mode 100644 index 3b936401..00000000 --- a/doc/getting-started/installation.tex +++ /dev/null @@ -1,89 +0,0 @@ -\documentclass[twocolumn, 10pt]{article} -\setlength\textwidth{6.875in} -\setlength\textheight{8.875in} -% set both margins to 2.5 pc -\setlength{\oddsidemargin}{-0.1875in}% 1 - (8.5 - 6.875)/2 -\setlength{\evensidemargin}{-0.1875in} -\setlength{\marginparwidth}{0pc} -\setlength{\marginparsep}{0pc}% -\setlength{\topmargin}{0in} \setlength{\headheight}{0pt} -\setlength{\headsep}{0pt} -\setlength{\footskip}{37pt}% -%\setlength{\columnsep}{0.3125in} -%\setlength{\columnwidth}{3.28125in}% (6.875 - 0.3125)/2 = 3.28125in -\setlength{\parindent}{1pc} -\newcommand{\myMargin}{1.00in} -\usepackage[top=\myMargin, left=\myMargin, right=\myMargin, bottom=\myMargin, nohead]{geometry} -\usepackage{epsfig,graphicx} -\usepackage{palatino} -\usepackage{fancybox} -\usepackage{hyperref} -\usepackage[procnames]{listings} - -\input{../style/scala.tex} - -\lstset{basicstyle={\footnotesize\ttfamily}} - -\newenvironment{commentary} -{ \vspace{-0.1in} - \begin{quotation} - \noindent - \small \em - \rule{\linewidth}{1pt}\\ -} -{ - \end{quotation} -} - -% \newenvironment{kode}% -% {\footnotesize -% %\setlength{\parskip}{0pt} -% %\setlength{\topsep}{0pt} -% %\setlength{\partopsep}{0pt} -% \verbatim} -% {\endverbatim -% %\vspace*{-0.1in} -% } - -% \newenvironment{kode}% -% {\VerbatimEnvironment -% \footnotesize\begin{Sbox}\begin{minipage}{6in}\begin{Verbatim}}% -% {\end{Verbatim}\end{minipage}\end{Sbox} -% \setlength{\fboxsep}{8pt}\fbox{\TheSbox}} - -% \newenvironment{kode} -% {\begin{Sbox} -% \footnotesize -% \begin{minipage}{6in} -% %\setlength{\parskip}{0pt} -% %\setlength{\topsep}{0pt} -% %\setlength{\partopsep}{0pt} -% \verbatim} -% {\endverbatim -% \end{minipage} -% \end{Sbox} -% \fbox{\TheSbox} -% %\vspace*{-0.1in} -% } - -\title{Getting Started: Tutorial 0 - Chisel Installation} -\author{Jonathan Bachrach, Vincent Lee \\ -EECS Department, UC Berkeley\\ -{\tt \{jrb\}@eecs.berkeley.edu} -} -\date{\today} - -\newenvironment{example}{\VerbatimEnvironment\begin{footnotesize}\begin{Verbatim}}{\end{Verbatim}\end{footnotesize}} -\newcommand{\kode}[1]{\begin{footnotesize}{\tt #1}\end{footnotesize}} - -\def\code#1{{\tt #1}} - -\def\note#1{\noindent{\bf [Note: #1]}} -%\def\note#1{} - -\begin{document} -\maketitle{} - -\input{installation-guts} - -\end{document} diff --git a/doc/getting-started/makem.bash b/doc/getting-started/makem.bash deleted file mode 100755 index a81d3f9d..00000000 --- a/doc/getting-started/makem.bash +++ /dev/null @@ -1,6 +0,0 @@ -#/bin/bash -f - -for i in 00_installation 01_the_basics 02_bits_and_uint 03_module_instantiation 04_writing_chisel_testcases 05_creating_projects 06_registers_memories 07_scripting_construction -do - (cd $i; pdflatex $i.tex) -done diff --git a/doc/getting-started/modules-guts.tex b/doc/getting-started/modules-guts.tex deleted file mode 100644 index b9ee1b53..00000000 --- a/doc/getting-started/modules-guts.tex +++ /dev/null @@ -1,326 +0,0 @@ -\section{Module Instantiation} - -Like other hardware description languages, Chisel allows fairly straightforward module instantiation to enable modularity and hierarchy. In Chisel, instantiating a Module class is the equivalent to instantiating a module in Verilog. To do this, we simply use a call to \verb+Module+ with module created with the Scala \verb+new+ keyword in order to indicate that we are instantiation a new module. We want to make sure we assign this to a value so that we can reference its input and outputs which we also need to connect. - -For example, suppose we would like to construct a 4-bit adder using multiple copies of the \verb+FullAdder+ module. as shown in the Figure 1. The Chisel source code is shown below. - -\begin{figure}[ht!] -\centering -\includegraphics[width=80mm]{figs/4_Bit_Adder.jpg} -\caption{Block Diagram of 4-Bit Adder} -\label{overflow} -\end{figure} - -\begin{scala} -// A 4-bit adder with carry in and carry out -class Adder4 extends Module { - val io = new Bundle { - val A = UInt(INPUT, 4) - val B = UInt(INPUT, 4) - val Cin = UInt(INPUT, 1) - val Sum = UInt(OUTPUT, 4) - val Cout = UInt(OUTPUT, 1) - } - // Adder for bit 0 - val Adder0 = Module(new FullAdder()) - Adder0.io.a := io.A(0) - Adder0.io.b := io.B(0) - Adder0.io.cin := io.Cin - val s0 = Adder0.io.sum - // Adder for bit 1 - val Adder1 = Module(new FullAdder()) - Adder1.io.a := io.A(1) - Adder1.io.b := io.B(1) - Adder1.io.cin := Adder0.io.cout - val s1 = Cat(Adder1.io.sum, s0) - // Adder for bit 2 - val Adder2 = Module(new FullAdder()) - Adder2.io.a := io.A(2) - Adder2.io.b := io.B(2) - Adder2.io.cin := Adder1.io.cout - val s2 = Cat(Adder2.io.sum, s1) - // Adder for bit 3 - val Adder3 = Module(new FullAdder()) - Adder3.io.a := io.A(3) - Adder3.io.b := io.B(3) - Adder3.io.cin := Adder2.io.cout - io.Sum := Cat(Adder3.io.sum, s2).toUInt() - io.Cout := Adder3.io.cout -} -\end{scala} - -In this example, notice how when referencing each module I/O we must first reference the \verb+io+ that contains the ports for the I/Os. Again, note how all assignments to the module I/Os use a reassignment operator \verb+:=+. When instantiating modules, it is important to make sure that you connect all the input and output ports. If a port is not connected, the Chisel compiler may optimize away portions of your design that it find unecessary due to the unconnected ports and throw errors or warnings. - -\section{The Vec Class} - -The \verb+Vec+ class allows you to create an indexable vector in Chisel which can be filled with any expression that returns a chisel data type. The general syntax for a \verb+Vec+ declaration is given by: -\begin{scala} -val myVec = - Vec.fill( ) { } -\end{scala} -Where \verb++ corresponds to how long the vector is and \verb++ corresponds to what type of class the vector contains. - -For instance, if we wanted to instantiate a 10 entry vector of 5 bit UInt values, we would use: - -\begin{scala} -val ufix5_vec10 := Vec.fill(10) { UInt(width = 5) } -\end{scala} - -If we want to define a vector of registers... - -\begin{scala} -val reg_vec32 := Vec.fill(32){ Reg() } -\end{scala} - -In order to assign to a particular value of the \verb+Vec+, we simply assign the target value to the vector at a specified index. For instance, if we wanted to assign a UInt value of zero to the first register in the above example, the assignment would look like: - -\begin{scala} -reg_vec32(1) := UInt(0) -\end{scala} - -To access a particular element in the vector at some index, we specify the index of the vector. For example, to extract the 5th element of the register vector in the above example and assign it to some value \verb+reg5+, the assignment would look like: - -\begin{scala} -val reg5 = reg_vec(5) -\end{scala} - -The syntax for the \verb+Vec+ class is slightly different when instantiating a vector of modules. When instantiating a vector of modules the data type that is specified in the {} braces is slightly different than the usualy primitive types. To specify a vector of modules, we use the \verb+io+ bundle when specifying the type of the vector. For example, in order to specify a \verb+Vec+ with 16 modules , say \verb+FullAdder+s in this case, we would use the following declaration: - -\begin{scala} -val FullAdders = - Vec.fill(16){ Module(new FullAdder()).io } -\end{scala} - -Notice we use the keyword \verb+new+ in the vector definition before the module name \verb+FullAdder+. For how to actually access the \verb+io+ on the vector modules, refer to the next section. - -\subsection{\problem{Vec Shift Reg}} - -The next assignment is to construct a simple bit shift register. -The following is a the template from \verb+$TUT_DIR/problems/VecShiftRegisterSimple.scala+: - -\begin{scala} -class VecShiftRegisterSimple extends Module { - val io = new Bundle { - val in = UInt(INPUT, 8) - val out = UInt(OUTPUT, 8) - } - val delays = Vec.fill(4){ Reg(UInt(width = 8)) } - ... - io.out := UInt(0) -} -\end{scala} - -\noindent -where \verb+out+ is a four cycle delayed copy of values on \verb+in+. - -\section{Parametrization} - -In the previous Adder example, we explicitly instantiated four different copies of a \verb+FullAdder+ and wired up the ports. But suppose we want to generalize this structure to an n-bit adder. Like Verilog, Chisel allows you to pass parameters to specify certain aspects of your design. In order to do this, we add a parameter in the Module declaration to our Chisel definition. -For a carry ripple adder, we would like to parametrize the width to some integer value \verb+n+ as shown in the following example: - -\begin{scala} - -// A n-bit adder with carry in and carry out -class Adder(n: Int) extends Module { - val io = new Bundle { - val A = UInt(INPUT, n) - val B = UInt(INPUT, n) - val Cin = UInt(INPUT, 1) - val Sum = UInt(OUTPUT, n) - val Cout = UInt(OUTPUT, 1) - } - // create a vector of FullAdders - val FAs = Vec.fill(n){ Module(new FullAdder()).io } - - // define carry and sum wires - val carry = Vec.fill(n+1){ UInt(width = 1) } - val sum = Vec.fill(n){ Bool() } - - // first carry is the top level carry in - carry(0) := io.Cin - - // wire up the ports of the full adders - for(i <- 0 until n) { - FAs(i).a := io.A(i) - FAs(i).b := io.B(i) - FAs(i).cin := carry(i) - carry(i+1) := FAs(i).cout - sum(i) := FAs(i).sum.toBool() - } - io.Sum := sum.toBits().toUInt() - io.Cout := carry(n) -} - -\end{scala} - -Note that in this example, we keep track of the sum output in a \verb+Vec+ of \verb+Bool+s. This is because Chisel does not support bit assignment directly. Thus in order to get the n-bit wide \verb+sum+ in the above example, we use an n-bit wide \verb+Vec+ of \verb+Bool+s and then cast it to a UInt(). Note that it must first be casted to the \verb+Bits()+ type before casting it to \verb+UInt()+. - -You will notice that modules are instantiated in a Vec class which allows us to iterate through each module when assigning the ports connections to each \verb+FullAdder+. This is similar to the generate statement in Verilog. However, you will see in more advanced tutorials that Chisel can offer more powerful variations. - -Instantiating a parametrized module is very similar to instantiating an unparametrized module except that we must provide arguments for the parameter values. For instance, if we wanted to instantiate a 4-bit version of the \verb+Adder+ module we defined above, it would look like: - -\begin{scala} -val adder4 = Module(new Adder(4)) -\end{scala} - -We can also instantiate the \verb+Adder+ by explicitly specifying the value of it parameter \verb+n+ like the this: - -\begin{scala} -val adder4 = Module(new Adder(n = 4)) -\end{scala} - -Explicitly specifying the parameter is useful when you have a module with multiple parameters. Suppose you have a parametrized FIFO module with the following module definition: - -\begin{scala} -class FIFO(width: Int, depth: Int) extends Module {...} -\end{scala} - -You can explicitly specify the parameter values in any order: - -\begin{scala} -val fifo1 = Module(new FIFO(16, 32)) -val fifo2 = Module(new FIFO(width = 16, depth = 32)) -val fifo3 = Module(new FIFO(depth = 32, width = 16)) -\end{scala} - -All of the above definitions pass the same parameters to the FIFO module. Notice that when you explicitly assign the parameter values, they can occur in any order you want such as the definition for fifo3. - -\section{Advanced Parametrization} - -Although parameters can be passed explicitly through a Module's constructor, this technique does not scale when parameterizing large designs with many generic components. For a more detailed explanation of why a better parameterization method is needed, please see XXXX. In addition, XXXX explains heuristics for how to organize and parameterize large designs, which we highly recommend one reads prior to using this functionality in a design. The following, however, is a basic introduction. - -Every Module has its own \verb+params+ object, which acts as a dictionary. Querying this object is shown below. - -\begin{scala} -val width = params[Int]('width') -\end{scala} - -If \verb+params+ is queried and no parameter matches the query, Chisel throws a \verb+ParameterUndefinedException+. Notice the query return type must be provided. - -When a parent Module creates a child Module, the parent's \verb+params+ object is automatically cloned and passed to the child. In the following example, suppose the parent's params object returns \verb+10+ when queried for width. Because the \verb+Parent+ \verb+params+ object is automatically cloned for \verb+Child+, the \verb+Child+ query also returns \verb+10+. - -\begin{scala} -class Parent extends Module { - val io = new Bundle { ... } - val width = params[Int]('width') // returns 10 - // create child Module implicitly passing params - val child = Module(new Child) -} -class Child extends Module { - val io = new Bundle { ... } - val width = params[Int]('width') // returns 10 -} -\end{scala} - -Suppose a parent Module wants to override or add parameters to its child's \verb+params+ object. This case requires adding a partial function (a Scala way of defining key-value mappings) to the \verb+Child+ Module constructor: - -\begin{scala} -class Parent extends Module { - val io = new Bundle { ... } - val width = params[Int]('width') // returns 10 - val n = params[Int]('n') // returns 20 - // Partial function is added to Module constructor - val child = Module(new Child,{'n' => 40}) -} -class Child extends Module { - val io = new Bundle { ... } - val width = params[Int]('width') // returns 10 - val n = params[Int]('n') // returns 40 -} -\end{scala} - -An example which is impossible to do with simple parameterization, but simple with the advanced parameterization, is when using a generic \verb+Mesh+ generator with a custom \verb+MyRouter+ Module. The existing source code might look like: - -\begin{scala} -class Mesh(routerConstructor: () => Router, n:Int) extends Module { - val io = new Bundle { ... } - val routers = Vec.fill(n){Module(routerConstructor())} - hookUpRouters(routers) -} -\end{scala} - -However, our custom \verb+MyRouter+ Module requires a parameter, \verb+RoutingFunction+ that we want to sweep for a design space evaluation. Using the simple parameterization method would require a change to the \verb+Mesh+ Module's constructor to include \verb+RoutingFunction+. - -Alternatively, one can use the \verb+params+ object to implicitly pass the \verb+RoutingFunction+: - -\begin{scala} -class MyRouter extends Module { - val io = new Bundle { ... } - val myRoutingFunction = params[RoutingFunction]('r') - ... -} -class Top extends Module { - val io = new Bundle { ... } - val mesh = Module(new Mesh(() => new MyRouter),{'r' => new RoutingFunction}) -} -\end{scala} - -For more advanced uses, tips, and tricks, please see XXXX. - -\section{Built In Primitives} - -Like other HDL, Chisel provides some very basic primitives. These are constructs that are built in to the Chisel compiler and come for free. The Reg, UInt, and Bundle classes are such primitives that has already been covered. Unlike Module instantiations, primitive do not require explicit connections of their io ports to use. Other useful primitive types include the Mem and Vec classes which will be discussed in a more advanced tutorial. In this tutorial we explore the use of the \verb+Mux+ primitive - -\subsection{The Mux Class} - -The \verb+Mux+ primitive is a two input multiplexer. In order to use the \verb+Mux+ we first need to define the expected syntax of the \verb+Mux+ class. As with any two input multiplexer, it takes three inputs and one output. Two of the inputs correspond to the data values \verb+A+ and \verb+B+ that we would like to select which can be any width and data type as long as they are the same. The third input \verb+select+ which is a Bool type determines which one to output. -A \verb+select+ value of \verb+true+ will output the first value \verb+A+, while a \verb+select+ value of \verb+false+ will pass \verb+B+. - -\begin{scala} -val out = Mux(select, A, B) -\end{scala} - -Thus if \verb+A=10+, \verb+B=14+, and \verb+select+ was \verb+true+, the value of \verb+out+ would be assigned 10. Notice how using the \verb+Mux+ primitive type abstracts away the logic structures required if we had wanted to implement the multiplexer explicitly. - -\subsection{\problem{Parameterized Width Adder}} - -The next assignment is to construct an adder with a parameterized width and using the built in addition operator \verb!+!. -The following is a the template from \verb+$TUT_DIR/problems/Adder.scala+: - -\begin{scala} -class Adder(val w: Int) extends Module { - val io = new Bundle { - val in0 = UInt(INPUT, 1) - val in1 = UInt(INPUT, 1) - val out = UInt(OUTPUT, 1) - } - ... - io.out := UInt(0) -} -\end{scala} - -\noindent -where \verb+out+ is sum of \verb+w+ width unsigned inputs \verb+in0+ and \verb+in1+. -Notice how \verb+val+ is added to the width parameter value to -allow the width to be accessible from the tester as a field of the adder module object. Run - -\begin{bash} -make Adder.out -\end{bash} - -\noindent -until your circuit passes the tests. - -% Martin: I would drop the following as it is just confusing in a tutorial -% state simple that there is a Mux primitive and that is fine. - -%The instantiation would look something like this: -% -%\begin{scala} -%// where n is the width of A and m is the width of B -%val mux = Module(new Mux(n, m)) -%mux.io.select := select -%mux.io.A := A -%mux.io.B := B -%val out = mux.io.out -%\end{scala} -% -%We see that clearly it is much cleaner to use the primitive \verb+Mux+ type instead of trying to write and implement our own general multiplexer since the \verb+Mux+ type does all the wiring for you. - - -%\section{Exercises} -% -%\subsection{n-bit Subtractor} -% -%Earlier in this tutorial we demonstarted how to parametrize and instantiate an n-bit ripple adder. -% diff --git a/doc/getting-started/modules.tex b/doc/getting-started/modules.tex deleted file mode 100644 index 81f44c97..00000000 --- a/doc/getting-started/modules.tex +++ /dev/null @@ -1,58 +0,0 @@ -\documentclass[twocolumn, 10pt]{article} -\setlength\textwidth{6.875in} -\setlength\textheight{8.875in} -% set both margins to 2.5 pc -\setlength{\oddsidemargin}{-0.1875in}% 1 - (8.5 - 6.875)/2 -\setlength{\evensidemargin}{-0.1875in} -\setlength{\marginparwidth}{0pc} -\setlength{\marginparsep}{0pc}% -\setlength{\topmargin}{0in} \setlength{\headheight}{0pt} -\setlength{\headsep}{0pt} -\setlength{\footskip}{37pt}% -%\setlength{\columnsep}{0.3125in} -%\setlength{\columnwidth}{3.28125in}% (6.875 - 0.3125)/2 = 3.28125in -\setlength{\parindent}{1pc} -\newcommand{\myMargin}{1.00in} -\usepackage[top=\myMargin, left=\myMargin, right=\myMargin, bottom=\myMargin, nohead]{geometry} -\usepackage{epsfig,graphicx} -\usepackage{palatino} -\usepackage{fancybox} -\usepackage{hyperref} -\usepackage[procnames]{listings} - -\input{../style/scala.tex} - -\lstset{basicstyle={\footnotesize\ttfamily}} - -\newenvironment{commentary} -{ \vspace{-0.1in} - \begin{quotation} - \noindent - \small \em - \rule{\linewidth}{1pt}\\ -} -{ - \end{quotation} -} - -\title{Getting Started - Tutorial 03: Instantiating Modules} -\author{Jonathan Bachrach, Vincent Lee \\ -EECS Department, UC Berkeley\\ -{\tt \{jrb\}@eecs.berkeley.edu} -} -\date{\today} - -\newenvironment{example}{\VerbatimEnvironment\begin{footnotesize}\begin{Verbatim}}{\end{Verbatim}\end{footnotesize}} -\newcommand{\kode}[1]{\begin{footnotesize}{\tt #1}\end{footnotesize}} - -\def\code#1{{\tt #1}} - -\def\note#1{\noindent{\bf [Note: #1]}} -%\def\note#1{} - -\begin{document} -\maketitle{} - -\input{modules-guts} - -\end{document} diff --git a/doc/getting-started/projects-guts.tex b/doc/getting-started/projects-guts.tex deleted file mode 100644 index 4cb90208..00000000 --- a/doc/getting-started/projects-guts.tex +++ /dev/null @@ -1,109 +0,0 @@ -\section{Creating Your Own Projects} - -In order to create your own projects from scratch, you will need to create a directory, a Chisel source file, and a build.sbt configuration file. In the first part of this tutorial we cover the basic calls to SBT in order generate appropriate files. At the end of the tutorial, we will explain how the Makefile infrastructure can make the process more streamlined. - -\subsection{Directory Structure} - -The simplest project file organization is using a single directory containing your Scala project file and your Chisel source file. The project directory structure would look like: - -\begin{bash} -Hello/ - build.sbt # scala configuration file - Hello.scala # your source file -\end{bash} - -We will refer to the path to the \verb+Hello+ directory as \verb+$BASEDIR+ from here on. More sophisticated directory structures can be useful in the future. Consult the SBT documentation for more information. - -\subsection{The Source Directory and Chisel Main} - -The top directory \verb+$BASEDIR/+ contains Scala source files containing all of the Chisel module definitions for your circuit and a main method. In this simple example, we have one Scala source file as shown below: - -\begin{scala} -package Hello - -import Chisel._ - -class HelloModule extends Module { - val io = new Bundle { - val out = UInt(OUTPUT, 8) - } - io.out := UInt(42) -} - -class HelloModuleTests(c: HelloModule) - extends Tester(c) { - step(1) - expect(c.io.out, 42) -} - -object hello { - def main(args: Array[String]): Unit = { - val margs = - Array("--backend", "c", "--genHarness", "--compile", "--test") - chiselMainTest(margs, () => Module(new HelloModule())) { - c => new HelloModuleTests(c) - }) - } -} -\end{scala} - -In the above example, we have a module definition in package \verb+Hello+ for a \verb+Hello+ module. The main method calls \verb+chiselMainTest+ for a new Hello module\footnote{Note that when you have multiple Scala files, in order for main to recognize your module definition, your module definition must be in the same package as the main function}. In addition to creating the module, the call to \verb+chiselMainTest+ also includes a call to execute the scala testbench defined in the routine \verb+HelloModuleTests+. - -\subsection{The build.sbt Template} - -The \verb+build.sbt+ configuration file is located in the top folder and contains a number of settings used by \verb+sbt+ when building and compiling the Chisel sources. The following shows the recommended \verb+build.sbt+ template that should be used: - -\begin{scala} -scalaVersion := "2.10.2" - -resolvers ++= Seq( - "scct-github-repository" at "http://mtkopone.github.com/scct/maven-repo" -) - -libraryDependencies += - "edu.berkeley.cs" %% "chisel" % "latest.release" -\end{scala} - -The SBT project file contains a reference to Scala version greater or equal to 2.10.2 and a dependency on the latest release of the Chisel library. - -\section{Compiling the Chisel Source} - -\subsection{Compiling the Emulation Files} - -In order to launch SBT to compile the Chisel code we must first be in the directory \verb+$BASEDIR/+. The following call is then made to compile and run the Hello module: - -\begin{bash} -sbt run -\end{bash} - -\subsection{Running the Chisel Tests} - -To actually run the tests referenced in the main method of \verb+$BASEDIR/Hello.scala+, we need to tell SBT to also generate the harness and run the tests. For instance, for our Hello module introduced earlier, the Chisel main method references a test routine \verb+HelloTests+. In order to both compile the Hello component and run the tests defined in \verb+Hello+, we make the following call to sbt: - -\begin{bash} -sbt "run --backend c --compile --test --genHarness" -\end{bash} - -Note the addition of the 5 arguments at the end of the call to \verb+run+. This will both compile the \verb+.cpp+ and \verb+.h+ files for the emulator and run the Chisel tests defined. - -\subsection{Compiling Verilog} - -Similarly to compile the Chisel code and generate the Verilog HDL, a similar call to SBT is made with slightly different arguments. The call looks like: - -\begin{bash} -sbt "run --backend v --genHarness" -\end{bash} - -Notice the call is very similar to when generating C++; the key difference is the parameter to the \verb+--backend+ attribute which is now \verb+v+ which specifies to sbt that we would like to compile our Chisel component to Verilog. - -\section{Putting It All Together} - -In summary, the bare minimum project components that are necessary for your project to get off the ground are the following files: - -\begin{enumerate} -\item \verb+$BASEDIR/build.sbt+ -\item \verb+$BASEDIR/.scala+ -\end{enumerate} - -Together, these files compose a Chisel project and can be used to generate the Verilog and C++ files. It is strongly recommended that you supplement the file structure with appropriate Makefiles but is not strictly necessary (examples can be found in the Chisel tutorial project). - diff --git a/doc/getting-started/projects.tex b/doc/getting-started/projects.tex deleted file mode 100644 index dfbcdd3f..00000000 --- a/doc/getting-started/projects.tex +++ /dev/null @@ -1,58 +0,0 @@ -\documentclass[twocolumn, 10pt]{article} -\setlength\textwidth{6.875in} -\setlength\textheight{8.875in} -% set both margins to 2.5 pc -\setlength{\oddsidemargin}{-0.1875in}% 1 - (8.5 - 6.875)/2 -\setlength{\evensidemargin}{-0.1875in} -\setlength{\marginparwidth}{0pc} -\setlength{\marginparsep}{0pc}% -\setlength{\topmargin}{0in} \setlength{\headheight}{0pt} -\setlength{\headsep}{0pt} -\setlength{\footskip}{37pt}% -%\setlength{\columnsep}{0.3125in} -%\setlength{\columnwidth}{3.28125in}% (6.875 - 0.3125)/2 = 3.28125in -\setlength{\parindent}{1pc} -\newcommand{\myMargin}{1.00in} -\usepackage[top=\myMargin, left=\myMargin, right=\myMargin, bottom=\myMargin, nohead]{geometry} -\usepackage{epsfig,graphicx} -\usepackage{palatino} -\usepackage{fancybox} -\usepackage{hyperref} -\usepackage[procnames]{listings} - -\input{../style/scala.tex} - -\lstset{basicstyle={\footnotesize\ttfamily}} - -\newenvironment{commentary} -{ \vspace{-0.1in} - \begin{quotation} - \noindent - \small \em - \rule{\linewidth}{1pt}\\ -} -{ - \end{quotation} -} - -\title{Getting Started - Tutorial 05: Creating Your Own Project} -\author{Jonathan Bachrach, Vincent Lee \\ -EECS Department, UC Berkeley\\ -{\tt \{jrb\}@eecs.berkeley.edu} -} -\date{\today} - -\newenvironment{example}{\VerbatimEnvironment\begin{footnotesize}\begin{Verbatim}}{\end{Verbatim}\end{footnotesize}} -\newcommand{\kode}[1]{\begin{footnotesize}{\tt #1}\end{footnotesize}} - -\def\code#1{{\tt #1}} - -\def\note#1{\noindent{\bf [Note: #1]}} -%\def\note#1{} - -\begin{document} -\maketitle{} - -\input{projects-guts} - -\end{document} diff --git a/doc/getting-started/scripting-guts.tex b/doc/getting-started/scripting-guts.tex deleted file mode 100644 index 1f550ad9..00000000 --- a/doc/getting-started/scripting-guts.tex +++ /dev/null @@ -1,223 +0,0 @@ -\section{Using the For loop} - -Often times parametrization requires instantiating multiple components which are connected in a very regular structure. A revisit to the parametrized \verb+Adder+ component definition shows the \verb+for+ loop construct in action: - -\begin{scala} -// A n-bit adder with carry in and carry out -class Adder(n: Int) extends Module { - val io = new Bundle { - val A = UInt(INPUT, n) - val B = UInt(INPUT, n) - val Cin = UInt(INPUT, 1) - val Sum = UInt(OUTPUT, n) - val Cout = UInt(OUTPUT, 1) - } - // create a vector of FullAdders - val FAs = Vec.fill(n){ Module(new FullAdder()).io } - val carry = Vec.fill(n+1){ UInt(width = 1) } - val sum = Vec.fill(n){ Bool() } - - // first carry is the top level carry in - carry(0) := io.Cin - - // wire up the ports of the full adders - for(i <- 0 until n) { - FAs(i).a := io.A(i) - FAs(i).b := io.B(i) - FAs(i).cin := carry(i) - carry(i+1) := FAs(i).cout - sum(i) := FAs(i).sum.toBool() - } - io.Sum := sum.toBits().toUInt() - io.Cout := carry(n) -} -\end{scala} - -Notice that a Scala integer \verb+i+ value is used in the \verb+for+ loop definition as the index variable. This indexing variable is specified to take values from 0 \verb+until+ n, which means it takes values 0, 1, 2..., n-1. If we wanted it to take values from 0 to n inclusive, we would use \verb+for (i <- 0 to n)+. - -It is also important to note, that the indexing variable \verb+i+ does not actually manifest itself in the generated hardware. It exclusively belongs to Scala and is only used in declaring how the connections are specified in the Chisel component definition. - -The for loop construct is also very useful for assigning to arbitrarily long \verb+Vec+s - -\section{Using If, Else If, Else} - -As previously mentioned, the \verb+if, elseif,+ and \verb+else+ keywords are reserved for Scala control structures. What this means for Chisel is that these constructs allow you to selectively generate different structures depending on parameters that are supplied. This is particularly useful when you want to turn certain features of your implementation "on" or "off", or if you want to use a different variant of some component. - -For instance, suppose we have several simple counters that we would like to package up into a general purpose counter module: UpCounter, DownCounter, and OneHotCounter. From the definitions below, we notice that for these simple counters, the I/O interfaces and parameters are identical: - -\begin{scala} -// Simple up counter that increments from 0 and wraps around -class UpCounter(CounterWidth:Int) extends Module { - val io = new Bundle { - val output = UInt(OUTPUT, CounterWidth) - val ce = Bool(INPUT) - }... -} - -// Simple down counter that decrements from -// 2^CounterWidth-1 then wraps around -class DownCounter(CounterWidth:Int) extends Module{ - val io = new Bundle { - val output = UInt(OUTPUT, CounterWidth) - val ce = Bool(INPUT) - }... -} - -// Simple one hot counter that increments from one hot 0 -// to CounterWidth-1 then wraps around -class OneHotCounter(CounterWidth:Int) extends Module { - val io = new Bundle { - val output = UInt(OUTPUT, CounterWidth) - val ce = Bool(INPUT) - }... -} -\end{scala} - -We could just instantiate all three of these counters and multiplex between them but if we needed one at any given time this would be a waste of hardware. In order to choose between which of these three counters we want to instantiate, we can use Scala's \verb+if, else if, else+ statements to tell Chisel how to pick which component to instantiate based on a \verb+CounterType+ parameter: - -\begin{scala} -class Counter(CounterWidth: Int, CounterType: String) - extends Module { - val io = new Bundle { - val output = UInt(OUTPUT, CounterWidth) - val ce = Bool(INPUT) - } - if (CounterType == "UpCounter") { - val upcounter = new UpCounter(CounterWidth) - upcounter.io.ce := io.ce - io.output := upcounter.io.output - } else if (CounterType == "DownCounter") { - val downcounter = new DownCounter(CounterWidth) - downcounter.io.ce := io.ce - io.output := downcounter.io.output - } else if (CounterType == "OneHotCounter") { - val onehotcounter = new OneHotCounter(CounterWidth) - onehotcounter.io.ce := io.ce - io.output := onehotcounter.io.output - } else { - // default output 1 - io.output := UInt(1) - } -} -\end{scala} - -By consolidating these three counter components into a single \verb+Counter+ module, we can instantiate a different counter by simply changing the parameter \verb+CounterType+. For instance: - -\begin{scala} -// instantiate a down counter of width 16 -val downcounter = - Module(new Counter(16, "DownCounter")) - -// instantiate an up counter of width 16 -val upcounter = - Module(new Counter(16, "UpCounter")) - -// instantiate a one hot counter of width 16 -val onehotcounter = - Module(new Counter(16, "OneHotCounter")) -\end{scala} - -This allows seamless alternation between them. - -\section{Using def} - -Chisel also allows the usage of the Scala \verb+def+ statement to define Chisel code that may be used frequently. These \verb+def+ statements can be packaged into a Scala Object and then called inside a Module. The following Chisel code shows an alternate implementation of an counter using \verb+def+ that increments by \verb+amt+ if the \verb+inc+ signal is asserted. - -\begin{scala} -object Counter { - def wrapAround(n: UInt, max: UInt) = - Mux(n > max, UInt(0), n) - - def counter(max: UInt, en: Bool, amt: UInt) = { - val x = Reg(init = UInt(0, max.getWidth)) - x := wrapAround(x + amt, max) - x - } -} - -class Counter extends Module { - val io = new Bundle { - val inc = Bool(INPUT) - val amt = UInt(INPUT, 4) - val tot = UInt(OUTPUT, 8) - } - io.tot := counter(UInt(255), io.inc, io.amt) -} -\end{scala} - -\noindent -In this example, we use calls to subroutines defined in the \verb+Counter+ object in order to perform the appropriate logic. - -\section{\problem{Parameterized Vec Shift Reg}} - -The next assignment is to construct a bit shift register with delay parameter. -The following is a the template from \verb+$TUT_DIR/problems/VecShiftRegisterParam.scala+: - -\begin{scala} -class VecShiftRegisterParam(val n: Int, val w: Int) extends Module { - val io = new Bundle { - val in = UInt(INPUT, w) - val out = UInt(OUTPUT, w) - } - ... - io.out := UInt(0) -} -\end{scala} - -\noindent -where \verb+out+ is a \verb+n+ cycle delayed copy of values on \verb+in+. -Also notice how \verb+val+ is added to each parameter value to -allow those values to be accessible from the tester. Run - -\begin{bash} -make VecShiftRegisterParam.out -\end{bash} - -\noindent -until your circuit passes the tests. - -\section{\problem{Mul Lookup Table}} - -The next assignment is to write a 16x16 multiplication table using \verb+Vec+. -The following is a the template from \verb+$TUT_DIR/problems/Mul.scala+: - -\begin{scala} -class Mul extends Module { - val io = new Bundle { - val x = UInt(INPUT, 4) - val y = UInt(INPUT, 4) - val z = UInt(OUTPUT, 8) - } - val muls = new ArrayBuffer[UInt]() - - // flush this out ... - - io.z := UInt(0) -} -\end{scala} - -\noindent -As a hint build the lookup table using a rom constructed from the \verb+tab+ lookup table represented as a Scala ArrayBuffer with incrementally added elements (using \verb!+=!): - -\begin{scala} -val tab = Vec(muls) -\end{scala} - -\noindent -and lookup the result using an address formed from the \verb+x+ and \verb+y+ inputs as follows: - -\begin{scala} -io.z := tab(Cat(io.x, io.y)) -\end{scala} - -\noindent -Run - -\begin{bash} -make Mul.out -\end{bash} - -\noindent -until your circuit passes the tests. - -% The first call to \verb+counter+ in the \verb+Counter+ module diff --git a/doc/getting-started/scripting.tex b/doc/getting-started/scripting.tex deleted file mode 100644 index 7abb4b09..00000000 --- a/doc/getting-started/scripting.tex +++ /dev/null @@ -1,58 +0,0 @@ -\documentclass[twocolumn, 10pt]{article} -\setlength\textwidth{6.875in} -\setlength\textheight{8.875in} -% set both margins to 2.5 pc -\setlength{\oddsidemargin}{-0.1875in}% 1 - (8.5 - 6.875)/2 -\setlength{\evensidemargin}{-0.1875in} -\setlength{\marginparwidth}{0pc} -\setlength{\marginparsep}{0pc}% -\setlength{\topmargin}{0in} \setlength{\headheight}{0pt} -\setlength{\headsep}{0pt} -\setlength{\footskip}{37pt}% -%\setlength{\columnsep}{0.3125in} -%\setlength{\columnwidth}{3.28125in}% (6.875 - 0.3125)/2 = 3.28125in -\setlength{\parindent}{1pc} -\newcommand{\myMargin}{1.00in} -\usepackage[top=\myMargin, left=\myMargin, right=\myMargin, bottom=\myMargin, nohead]{geometry} -\usepackage{epsfig,graphicx} -\usepackage{palatino} -\usepackage{fancybox} -\usepackage{hyperref} -\usepackage[procnames]{listings} - -\input{../style/scala.tex} - -\lstset{basicstyle={\footnotesize\ttfamily}} - -\newenvironment{commentary} -{ \vspace{-0.1in} - \begin{quotation} - \noindent - \small \em - \rule{\linewidth}{1pt}\\ -} -{ - \end{quotation} -} - -\title{Getting Started: Tutorial 07 - Scripting Hardware Generation} -\author{Jonathan Bachrach, Vincent Lee \\ -EECS Department, UC Berkeley\\ -{\tt \{jrb\}@eecs.berkeley.edu} -} -\date{\today} - -\newenvironment{example}{\VerbatimEnvironment\begin{footnotesize}\begin{Verbatim}}{\end{Verbatim}\end{footnotesize}} -\newcommand{\kode}[1]{\begin{footnotesize}{\tt #1}\end{footnotesize}} - -\def\code#1{{\tt #1}} - -\def\note#1{\noindent{\bf [Note: #1]}} -%\def\note#1{} - -\begin{document} -\maketitle{} - -\input{scripting-guts} - -\end{document} diff --git a/doc/getting-started/state-guts.tex b/doc/getting-started/state-guts.tex deleted file mode 100644 index 5b45e744..00000000 --- a/doc/getting-started/state-guts.tex +++ /dev/null @@ -1,356 +0,0 @@ -\section{Conditional Register Updates} - -As shown earlier in the tutorial, conditional register updates are performed with the \verb+when+ block which takes a \verb+Bool+ value or some boolean expression to evaluate. -In this section we more fully explore how to use this \verb+when+ conditional update structure. - -If a \verb+when+ block is used by itself, Chisel will assume that if the condition for the \verb+when+ block doesn't evaluate to true, there is no update to the register value. However, most of the time we don't want to limit ourselves to a single conditional. Thus in Chisel we use \verb+.elsewhen+ and \verb+.otherwise+ statements to select between multiple possible register updates as shown in the following sections. - -\subsection{The .elsewhen Clause} - -When specifying a conditional update, we may want to check several conditions which we want to check in some order. -To do this for register updates, we use a \verb+when ... .elsewhen+ structure. This is analagous to an \verb+if... else if+ control structure in sequential programming. \footnote{Note that the if .. else if control structure in Chisel is NOT used to specify register updates} -As with \verb+else if+ clauses, as many \verb+.elsewhen+ statements can be chained together in a single \verb+when+ block. - -The general structure thus looks like: - -%$when$ () {} -%.elsewhen () {} -%... -%.elsewhen () {} - -\begin{scala} -when () {} -.elsewhen () {} -... -.elsewhen () {} -\end{scala} - -Where \verb++ through \verb++ represent the trigger conditions of their respective \verb++ segments. - -An example of this statement in action is shown in the following implementation of a simple stack pointer. Suppose, we need to maintain a pointer that keeps track of the address of the top of a stack. Given a signal \verb+pop+ that decrements the stack pointer address by 1 entry and a signal \verb+push+ that increments the stack pointer address by 1 entry, the implementation of just the pointer would look like the following: - -\begin{scala} -class StackPointer(depth:Int) extends Module { - val io = new Bundle { - val push = Bool(INPUT) - val en = Bool(INPUT) - val pop = Bool(INPUT) - } - - val sp = Reg(init = UInt(0, width = log2Up(depth))) - - when (io.en && io.push && (sp != UInt(depth-1))) { - sp := sp + UInt(1) - } .elsewhen(io.en && io.pop && (sp > UInt(0))) { - sp := sp - UInt(1) - } -} -\end{scala} - -Notice that in this implementation, the push signal has higher priority over the pop signal as it appears earlier in the \verb+when+ block. - -\subsection{The .otherwise Clause} - -In order to specify a default register update value if all the conditions in the \verb+when+ block fail to trigger, we use an \verb+.otherwise+ clause. -The \verb+.otherwise+ clause is analagous to the \verb+else+ case that completes an \verb+if ... else+ block. The \verb+.otherwise+ statement must occur last in the \verb+when+ block. - -The general structure for the complete \verb+when+ block now looks like: -\begin{scala} -when () {} -.elsewhen () {} -... -.elsewhen () {} -.otherwise {} -\end{scala} - -In the previous example, we could add a default statement which just assigns \verb+sp+ to the current value of \verb+sp+. The \verb+block+ would then look like: - -\begin{scala} -when(io.en && io.push && (sp != UInt(depth-1))) { - sp := sp + UInt(1) -} .elsewhen(io.en && io.pop && (sp > UInt(0))) { - sp := sp - UInt(1) -} .otherwise { - sp := sp -} -\end{scala} - -The explicit assignment to preserve the value of \verb+sp+ is redundant in this case but it captures the point of the \verb+.otherwise+ statement. - -\subsection{The unless Clause} - -% Martin: this feels a little bit strange as it is not a usual construct in a programming language. -% It is simple !condition, right? So I would drop it. - -To complement the \verb+when+ statement, Chisel also supports an \verb+unless+ statement. The \verb+unless+ statement is a conditional assignment that triggers only if the condition is false. The general structure for the \verb+unless+ statement is: - -\begin{scala} -unless ( ) { } -\end{scala} - -For example, suppose we want to do a simple search of the contents of memory and determine the address that contains some number. Since we don't know how long the search will take, the module will output a \verb+done+ signal when it is finished and until then, we want to continue to search memory. The Chisel code for the module would look like: - -\begin{scala} -class MemorySearch extends Module { - val io = new Bundle { - val target = UInt(INPUT, 4) - val address = UInt(OUTPUT, 3) - val en = Bool(INPUT) - val done = Bool(INPUT) - } - val index = Reg(init = UInt(0, width = 3)) - val list = Vec(UInt(0), UInt(4), UInt(15), UInt(14), UInt(2), UInt(5), UInt(13)) - val memVal = list(index) - - val done = (memVal === io.target) || (index === UInt(7)) - - unless (done) { - index := index + UInt(1) - } - io.done := done - io.address := index -} -\end{scala} - -In this example, we limit the size of the memory to 8 entries and use a vector of literals to create a read only memory. Notice that the \verb+unless+ statement is used to terminate the iteration if it see that the \verb+done+ signal is asserted. Otherwise, it will continue to increment the index in memory until it finds the value in \verb+target+ or reaches the last index in the memory (7). - -\section{Combinational Conditional Assignment} - -You can also use the \verb+when .elsewhen .otherwise+ block to define combinational values that may take many values. For example, the following Chisel code show how to implement a basic arithmetic unit with 4 operations: add, subtract, and pass. In this example, we check the opcode to determine which operation to perform and conditionally assign the output. - -\begin{scala} -class BasicALU extends Module { - val io = new Bundle { - val a = UInt(INPUT, 4) - val b = UInt(INPUT, 4) - val opcode = UInt(INPUT, 2) - val output = UInt(OUTPUT, 4) - } - io.output := UInt(0) - when (io.opcode === UInt(0)) { - io.output := io.a + io.b // ADD - } .elsewhen (io.opcode === UInt(1)) { - io.output := io.b - io.b // SUB - } .elsewhen (io.opcode === UInt(2)) { - io.output := io.a // PASS A - } .otherwise { - io.output := io.b // PASS B - } -} -\end{scala} - -Notice that this can easily be easily expanded to check many different conditions for more complicated arithmetic units or combinational blocks. - -\section{Read Only Memories} - -To instantiate read only memories in Chisel, we use a vector of constant literals and specify a literal type. For example, in order to instantiate an 4 entry read only memory with the values 0 to 3, the definition would look like the following: - -\begin{footnotesize} -\begin{scala} -val numbers = - Vec(UInt(0),UInt(1),UInt(2),UInt(3)){ UInt(width = 2) } -\end{scala} -\end{footnotesize} - -Notice that we need to specify the type of literal in the {...} braces following the literals. Accessing the values in the read only memory is the same as accessing an entry in a \verb+Vec+. For example, to access the 2nd entry of the memory we would use: - -\begin{scala} -val entry2 = numbers(2) -\end{scala} - -\section{Read-Write Memories} - -Chisel contains a primitive for memories called \verb+Mem+. Using the \verb+Mem+ class it is possible to construct multi-ported memory that can be synchronous or combinational read. \footnote{The complete definition can be found in the chisel source in Mem.scala} - -\subsection{Basic Instantiation} - -The \verb+Mem+ construction takes a memory depth and a data type which it is composed of. The general declaration structure looks like: - -\begin{scala} -val myMem = Mem(, ) -\end{scala} - -Where \verb++ corresponds to the number of entries of \verb++ are in the memory. - -For instance, if you wanted to create a 128 deep memory of 32 bit UInt types, you would use the following instantiation: - -\begin{scala} -val myMem = Mem(UInt(width = 32), depth = 128) -\end{scala} - -Note that when constructing a memory in Chisel, the initial value of memory contents cannot be specified. Therefore, you should never assume anything about the initial contents of your \verb+Mem+ class. - -\subsection{Synchronous vs. Combinational Read} - -It is possible to specify either combinational or synchronous read behavior during instantiation by setting the \verb+seqRead+ parameter when defining the \verb+Mem+. The \verb+seqRead+ parameter is a \verb+Bool+ that tells Chisel if you want synchronous read behavior memory or not. - -For instance, if we wanted a combinational read 128 entry memory of 32 bit UInt types, we would use the following definition: - -\begin{scala} -val asyncMem = - Mem(UInt(width = 32), 128, seqRead = false) -\end{scala} - -Likewise, if we wanted a synchronous read 128 entry memory of 32 bit UInt types, we would set the \verb+seqRead+ to true: - -\begin{scala} -val syncMem = - Mem(UInt(width = 32), 128, seqRead = true) -\end{scala} - -% this needs more elaboration. Memories in hardware are tough... - -By default, Chisel will assume that the read behavior is combinational. - -\subsection{Adding Write Ports} - -To add write ports to the \verb+Mem+, we use a \verb+when+ block to allow Chisel to infer a write port. Inside the \verb+when+ block, we specify the location and data for the write transaction. In general, adding a write port requires the following definition: - -\begin{scala} -when ( ) { - ( ) := -} -\end{scala} - -Where \verb++ refers to the entry number in the memory to write to. Also notice that we use the reassignment operator \verb+:=+ when writing to the memory. - - -For example, suppose we have a 128 deep memory of 32 bit UInt types. If we wanted to write a 32 bit value \verb+dataIn+ to the memory at location \verb+writeAddr+ if as write enable signal \verb+we+ is true, our Chisel code would look like: - -\begin{scala} -... -val myMem = Mem(UInt(width = 32), depth = 128) -when (wen) { - myMem(writeAddr) := dataIn -} -... -\end{scala} - - - -\subsection{Adding Read Ports} - -Depending on the type of read behaviour specified, the syntax for adding read ports to \verb+Mem+ in Chisel is slightly different for combinational read and synchronous read memories. - -\subsubsection{Combinational Read Ports} - -For combinational read memories, adding read ports to the memory simply amounts to placing an assignment inside a \verb+when+ block with some trigger condition. If you want Chisel to infer multiple read ports, simply add more assignments in the \verb+when+ definition. The general definition for read ports is thus: - -\begin{scala} -when () { - := ( ) - ... - := ( ) -} -\end{scala} - -For instance, if you wanted a 128 entry memory of 32 bit UInt values with two combinational read ports, with some read enable \verb+re+ and reads from addresses \verb+raddr1+ and \verb+raddr2+, we would use the following \verb+when+ block definition: - -\begin{scala} -... -val myMem = - Mem(UInt(width = 32), 128, seqRead = false) -val read_port1 = UInt(width = 32) -val read_port2 = UInt(width = 32) -when (re) { - read_port1 := myMem(raddr1) - read_port2 := myMem(raddr2) -} -... -\end{scala} - -Note that the type and width of the \verb+read_port1+ and \verb+read_port2+ should match the type and width of the entries in the \verb+Mem+. - -\subsubsection{Synchronous Read Ports} - -In order to add synchronous read ports to the Chisel \verb+Mem+ class, Chisel requires that the output from the memory be assigned to a \verb+Reg+ type. Like the combinational read port, a synchronous read assignment must occur in a \verb+when+ block. The general structure for the definition of a synchronous read port is as follows: - -\begin{scala} -... -val myMem = - Mem(UInt(width = 32), depth = 128, seqRead = true) -val read_port = Reg(UInt(width = 32)) -when (re) { - read_port := myMem(raddr) -} -... -\end{scala} - -\subsection{Example of Mem in Action} - -% Martin: no, it was not yet shown -%We introduced a basic stack pointer bookkeeping example earlier in the tutorial. In this section we show how the complete stack implementation would look like. - -Here we provide a small example of using a memory by implementing a stack. - -Suppose we would like to implement a stack that takes two signals \verb+push+ and \verb+pop+ where \verb+push+ tells the stack to push an input \verb+dataIn+ to the top of the stack, and \verb+pop+ tells the stack to pop off the top value from the stack. Furthermore, an enable signal \verb+en+ disables pushing or popping if not asserted. Finally, the stack should always output the top value of the stack. - -\begin{scala} -class Stack(depth: Int) extends Module { - val io = new Bundle { - val dataIn = UInt(INPUT, 32) - val dataOut = UInt(OUTPUT, 32) - val push = Bool(INPUT) - val pop = Bool(INPUT) - val en = Bool(INPUT) - } - - // declare the memory for the stack - val stack_mem = - Mem(UInt(width = 32), depth, seqRead = false) - val sp = Reg(init = UInt(0, width = log2Up(depth))) - val dataOut = Reg(init = UInt(0, width = 32)) - - // Push condition - make sure stack isn't full - when(io.en && io.push && (sp != UInt(depth-1))) { - stack_mem(sp + UInt(1)) := io.dataIn - sp := sp + UInt(1) - } - // Pop condition - make sure the stack isn't empty - .elsewhen(io.en && io.pop && (sp > UInt(0))) { - sp := sp - UInt(1) - } - - when(io.en) { - dataOut := stack_mem(sp) - } - - io.dataOut := dataOut -} -\end{scala} - -Since the module is parametrized to be \verb+depth+ entries deep, in order to correctly extract the minimum width of the stack pointer \verb+sp+ we take the \verb+log2Up(depth)+. This takes the base 2 logarithm of \verb+depth+ and rounds up. - -\subsection{\problem{Load/Search Mem}} - -In this assignment, write a memory module that supports loading elements and searching based on the following template: - -\begin{scala} -class DynamicMemorySearch(val n: Int, val w: Int) extends Module { - val io = new Bundle { - val isWr = Bool(INPUT) - val wrAddr = UInt(INPUT, log2Up(n)) - val data = UInt(INPUT, w) - val en = Bool(INPUT) - val target = UInt(OUTPUT, log2Up(n)) - val done = Bool(OUTPUT) - } - val index = Reg(init = UInt(0, width = log2Up(n))) - val memVal = UInt(0) - /// fill in here - io.done := Bool(false) - io.target := index -} -\end{scala} - -\noindent -and found in \verb+$TUT_DIR/problems/DynamicMemorySearch.scala+. -Notice how it support depth and width parameters \verb+n+ and \verb+w+ and -how the address width is computed from the depth. Run - -\begin{bash} -make DynamicMemorySearch.out -\end{bash} - -\noindent -until your circuit passes the tests. diff --git a/doc/getting-started/state.tex b/doc/getting-started/state.tex deleted file mode 100644 index ac993c25..00000000 --- a/doc/getting-started/state.tex +++ /dev/null @@ -1,58 +0,0 @@ -\documentclass[twocolumn, 10pt]{article} -\setlength\textwidth{6.875in} -\setlength\textheight{8.875in} -% set both margins to 2.5 pc -\setlength{\oddsidemargin}{-0.1875in}% 1 - (8.5 - 6.875)/2 -\setlength{\evensidemargin}{-0.1875in} -\setlength{\marginparwidth}{0pc} -\setlength{\marginparsep}{0pc}% -\setlength{\topmargin}{0in} \setlength{\headheight}{0pt} -\setlength{\headsep}{0pt} -\setlength{\footskip}{37pt}% -%\setlength{\columnsep}{0.3125in} -%\setlength{\columnwidth}{3.28125in}% (6.875 - 0.3125)/2 = 3.28125in -\setlength{\parindent}{1pc} -\newcommand{\myMargin}{1.00in} -\usepackage[top=\myMargin, left=\myMargin, right=\myMargin, bottom=\myMargin, nohead]{geometry} -\usepackage{epsfig,graphicx} -\usepackage{palatino} -\usepackage{fancybox} -\usepackage{hyperref} -\usepackage[procnames]{listings} - -\input{../style/scala.tex} - -\lstset{basicstyle={\footnotesize\ttfamily}} - -\newenvironment{commentary} -{ \vspace{-0.1in} - \begin{quotation} - \noindent - \small \em - \rule{\linewidth}{1pt}\\ -} -{ - \end{quotation} -} - -\title{Getting Started: Tutorial 06 - Conditional Assignments and Memories} -\author{Jonathan Bachrach, Vincent Lee \\ -EECS Department, UC Berkeley\\ -{\tt \{jrb\}@eecs.berkeley.edu} -} -\date{\today} - -\newenvironment{example}{\VerbatimEnvironment\begin{footnotesize}\begin{Verbatim}}{\end{Verbatim}\end{footnotesize}} -\newcommand{\kode}[1]{\begin{footnotesize}{\tt #1}\end{footnotesize}} - -\def\code#1{{\tt #1}} - -\def\note#1{\noindent{\bf [Note: #1]}} -%\def\note#1{} - -\begin{document} -\maketitle{} - -\input{state-guts} - -\end{document} diff --git a/doc/getting-started/testing-guts.tex b/doc/getting-started/testing-guts.tex deleted file mode 100644 index e2ca42ec..00000000 --- a/doc/getting-started/testing-guts.tex +++ /dev/null @@ -1,179 +0,0 @@ -\section{The Scala Testbench Simulation} - -Chisel's Scala based testbench is the first line of defense against simple bugs in your design. The Scala testbench uses several unique Chisel constructs to perform this. To see how this works, let's first explore a simple example. - -\subsection{Scala Testbench Example} - -Below is the \verb+ByteSelector.scala+ module definition from the previous tutorial and the corresponding Chisel test harness. - -\begin{scala} -package TutorialExamples - -import Chisel._ - -class ByteSelector extends Module { - val io = new Bundle { - val in = UInt(INPUT, 32) - val offset = UInt(INPUT, 2) - val out = UInt(OUTPUT, 8) - } - io.out := UInt(0, width = 8) - when (io.offset === UInt(0)) { - io.out := io.in(7,0) - } .elsewhen (io.offset === UInt(1)) { - io.out := io.in(15,8) - } .elsewhen (io.offset === UInt(2)) { - io.out := io.in(23,16) - } .otherwise { - io.out := io.in(31,24) - } -} - -class ByteSelectorTests(c: ByteSelector) - extends Tester(c) { - val test_in = 12345678 - for (t <- 0 until 4) { - poke(c.io.in, test_in) - poke(c.io.offset, t) - step(1) - expect(c.io.out, (test_in >> (t * 8)) & 0xFF) - } -} -\end{scala} - -In the test harness \verb+ByteSelectorTests+ we see that the test portion is written in Scala with some Chisel constructs inside a \verb+Tester+ class definition. The device under test is passed to us as a parameter \verb+c+. - -In the \verb+for+ loop, the assignments for each input of the \verb+ByteSelector+ is set to the appropriate values using \verb+poke+. For this particular example, we are testing the \verb+ByteSelector+ by hardcoding the input to some known value and checking if each of the 4 offsets returns the appropriate byte. To do this, on each iteration we generate appropriate inputs to the module and tell the simulation to assign this value to the input of the device we are testing \verb+c+: - -\begin{scala} -val test_in = 12345678 -for (t <- 0 until 4) { - // set in of the DUT to be some known word - poke(c.io.in, test_in) - // set the offset of the DUT - poke(c.io.offset, t) - ... -} -\end{scala} - -Next we step the circuit. We next advance the simulation by calling the \verb+step+ function. This effectively advances the simulation one clock cycle in the presence of sequential logic. - -\begin{scala} -step(1) -\end{scala} - -Finally, we check for expected outputs. -In this case, we check the expected output of \verb+ByteSelector+ as follows: - -\begin{scala} -expect(c.io.out, (test_in >> (t * 8)) & 0xFF) -\end{scala} - -This defines the reference output expected for this particular cycle of the simulation. Since the circuit we are testing is purely combinational, we expected that the output we define appears on any advancement of the simulation. The \verb+expect+ function will record either true or false after checking if the output generates the expected reference output. The results of successive \verb+expect+'s are anded into a \verb+Tester+ field called \verb+ok+ which starts out as \verb+true+. The value of the \verb+ok+ field determines the success or failure of the tester execution. - -Actually \verb+expect+ is defined in terms of \verb+peek+ roughly as follows: - -\begin{scala} -def expect (data: Bits, expected: BigInt) = - ok = peek(data) == expected && ok -\end{scala} - -where \verb+peek+ gets the value of a signal from the DUT. - -\subsection{Simulation Debug Output} - -Now suppose we run the testbench for the \verb+ByteSelector+ defined previously. To do this, \verb+cd+ into the \verb+$DIR/problems+ directory and run \verb+make ByteSelector+. - -When we run the testbench, we will notice that the simulation produces debug output every time the \verb+step+ function is called. Each of these calls gives the state of the inputs and outputs to the \verb+ByteSelector+ and whether the check between the reference output and expected output matched as shown below: - -\begin{bash} -STARTING ../emulator/problems/ByteSelector ---- -POKE ByteSelector__io_in <- 12345678 -POKE ByteSelector__io_offset <- 0 -STEP 1 <- 0 -PEEK ByteSelector__io_out -> 0x4e -EXPECT ByteSelector__io_out <- 78 == 78 PASS -POKE ByteSelector__io_in <- 12345678 -POKE ByteSelector__io_offset <- 1 -STEP 1 <- 0 -PEEK ByteSelector__io_out -> 0x61 -EXPECT ByteSelector__io_out <- 97 == 97 PASS -... -POKE ByteSelector__io_in <- 12345678 -POKE ByteSelector__io_offset <- 3 -STEP 1 <- 0 -PEEK ByteSelector__io_out -> 0x00 -EXPECT ByteSelector__io_out <- 0 == 0 PASS -PASSED // Final pass assertion -[success] Total time: 6 s, completed Feb 23, 2014 9:52:22 PM -\end{bash} - -Also notice that there is a final pass assertion "PASSED" at the end which corresponds to the \verb+allGood+ at the very end of the testbench. In this case, we know that the test passed since the allGood assertion resulted in a "PASSED". In the event of a failure, the assertion would result in a "FAILED" output message here. - -\subsection{General Testbench} - -In general, the scala testbench should have the following rough structure: - -\begin{itemize} -\item Set inputs using \verb+poke+ -\item Advance simulation using \verb+step+ -\item Check expected values using \verb+expect+ (and/or \verb+peek+) -\item Repeat until all appropriate test cases verified -\end{itemize} - -For sequential modules we may want to delay the output definition to the appropriate time as the \verb+step+ function implicitly advances the clock one period in the simulation. Unlike Verilog, you do not need to explicitly specify the timing advances of the simulation; Chisel will take care of these details for you. - -\section{\problem{Max2 Testbench}} - -In this assignment, write a tester for the \verb+Max2+ circuit: - -\begin{scala} -class Max2 extends Module { - val io = new Bundle { - val in0 = UInt(INPUT, 8) - val in1 = UInt(INPUT, 8) - val out = UInt(OUTPUT, 8) - } - io.out := Mux(io.in0 > io.in0, io.in0, io.in1) -} -\end{scala} - -\noindent -found in \verb+$TUT_DIR/problems/Max2.scala+ by filling in the following tester: - -\begin{scala} -class Max2Tests(c: Max2) extends Tester(c) { - for (i <- 0 until 10) { - // FILL THIS IN HERE - poke(c.io.in0, 0) - poke(c.io.in1, 0) - // FILL THIS IN HERE - step(1) - expect(c.io.out, 1) - } -} -\end{scala} - -\noindent -using random integers generated as follows: - -\begin{scala} -// returns random int in 0..lim-1 -val in0 = rnd.nextInt(lim) -\end{scala} - -\noindent -Run - -\begin{bash} -make Max2.out -\end{bash} - -\noindent -until the circuit passes your tests. - -\section{Limitations of the Testbench} - -The Chisel testbench works well for simple tests and small numbers of simulation iterations. However, for larger test cases, the Chisel testbench quickly becomes more complicated and slower simply due to the inefficiency of the infrastructure. For these larger and more complex test cases, we recommend using the C++ emulator or Verilog test harnesses which run faster and can handle more rigorous test cases. - diff --git a/doc/getting-started/testing.tex b/doc/getting-started/testing.tex deleted file mode 100644 index 3c068cd9..00000000 --- a/doc/getting-started/testing.tex +++ /dev/null @@ -1,58 +0,0 @@ -\documentclass[twocolumn, 10pt]{article} -\setlength\textwidth{6.875in} -\setlength\textheight{8.875in} -% set both margins to 2.5 pc -\setlength{\oddsidemargin}{-0.1875in}% 1 - (8.5 - 6.875)/2 -\setlength{\evensidemargin}{-0.1875in} -\setlength{\marginparwidth}{0pc} -\setlength{\marginparsep}{0pc}% -\setlength{\topmargin}{0in} \setlength{\headheight}{0pt} -\setlength{\headsep}{0pt} -\setlength{\footskip}{37pt}% -%\setlength{\columnsep}{0.3125in} -%\setlength{\columnwidth}{3.28125in}% (6.875 - 0.3125)/2 = 3.28125in -\setlength{\parindent}{1pc} -\newcommand{\myMargin}{1.00in} -\usepackage[top=\myMargin, left=\myMargin, right=\myMargin, bottom=\myMargin, nohead]{geometry} -\usepackage{epsfig,graphicx} -\usepackage{palatino} -\usepackage{fancybox} -\usepackage{hyperref} -\usepackage[procnames]{listings} - -\input{../style/scala.tex} - -\lstset{basicstyle={\footnotesize\ttfamily}} - -\newenvironment{commentary} -{ \vspace{-0.1in} - \begin{quotation} - \noindent - \small \em - \rule{\linewidth}{1pt}\\ -} -{ - \end{quotation} -} - -\title{Getting Started - Tutorial 04: Writing Scala Testbenches} -\author{Jonathan Bachrach, Vincent Lee \\ -EECS Department, UC Berkeley\\ -{\tt \{jrb\}@eecs.berkeley.edu} -} -\date{\today} - -\newenvironment{example}{\VerbatimEnvironment\begin{footnotesize}\begin{Verbatim}}{\end{Verbatim}\end{footnotesize}} -\newcommand{\kode}[1]{\begin{footnotesize}{\tt #1}\end{footnotesize}} - -\def\code#1{{\tt #1}} - -\def\note#1{\noindent{\bf [Note: #1]}} -%\def\note#1{} - -\begin{document} -\maketitle{} - -\input{testing-guts} - -\end{document} diff --git a/doc/html.cfg b/doc/html.cfg deleted file mode 100644 index 6951fdef..00000000 --- a/doc/html.cfg +++ /dev/null @@ -1,9 +0,0 @@ -\Preamble{xhtml} - \Configure{graphics*} - {pdf} - {\Needs{"convert \csname Gin@base\endcsname.pdf - \csname Gin@base\endcsname.png"}% - \Picture[pict]{\csname Gin@base\endcsname.png}% - } -\begin{document} -\EndPreamble diff --git a/doc/installation/installation.tex b/doc/installation/installation.tex deleted file mode 100644 index f244bf1e..00000000 --- a/doc/installation/installation.tex +++ /dev/null @@ -1,301 +0,0 @@ -\documentclass[twocolumn, 10pt]{article} -\setlength\textwidth{6.875in} -\setlength\textheight{8.875in} -% set both margins to 2.5 pc -\setlength{\oddsidemargin}{-0.1875in}% 1 - (8.5 - 6.875)/2 -\setlength{\evensidemargin}{-0.1875in} -\setlength{\marginparwidth}{0pc} -\setlength{\marginparsep}{0pc}% -\setlength{\topmargin}{0in} \setlength{\headheight}{0pt} -\setlength{\headsep}{0pt} -\setlength{\footskip}{37pt}% -%\setlength{\columnsep}{0.3125in} -%\setlength{\columnwidth}{3.28125in}% (6.875 - 0.3125)/2 = 3.28125in -\setlength{\parindent}{1pc} -\newcommand{\myMargin}{1.00in} -\usepackage[top=\myMargin, left=\myMargin, right=\myMargin, bottom=\myMargin, nohead]{geometry} -\usepackage{epsfig,graphicx} -\usepackage{palatino} -\usepackage{fancybox} -\usepackage{hyperref} -\usepackage[procnames]{listings} - -\input{../style/scala.tex} - -\lstset{basicstyle={\footnotesize\ttfamily}} - -\newenvironment{commentary} -{ \vspace{-0.1in} - \begin{quotation} - \noindent - \small \em - \rule{\linewidth}{1pt}\\ -} -{ - \end{quotation} -} - -% \newenvironment{kode}% -% {\footnotesize -% %\setlength{\parskip}{0pt} -% %\setlength{\topsep}{0pt} -% %\setlength{\partopsep}{0pt} -% \verbatim} -% {\endverbatim -% %\vspace*{-0.1in} -% } - -% \newenvironment{kode}% -% {\VerbatimEnvironment -% \footnotesize\begin{Sbox}\begin{minipage}{6in}\begin{Verbatim}}% -% {\end{Verbatim}\end{minipage}\end{Sbox} -% \setlength{\fboxsep}{8pt}\fbox{\TheSbox}} - -% \newenvironment{kode} -% {\begin{Sbox} -% \footnotesize -% \begin{minipage}{6in} -% %\setlength{\parskip}{0pt} -% %\setlength{\topsep}{0pt} -% %\setlength{\partopsep}{0pt} -% \verbatim} -% {\endverbatim -% \end{minipage} -% \end{Sbox} -% \fbox{\TheSbox} -% %\vspace*{-0.1in} -% } - -\title{Chisel Installation} -\author{Jonathan Bachrach \\ -EECS Department, UC Berkeley\\ -{\tt \{jrb\}@eecs.berkeley.edu} -} -\date{\today} - -\newenvironment{example}{\VerbatimEnvironment\begin{footnotesize}\begin{Verbatim}}{\end{Verbatim}\end{footnotesize}} -\newcommand{\kode}[1]{\begin{footnotesize}{\tt #1}\end{footnotesize}} - -\def\code#1{{\tt #1}} - -\def\note#1{\noindent{\bf [Note: #1]}} -%\def\note#1{} - -\begin{document} -\maketitle{} - -\section{Introduction} - -This document is an installation guide for {\em Chisel} (Constructing -Hardware In a Scala Embedded Language). Chisel is a hardware -construction language embedded in the high-level programming language -Scala. - -\subsection{Github} - -\begin{itemize} -\item Get an account on \verb|www.github.com| -\item Register your public key on \verb|github.com| -\end{itemize} - -\subsection{Development Tool Installation} - -\subsubsection{MacOSX} - -\begin{enumerate} -\item Install XCODE including console tools. -\item Install MacPorts from \url{http://www.macports.org} -\end{enumerate} - -\noindent -From there install the following MacPorts packages: - -\begin{enumerate} -\item \verb+git+ -\item \verb+openjdk6+ -\end{enumerate} - -\noindent -using - -\begin{bash} -sudo port install -\end{bash} - -\subsubsection{Linux} - -To install Chisel on Linux, install the following packages: - -\begin{enumerate} -\item \verb+git+ -\item \verb|g++| -\item \verb+openjdk-7-jre+ -\item \verb+openjdk-7-jdk+ -\end{enumerate} - -\noindent -using - -\begin{bash} -sudo apt-get install -\end{bash} - -% To install Chisel on Linux, download and run the \verb|install| script -% provided on the website. Note: python must be installed for -% this script to work. The script does the following: -% \begin{enumerate} -% \item installs \verb|g++| if necessary -% \item installs Java runtime and compiler if necessary -% \item installs \verb+git+ if necessary -% \item prompts for a location to install Chisel (needs an absolute path)\label{step:chiseldir} -% \item clones Chisel into the location provided by Step~\ref{step:chiseldir} -% \end{enumerate} -% -% After running the installation script, you need to set the CHISEL -% environment variable in your bashrc file to point to where you -% installed Chisel in Step~\ref{step:chiseldir}. -% -% \subsection{Verify} -% To verify that everything has been configured correctly, download -% run the \verb|verify| script provided on teh website. The -% script will run the compiler on simple use case. If everything -% goes correctly, you should find the following files in -% $CHISEL/emulator: -% \begin{itemize} -% \item GCD-emulator.cpp -% \item GCD-makefile -% \item GCD.h -% \item GCD.cpp -% \end{itemize} - -\section{Setting Up Tutorial} - -\verb+cd+ above directory = \verb+$DIR+ you've chosen to place Chisel tutorial and type: - -\begin{bash} -cd $DIR -git clone https://github.com/ucb-bar/chisel-tutorial.git -\end{bash} - -\noindent -Your copy of the Chisel Tutorial repository will then be in \verb+$DIR/chisel-tutorial+. Define this as a variable in your bash environment: - -The following is the Chisel tutorial directory structure: - -\begin{bash} -chisel-tutorial/ - src/ - problems/ - Accumulator.scala ... - solutions/ - Accumulator.scala ... - emulator/ - problems/ - Makefile - solutions/ - Makefile - verilog/ - problems/ - Makefile - solutions/ - Makefile - sbt/ - project/ - build.scala -\end{bash} - -\noindent -The tutorial is split into problems and solutions, where the problems have some piece of the design to be filled in by the user and where the solutions are meant to be complete designs that should pass the given tests. In order to run either, you change directory into the appropriate subdirectory and type make of the particular lesson name: - -\begin{bash} -cd $CHISEL/tutorial/emulator/solutions -make GCD -\end{bash} - -\noindent -or you can run all tests using - -\begin{bash} -cd $CHISEL/tutorial/emulator/solutions -make all -\end{bash} - -\noindent -and the output should show that all tests have passed. - -In order to produce Verilog, just do the following: - -\begin{bash} -cd $CHISEL/tutorial/verilog/solutions -make all -\end{bash} - -\section{Creating Your Own Projects} - -SBT has a particular directory structure that we adhere to and -somewhat improve. Assuming that we have a project named {\em gpu}, -then the following would be the directory structure template: - -\begin{bash} -gpu/ - sbt/ - project/ - build.scala # edit this as shown below - src/ - gpu.scala # your source files go here - emulator/ # your C++ target can go here - verilog/ # your Verilog target can go here -\end{bash} - -\noindent -and the following is the \verb+build.scala+ template: - -\begin{scala} -import sbt._ -import Keys._ - -object BuildSettings { - val buildOrganization = "edu.berkeley.cs" - val buildVersion = "1.1" - val buildScalaVersion = "2.10.4" - - def apply(projectdir: String) = { - Defaults.defaultSettings ++ Seq ( - organization := buildOrganization, - version := buildVersion, - scalaVersion := buildScalaVersion, - scalaSource in Compile := - Path.absolute(file(projectdir + "/src")) - libraryDependencies += - "edu.berkeley.cs" %% "chisel" % "latest.release" - ) - } -} - -object ChiselBuild extends Build { - import BuildSettings._ - lazy val gpu = - Project("gpu", file("gpu"), - settings = BuildSettings("..")) - dependsOn(chisel) -} -\end{scala} - -If you want to update your version of Chisel, all you have to do is -change the version number for Chisel. For instance, - -\begin{scala} -libraryDependencies += "edu.berkeley.cs" %% "chisel" % "1.0" -\end{scala} - -\noindent -is using release 1.0, and - -\begin{scala} -libraryDependencies += "edu.berkeley.cs" %% "chisel" % "1.0.1" -\end{scala} - -\noindent -is using release 1.0.1 - -\end{document} diff --git a/doc/manual/beramono.sty b/doc/manual/beramono.sty deleted file mode 100644 index fcbc324c..00000000 --- a/doc/manual/beramono.sty +++ /dev/null @@ -1,32 +0,0 @@ -\ProvidesPackage{beramono}[2004/01/31 (WaS)] -\RequirePackage{keyval} -\define@key{Fvm}{scaled}[.9]{% - \def\fvm@Scale{#1}} -\def\ProcessOptionsWithKV#1{% - \let\@tempc\relax - \let\Fvm@tempa\@empty - \@for\CurrentOption:=\@classoptionslist\do{% - \@ifundefined{KV@#1@\CurrentOption}% - {}% - {% - \edef\Fvm@tempa{\Fvm@tempa,\CurrentOption,}% - \@expandtwoargs\@removeelement\CurrentOption - \@unusedoptionlist\@unusedoptionlist - }% - }% - \edef\Fvm@tempa{% - \noexpand\setkeys{#1}{% - \Fvm@tempa\@ptionlist{\@currname.\@currext}% - }% - }% - \Fvm@tempa - \let\CurrentOption\@empty -} -\ProcessOptionsWithKV{Fvm} -\AtEndOfPackage{% - \let\@unprocessedoptions\relax -} -\renewcommand{\ttdefault}{fvm} -\endinput -%% -%% End of file `beramono.sty'. diff --git a/doc/manual/figs/bits-1.graffle b/doc/manual/figs/bits-1.graffle deleted file mode 100644 index 2c15dfc9..00000000 --- a/doc/manual/figs/bits-1.graffle +++ /dev/null @@ -1,352 +0,0 @@ - - - - - ActiveLayerIndex - 0 - ApplicationVersion - - com.omnigroup.OmniGrafflePro - 139.18.0.187838 - - AutoAdjust - - BackgroundGraphic - - Bounds - {{0, 0}, {577, 533}} - Class - SolidGraphic - ID - 2 - Style - - shadow - - Draws - NO - - stroke - - Draws - NO - - - - BaseZoom - 0 - CanvasOrigin - {0, 0} - CanvasSize - {577, 533} - ColumnAlign - 1 - ColumnSpacing - 36 - CreationDate - 2012-05-16 00:15:06 +0000 - Creator - Jonathan Bachrach - DisplayScale - 1 0/72 in = 1.0000 in - FileType - flat - GraphDocumentVersion - 8 - GraphicsList - - - Bounds - {{252, 384.99200000000002}, {72, 45}} - Class - ShapedGraphic - FontInfo - - Color - - w - 0 - - Font - Helvetica - NSKern - 0.0 - Size - 12 - - ID - 1168 - Shape - Rectangle - Style - - fill - - FillType - 2 - GradientAngle - 90 - GradientColor - - w - 0.666667 - - - - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf390 -\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc - -\f0\fs24 \cf0 \expnd0\expndtw0\kerning0 -Lit(1)} - VerticalPad - 0 - - - - Bounds - {{252, 302.99200000000002}, {72, 45}} - Class - ShapedGraphic - FontInfo - - Color - - w - 0 - - Font - Helvetica - NSKern - 0.0 - Size - 12 - - ID - 1167 - Shape - Rectangle - Style - - fill - - FillType - 2 - GradientAngle - 90 - GradientColor - - w - 0.666667 - - - - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf390 -\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc - -\f0\fs24 \cf0 \expnd0\expndtw0\kerning0 -UInt} - VerticalPad - 0 - - - - Class - LineGraphic - Head - - ID - 1168 - - ID - 1169 - Points - - {288, 348.49200000000002} - {288, 384.49200000000002} - - Style - - stroke - - HeadArrow - 0 - Legacy - - TailArrow - 0 - - - Tail - - ID - 1167 - - - - GridInfo - - GuidesLocked - NO - GuidesVisible - YES - HPages - 2 - ImageCounter - 3 - KeepToScale - - Layers - - - Lock - NO - Name - Layer 1 - Print - YES - View - YES - - - LayoutInfo - - Animate - NO - AutoLayout - 2 - LineLength - 0.4643835723400116 - circoMinDist - 18 - circoSeparation - 0.0 - layoutEngine - dot - neatoSeparation - 0.0 - twopiSeparation - 0.0 - - LinksVisible - NO - MagnetsVisible - NO - MasterSheets - - ModificationDate - 2013-07-30 21:15:05 +0000 - Modifier - Jonathan Bachrach - NotesVisible - NO - Orientation - 2 - OriginVisible - NO - OutlineStyle - Basic - PageBreaks - NO - PrintInfo - - NSBottomMargin - - float - 41 - - NSHorizonalPagination - - coded - BAtzdHJlYW10eXBlZIHoA4QBQISEhAhOU051bWJlcgCEhAdOU1ZhbHVlAISECE5TT2JqZWN0AIWEASqEhAFxlwCG - - NSLeftMargin - - float - 18 - - NSPaperSize - - size - {611.99999713897705, 792} - - NSPrintReverseOrientation - - int - 0 - - NSRightMargin - - float - 18 - - NSTopMargin - - float - 18 - - - PrintOnePage - - ReadOnly - NO - RowAlign - 1 - RowSpacing - 36 - SheetTitle - Canvas 1 - SmartAlignmentGuidesActive - YES - SmartDistanceGuidesActive - YES - UniqueID - 1 - UseEntirePage - - VPages - 1 - WindowInfo - - CurrentSheet - 0 - ExpandedCanvases - - FitInWindow - - Frame - {{301, 627}, {717, 626}} - ListView - - OutlineWidth - 142 - RightSidebar - - Sidebar - - SidebarWidth - 138 - VisibleRegion - {{1, 1}, {575, 532}} - Zoom - 1 - ZoomValues - - - Canvas 1 - 0.0 - 1 - - - - - diff --git a/doc/manual/figs/bits-1.pdf b/doc/manual/figs/bits-1.pdf deleted file mode 100644 index b6f74503..00000000 Binary files a/doc/manual/figs/bits-1.pdf and /dev/null differ diff --git a/doc/manual/figs/bits-and.graffle b/doc/manual/figs/bits-and.graffle deleted file mode 100644 index 6949936f..00000000 --- a/doc/manual/figs/bits-and.graffle +++ /dev/null @@ -1,614 +0,0 @@ - - - - - ActiveLayerIndex - 0 - ApplicationVersion - - com.omnigroup.OmniGrafflePro - 139.18.0.187838 - - AutoAdjust - - BackgroundGraphic - - Bounds - {{0, 0}, {632.2101313320826, 584}} - Class - SolidGraphic - ID - 2 - Style - - shadow - - Draws - NO - - stroke - - Draws - NO - - - - BaseZoom - 0 - CanvasOrigin - {0, 0} - CanvasSize - {632.2101313320826, 584} - ColumnAlign - 1 - ColumnSpacing - 36 - CreationDate - 2012-05-15 18:24:36 +0000 - Creator - Jonathan Bachrach - DisplayScale - 1 0/72 in = 1.0000 in - FileType - flat - GraphDocumentVersion - 8 - GraphicsList - - - Bounds - {{297, 466.98399999999998}, {72, 45}} - Class - ShapedGraphic - FontInfo - - Color - - w - 0 - - Font - Helvetica - NSKern - 0.0 - Size - 12 - - ID - 1174 - Shape - Rectangle - Style - - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf390 -\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc - -\f0\fs24 \cf0 \expnd0\expndtw0\kerning0 -Lit(2)} - VerticalPad - 0 - - - - Bounds - {{297, 384.98399999999998}, {72, 45}} - Class - ShapedGraphic - FontInfo - - Color - - w - 0 - - Font - Helvetica - NSKern - 0.0 - Size - 12 - - ID - 1165 - Shape - Rectangle - Style - - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf390 -\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc - -\f0\fs24 \cf0 \expnd0\expndtw0\kerning0 -UInt} - VerticalPad - 0 - - - - Bounds - {{207, 466.98399999999998}, {72, 45}} - Class - ShapedGraphic - FontInfo - - Color - - w - 0 - - Font - Helvetica - NSKern - 0.0 - Size - 12 - - ID - 1166 - Shape - Rectangle - Style - - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf390 -\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc - -\f0\fs24 \cf0 \expnd0\expndtw0\kerning0 -Lit(1)} - VerticalPad - 0 - - - - Bounds - {{207, 384.98399999999998}, {72, 45}} - Class - ShapedGraphic - FontInfo - - Color - - w - 0 - - Font - Helvetica - NSKern - 0.0 - Size - 12 - - ID - 1163 - Shape - Rectangle - Style - - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf390 -\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc - -\f0\fs24 \cf0 \expnd0\expndtw0\kerning0 -UInt} - VerticalPad - 0 - - - - Bounds - {{252, 302.98399999999998}, {72, 45}} - Class - ShapedGraphic - FontInfo - - Color - - w - 0 - - Font - Helvetica - NSKern - 0.0 - Size - 12 - - ID - 1168 - Shape - Rectangle - Style - - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf390 -\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc - -\f0\fs24 \cf0 \expnd0\expndtw0\kerning0 -Op(&)} - VerticalPad - 0 - - - - Bounds - {{252, 220.98400000000001}, {72, 45}} - Class - ShapedGraphic - FontInfo - - Color - - w - 0 - - Font - Helvetica - NSKern - 0.0 - Size - 12 - - ID - 1167 - Shape - Rectangle - Style - - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf390 -\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc - -\f0\fs24 \cf0 \expnd0\expndtw0\kerning0 -UInt} - VerticalPad - 0 - - - - Class - LineGraphic - Head - - ID - 1168 - - ID - 1169 - Points - - {288, 266.48400000000004} - {288, 302.48399999999998} - - Style - - stroke - - HeadArrow - 0 - Legacy - - TailArrow - 0 - - - Tail - - ID - 1167 - - - - Class - LineGraphic - Head - - ID - 1163 - - ID - 1170 - Points - - {275.41183610528583, 348.4223330470258} - {255.58797066071944, 384.54566538128557} - - Style - - stroke - - HeadArrow - 0 - Legacy - - TailArrow - 0 - - - Tail - - ID - 1168 - - - - Class - LineGraphic - Head - - ID - 1165 - - ID - 1171 - Points - - {300.58816389471417, 348.4223330470258} - {320.41202933928059, 384.54566538128557} - - Style - - stroke - - HeadArrow - 0 - Legacy - - TailArrow - 0 - - - Tail - - ID - 1168 - - - - Class - LineGraphic - Head - - ID - 1166 - - ID - 1172 - Points - - {243, 430.48399999999998} - {243, 466.48399999999998} - - Style - - stroke - - HeadArrow - 0 - Legacy - - TailArrow - 0 - - - Tail - - ID - 1163 - - - - Class - LineGraphic - Head - - ID - 1174 - - ID - 1173 - Points - - {333, 430.48399999999998} - {333, 466.48399999999998} - - Style - - stroke - - HeadArrow - 0 - Legacy - - TailArrow - 0 - - - Tail - - ID - 1165 - - - - GridInfo - - GuidesLocked - NO - GuidesVisible - YES - HPages - 2 - ImageCounter - 3 - KeepToScale - - Layers - - - Lock - NO - Name - Layer 1 - Print - YES - View - YES - - - LayoutInfo - - Animate - NO - AutoLayout - 2 - LineLength - 0.4643835723400116 - circoMinDist - 18 - circoSeparation - 0.0 - layoutEngine - dot - neatoSeparation - 0.0 - twopiSeparation - 0.0 - - LinksVisible - NO - MagnetsVisible - NO - MasterSheets - - ModificationDate - 2013-07-30 21:15:32 +0000 - Modifier - Jonathan Bachrach - NotesVisible - NO - Orientation - 2 - OriginVisible - NO - OutlineStyle - Basic - PageBreaks - NO - PrintInfo - - NSBottomMargin - - float - 41 - - NSHorizonalPagination - - coded - BAtzdHJlYW10eXBlZIHoA4QBQISEhAhOU051bWJlcgCEhAdOU1ZhbHVlAISECE5TT2JqZWN0AIWEASqEhAFxlwCG - - NSLeftMargin - - float - 18 - - NSPaperSize - - size - {611.99999713897705, 792} - - NSPrintReverseOrientation - - int - 0 - - NSRightMargin - - float - 18 - - NSTopMargin - - float - 18 - - - PrintOnePage - - ReadOnly - NO - RowAlign - 1 - RowSpacing - 36 - SheetTitle - Canvas 1 - SmartAlignmentGuidesActive - YES - SmartDistanceGuidesActive - YES - UniqueID - 1 - UseEntirePage - - VPages - 1 - WindowInfo - - CurrentSheet - 0 - ExpandedCanvases - - FitInWindow - - Frame - {{1124, 376}, {717, 626}} - ListView - - OutlineWidth - 142 - RightSidebar - - Sidebar - - SidebarWidth - 138 - VisibleRegion - {{1.0970537062243479, 1.0970537062243479}, {630.80588107899996, 583.63257171135308}} - Zoom - 0.91153240203857422 - ZoomValues - - - Canvas 1 - 0.0 - 1 - - - - - diff --git a/doc/manual/figs/bits-and.pdf b/doc/manual/figs/bits-and.pdf deleted file mode 100644 index dfa7ffe9..00000000 Binary files a/doc/manual/figs/bits-and.pdf and /dev/null differ diff --git a/doc/manual/figs/bits-or-and.graffle b/doc/manual/figs/bits-or-and.graffle deleted file mode 100644 index 71446108..00000000 --- a/doc/manual/figs/bits-or-and.graffle +++ /dev/null @@ -1,1024 +0,0 @@ - - - - - ActiveLayerIndex - 0 - ApplicationVersion - - com.omnigroup.OmniGrafflePro - 139.18.0.187838 - - AutoAdjust - - BackgroundGraphic - - Bounds - {{0, 0}, {722.06191369606006, 667}} - Class - SolidGraphic - ID - 2 - Style - - shadow - - Draws - NO - - stroke - - Draws - NO - - - - BaseZoom - 0 - CanvasOrigin - {0, 0} - CanvasSize - {722.06191369606006, 667} - ColumnAlign - 1 - ColumnSpacing - 36 - CreationDate - 2012-05-15 18:25:38 +0000 - Creator - Jonathan Bachrach - DisplayScale - 1 0/72 in = 1.0000 in - FileType - flat - GraphDocumentVersion - 8 - GraphicsList - - - Bounds - {{274.5, 549.01199999999994}, {72, 45}} - Class - ShapedGraphic - FontInfo - - Color - - w - 0 - - Font - Helvetica - NSKern - 0.0 - Size - 12 - - ID - 1183 - Shape - Rectangle - Style - - fill - - FillType - 2 - GradientAngle - 90 - GradientColor - - w - 0.666667 - - MiddleColor - - b - 0.588235 - g - 0.917647 - r - 0.568627 - - TrippleBlend - YES - - - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf390 -\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc - -\f0\fs24 \cf0 \expnd0\expndtw0\kerning0 -Lit(2)} - VerticalPad - 0 - - - - Bounds - {{274.5, 467.012}, {72, 45}} - Class - ShapedGraphic - FontInfo - - Color - - w - 0 - - Font - Helvetica - NSKern - 0.0 - Size - 12 - - ID - 1166 - Shape - Rectangle - Style - - fill - - FillType - 2 - GradientAngle - 90 - GradientColor - - w - 0.666667 - - MiddleColor - - b - 0.588235 - g - 0.917647 - r - 0.568627 - - TrippleBlend - YES - - - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf390 -\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc - -\f0\fs24 \cf0 \expnd0\expndtw0\kerning0 -UInt} - VerticalPad - 0 - - - - Bounds - {{184.5, 549.01199999999994}, {72, 45}} - Class - ShapedGraphic - FontInfo - - Color - - w - 0 - - Font - Helvetica - NSKern - 0.0 - Size - 12 - - ID - 1181 - Shape - Rectangle - Style - - fill - - FillType - 2 - GradientAngle - 90 - GradientColor - - w - 0.666667 - - - - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf390 -\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc - -\f0\fs24 \cf0 \expnd0\expndtw0\kerning0 -Lit(1)} - VerticalPad - 0 - - - - Bounds - {{184.5, 467.012}, {72, 45}} - Class - ShapedGraphic - FontInfo - - Color - - w - 0 - - Font - Helvetica - NSKern - 0.0 - Size - 12 - - ID - 1163 - Shape - Rectangle - Style - - fill - - FillType - 2 - GradientAngle - 90 - GradientColor - - w - 0.666667 - - - - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf390 -\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc - -\f0\fs24 \cf0 \expnd0\expndtw0\kerning0 -UInt} - VerticalPad - 0 - - - - Bounds - {{229.5, 385.012}, {72, 45}} - Class - ShapedGraphic - FontInfo - - Color - - w - 0 - - Font - Helvetica - NSKern - 0.0 - Size - 12 - - ID - 1168 - Shape - Rectangle - Style - - fill - - FillType - 2 - GradientAngle - 90 - GradientColor - - w - 0.666667 - - MiddleColor - - b - 0.588235 - g - 0.917647 - r - 0.568627 - - TrippleBlend - YES - - - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf390 -\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc - -\f0\fs24 \cf0 \expnd0\expndtw0\kerning0 -Op(&)} - VerticalPad - 0 - - - - Bounds - {{319.5, 385.012}, {72, 45}} - Class - ShapedGraphic - FontInfo - - Color - - w - 0 - - Font - Helvetica - NSKern - 0.0 - Size - 12 - - ID - 1179 - Shape - Rectangle - Style - - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf390 -\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc - -\f0\fs24 \cf0 \expnd0\expndtw0\kerning0 -Lit(3)} - VerticalPad - 0 - - - - Bounds - {{319.5, 303.012}, {72, 45}} - Class - ShapedGraphic - FontInfo - - Color - - w - 0 - - Font - Helvetica - NSKern - 0.0 - Size - 12 - - ID - 1172 - Shape - Rectangle - Style - - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf390 -\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc - -\f0\fs24 \cf0 \expnd0\expndtw0\kerning0 -UInt} - VerticalPad - 0 - - - - Bounds - {{229.5, 303.012}, {72, 45}} - Class - ShapedGraphic - FontInfo - - Color - - w - 0 - - Font - Helvetica - NSKern - 0.0 - Size - 12 - - ID - 1167 - Shape - Rectangle - Style - - fill - - FillType - 2 - GradientAngle - 90 - GradientColor - - w - 0.666667 - - MiddleColor - - b - 0.588235 - g - 0.917647 - r - 0.568627 - - TrippleBlend - YES - - - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf390 -\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc - -\f0\fs24 \cf0 \expnd0\expndtw0\kerning0 -UInt} - VerticalPad - 0 - - - - Bounds - {{274.5, 221.012}, {72, 45}} - Class - ShapedGraphic - FontInfo - - Color - - w - 0 - - Font - Helvetica - NSKern - 0.0 - Size - 12 - - ID - 1173 - Shape - Rectangle - Style - - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf390 -\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc - -\f0\fs24 \cf0 \expnd0\expndtw0\kerning0 -Op(|)} - VerticalPad - 0 - - - - Bounds - {{274.5, 139.012}, {72, 45}} - Class - ShapedGraphic - FontInfo - - Color - - w - 0 - - Font - Helvetica - NSKern - 0.0 - Size - 12 - - ID - 1176 - Shape - Rectangle - Style - - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf390 -\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc - -\f0\fs24 \cf0 \expnd0\expndtw0\kerning0 -UInt} - VerticalPad - 0 - - - - Class - LineGraphic - Head - - ID - 1168 - - ID - 1169 - Points - - {265.5, 348.512} - {265.5, 384.512} - - Style - - stroke - - HeadArrow - 0 - Legacy - - TailArrow - 0 - - - Tail - - ID - 1167 - - - - Class - LineGraphic - Head - - ID - 1163 - - ID - 1170 - Points - - {252.91189443734092, 430.45033350292323} - {233.08812081774249, 466.57366662158393} - - Style - - stroke - - HeadArrow - 0 - Legacy - - TailArrow - 0 - - - Tail - - ID - 1168 - - - - Class - LineGraphic - Head - - ID - 1166 - - ID - 1171 - Points - - {278.08810556265905, 430.45033350292323} - {297.91187918225751, 466.57366662158393} - - Style - - stroke - - HeadArrow - 0 - Legacy - - TailArrow - 0 - - - Tail - - ID - 1168 - - - - Class - LineGraphic - Head - - ID - 1167 - - ID - 1174 - Points - - {297.91189443734095, 266.45033350292317} - {278.08812081774249, 302.57366662158393} - - Style - - stroke - - HeadArrow - 0 - Legacy - - TailArrow - 0 - - - Tail - - ID - 1173 - - - - Class - LineGraphic - Head - - ID - 1172 - - ID - 1175 - Points - - {323.08810556265905, 266.45033350292317} - {342.91187918225751, 302.57366662158393} - - Style - - stroke - - HeadArrow - 0 - Legacy - - TailArrow - 0 - - - Tail - - ID - 1173 - - - - Class - LineGraphic - Head - - ID - 1173 - - ID - 1177 - Points - - {310.5, 184.512} - {310.5, 220.512} - - Style - - stroke - - HeadArrow - 0 - Legacy - - TailArrow - 0 - - - Tail - - ID - 1176 - - - - Class - LineGraphic - Head - - ID - 1179 - - ID - 1178 - Points - - {355.5, 348.512} - {355.5, 384.512} - - Style - - stroke - - HeadArrow - 0 - Legacy - - TailArrow - 0 - - - Tail - - ID - 1172 - - - - Class - LineGraphic - Head - - ID - 1181 - - ID - 1180 - Points - - {220.5, 512.51199999999994} - {220.5, 548.51199999999994} - - Style - - stroke - - HeadArrow - 0 - Legacy - - TailArrow - 0 - - - Tail - - ID - 1163 - - - - Class - LineGraphic - Head - - ID - 1183 - - ID - 1182 - Points - - {310.5, 512.51199999999994} - {310.5, 548.51199999999994} - - Style - - stroke - - HeadArrow - 0 - Legacy - - TailArrow - 0 - - - Tail - - ID - 1166 - - - - GridInfo - - GuidesLocked - NO - GuidesVisible - YES - HPages - 2 - ImageCounter - 3 - KeepToScale - - Layers - - - Lock - NO - Name - Layer 1 - Print - YES - View - YES - - - LayoutInfo - - Animate - NO - AutoLayout - 2 - LineLength - 0.4643835723400116 - circoMinDist - 18 - circoSeparation - 0.0 - layoutEngine - dot - neatoSeparation - 0.0 - twopiSeparation - 0.0 - - LinksVisible - NO - MagnetsVisible - NO - MasterSheets - - ModificationDate - 2013-07-30 21:14:33 +0000 - Modifier - Jonathan Bachrach - NotesVisible - NO - Orientation - 2 - OriginVisible - NO - OutlineStyle - Basic - PageBreaks - NO - PrintInfo - - NSBottomMargin - - float - 41 - - NSHorizonalPagination - - coded - BAtzdHJlYW10eXBlZIHoA4QBQISEhAhOU051bWJlcgCEhAdOU1ZhbHVlAISECE5TT2JqZWN0AIWEASqEhAFxlwCG - - NSLeftMargin - - float - 18 - - NSPaperSize - - size - {611.99999713897705, 792} - - NSPrintReverseOrientation - - int - 0 - - NSRightMargin - - float - 18 - - NSTopMargin - - float - 18 - - - PrintOnePage - - ReadOnly - NO - RowAlign - 1 - RowSpacing - 36 - SheetTitle - Canvas 1 - SmartAlignmentGuidesActive - YES - SmartDistanceGuidesActive - YES - UniqueID - 1 - UseEntirePage - - VPages - 1 - WindowInfo - - CurrentSheet - 0 - ExpandedCanvases - - FitInWindow - - Frame - {{301, 478}, {717, 626}} - ListView - - OutlineWidth - 142 - RightSidebar - - Sidebar - - SidebarWidth - 138 - VisibleRegion - {{1.2530329100446431, 1.2530329100446431}, {720.49392327566977, 666.6135081437501}} - Zoom - 0.79806363582611084 - ZoomValues - - - Canvas 1 - 0.0 - 1 - - - - - diff --git a/doc/manual/figs/bits-or-and.pdf b/doc/manual/figs/bits-or-and.pdf deleted file mode 100644 index 218a978d..00000000 Binary files a/doc/manual/figs/bits-or-and.pdf and /dev/null differ diff --git a/doc/manual/figs/node-hierarchy.graffle b/doc/manual/figs/node-hierarchy.graffle deleted file mode 100644 index b8258372..00000000 --- a/doc/manual/figs/node-hierarchy.graffle +++ /dev/null @@ -1,926 +0,0 @@ - - - - - ActiveLayerIndex - 0 - ApplicationVersion - - com.omnigroup.OmniGrafflePro - 138.33.0.157554 - - AutoAdjust - - BackgroundGraphic - - Bounds - {{0, 0}, {604.847, 543}} - Class - SolidGraphic - ID - 2 - Style - - shadow - - Draws - NO - - stroke - - Draws - NO - - - - CanvasOrigin - {0, 0} - CanvasSize - {604.847, 543} - ColumnAlign - 1 - ColumnSpacing - 36 - CreationDate - 2012-05-15 10:53:49 -0700 - Creator - Jonathan Bachrach - DisplayScale - 1 0/72 in = 1.0000 in - FileType - flat - GraphDocumentVersion - 8 - GraphicsList - - - Bounds - {{387, 425.988}, {72, 45}} - Class - ShapedGraphic - FontInfo - - Color - - w - 0 - - Font - Helvetica - NSKern - 0.0 - Size - 12 - - ID - 1163 - Shape - Rectangle - Style - - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1038\cocoasubrtf360 -{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc - -\f0\fs24 \cf0 \expnd0\expndtw0\kerning0 -Mem} - VerticalPad - 0 - - - - Bounds - {{297, 425.988}, {72, 45}} - Class - ShapedGraphic - FontInfo - - Color - - w - 0 - - Font - Helvetica - NSKern - 0.0 - Size - 12 - - ID - 1169 - Shape - Rectangle - Style - - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1038\cocoasubrtf360 -{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc - -\f0\fs24 \cf0 \expnd0\expndtw0\kerning0 -Reg} - VerticalPad - 0 - - - - Bounds - {{207, 425.988}, {72, 45}} - Class - ShapedGraphic - FontInfo - - Color - - w - 0 - - Font - Helvetica - NSKern - 0.0 - Size - 12 - - ID - 1192 - Shape - Rectangle - Style - - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1038\cocoasubrtf360 -{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc - -\f0\fs24 \cf0 \expnd0\expndtw0\kerning0 -Data} - VerticalPad - 0 - - - - Bounds - {{207, 343.988}, {72, 45}} - Class - ShapedGraphic - FontInfo - - Color - - w - 0 - - Font - Helvetica - NSKern - 0.0 - Size - 12 - - ID - 1168 - Shape - Rectangle - Style - - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1038\cocoasubrtf360 -{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc - -\f0\fs24 \cf0 \expnd0\expndtw0\kerning0 -Op} - VerticalPad - 0 - - - - Bounds - {{117, 343.988}, {72, 45}} - Class - ShapedGraphic - FontInfo - - Color - - w - 0 - - Font - Helvetica - NSKern - 0.0 - Size - 12 - - ID - 1183 - Shape - Rectangle - Style - - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1038\cocoasubrtf360 -{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc - -\f0\fs24 \cf0 \expnd0\expndtw0\kerning0 -Lit} - VerticalPad - 0 - - - - Bounds - {{297, 343.988}, {72, 45}} - Class - ShapedGraphic - FontInfo - - Color - - w - 0 - - Font - Helvetica - NSKern - 0.0 - Size - 12 - - ID - 1166 - Shape - Rectangle - Style - - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1038\cocoasubrtf360 -{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc - -\f0\fs24 \cf0 \expnd0\expndtw0\kerning0 -Updateable} - VerticalPad - 0 - - - - Bounds - {{207, 261.988}, {72, 45}} - Class - ShapedGraphic - FontInfo - - Color - - w - 0 - - Font - Helvetica - NSKern - 0.0 - Size - 12 - - ID - 1167 - Shape - Rectangle - Style - - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1038\cocoasubrtf360 -{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc - -\f0\fs24 \cf0 \expnd0\expndtw0\kerning0 -Node} - VerticalPad - 0 - - - - Class - LineGraphic - Head - - ID - 1168 - - ID - 1170 - Points - - {243, 307.488} - {243, 343.488} - - Style - - stroke - - HeadArrow - 0 - TailArrow - 0 - - - Tail - - ID - 1167 - - - - Class - LineGraphic - Head - - ID - 1183 - - ID - 1182 - Points - - {217.935, 307.325} - {178.065, 343.651} - - Style - - stroke - - HeadArrow - 0 - TailArrow - 0 - - - Tail - - ID - 1167 - - - - Class - LineGraphic - Head - - ID - 1192 - - ID - 1193 - Points - - {307.935, 389.325} - {268.065, 425.651} - - Style - - stroke - - HeadArrow - 0 - TailArrow - 0 - - - Tail - - ID - 1166 - - - - Class - LineGraphic - Head - - ID - 1169 - - ID - 1194 - Points - - {333, 389.488} - {333, 425.488} - - Style - - stroke - - HeadArrow - 0 - TailArrow - 0 - - - Tail - - ID - 1166 - - - - Class - LineGraphic - Head - - ID - 1163 - - ID - 1195 - Points - - {358.065, 389.325} - {397.935, 425.651} - - Style - - stroke - - HeadArrow - 0 - TailArrow - 0 - - - Tail - - ID - 1166 - - - - Class - LineGraphic - Head - - ID - 1166 - - ID - 1197 - Points - - {268.065, 307.325} - {307.935, 343.651} - - Style - - stroke - - HeadArrow - 0 - TailArrow - 0 - - - Tail - - ID - 1167 - - - - GridInfo - - GuidesLocked - NO - GuidesVisible - YES - HPages - 2 - ImageCounter - 3 - KeepToScale - - Layers - - - Lock - NO - Name - Layer 1 - Print - YES - View - YES - - - LayoutInfo - - Animate - NO - AutoLayout - 2 - LineLength - 0.4643835723400116 - circoMinDist - 18 - circoSeparation - 0.0 - layoutEngine - dot - neatoSeparation - 0.0 - twopiSeparation - 0.0 - - LinksVisible - NO - MagnetsVisible - NO - MasterSheets - - ModificationDate - 2012-05-22 23:15:43 -0700 - Modifier - Jonathan Bachrach - NotesVisible - NO - Orientation - 2 - OriginVisible - NO - OutlineStyle - Basic - PageBreaks - NO - PrintInfo - - NSBottomMargin - - float - 41 - - NSLeftMargin - - float - 18 - - NSPaperSize - - coded - BAtzdHJlYW10eXBlZIHoA4QBQISEhAdOU1ZhbHVlAISECE5TT2JqZWN0AIWEASqEhAx7X05TU2l6ZT1mZn2WgWQCgRgDhg== - - NSRightMargin - - float - 18 - - NSTopMargin - - float - 18 - - - PrintOnePage - - QuickLookPreview - - JVBERi0xLjMKJcTl8uXrp/Og0MTGCjUgMCBvYmoKPDwgL0xlbmd0aCA2IDAgUiAvRmls - dGVyIC9GbGF0ZURlY29kZSA+PgpzdHJlYW0KeAGVVMtu20AMvO9X8OgcvFku9yFd67aH - oA+kVtFD0YPr2EWDuE1q/z86XMeSbclKa8GQFuAsh8Mhn+iWnsjhicIUg9CfFX2hX3Q9 - 2zItt8Tl2S5p6mwk/ScXbBVyPESvEXFDbO73mNm8XOdoPsPNXA5Tfenlyw35VFmXQiZx - 2YrHx6Z81hKFJIhNkcU80Lww6+MlHvBV3eLrbAs++FjwNIw3yC+CNICGqtLMOClIT8MY - 5axU9/zanKat44WcpWY+4LuaOR/qeLlmD+mUw55zOQHUcfYuk5dkHXvKnkK0Dj9v0Mv1 - cBMUkNjWKLsAtO2qONrute2O0PKj9mlOD+UjexXxVQMraApqloSkaqAp3lMOFj2EOQI1 - G7p+y9bBA82aJh9+362uqLmnN80+j9rLtPbydSaOoStBGV0gj1A1yil5c5m8NplzUvLa - jYvkxdlUc2AK5oz858e7xW61+P7QL6HMB6tczEMlmCMV2yHQ0H4JI/ozhuO5hFH9kxXR - Gvr6v/u5G5MfhvhX+RHa5z4iv3rnVH7skiHzYCCc1C719f/42OPe6a7uzx7O4bru3Nz3 - jgqnsTqwp94ZEV7J1wHW0cuPzWPOne9tylJhnZw7//VitxijDzuf0h+ZW8T+F321/oH+ - qHEYk+pSNWCcT6sfPfbd3Ep1zv7y4GrsOXsztnWC79g/i3+ybARuF4d5bSUHMSybrzR5 - j0mFzTxNNlf0jZqb/d65/QuiI3f1CmVuZHN0cmVhbQplbmRvYmoKNiAwIG9iago1NTUK - ZW5kb2JqCjMgMCBvYmoKPDwgL1R5cGUgL1BhZ2UgL1BhcmVudCA0IDAgUiAvUmVzb3Vy - Y2VzIDcgMCBSIC9Db250ZW50cyA1IDAgUiAvTWVkaWFCb3ggWzAgMCA1MzEgNTQzXQo+ - PgplbmRvYmoKNyAwIG9iago8PCAvUHJvY1NldCBbIC9QREYgL1RleHQgXSAvQ29sb3JT - cGFjZSA8PCAvQ3MyIDkgMCBSIC9DczEgOCAwIFIgPj4gL0ZvbnQgPDwKL0YxLjAgMTAg - MCBSID4+ID4+CmVuZG9iagoxMSAwIG9iago8PCAvTGVuZ3RoIDEyIDAgUiAvTiAxIC9B - bHRlcm5hdGUgL0RldmljZUdyYXkgL0ZpbHRlciAvRmxhdGVEZWNvZGUgPj4Kc3RyZWFt - CngBhVJPSBRRHP7NNhKEiEGFeIh3CgmVKaysoNp2dVmVbVuV0qIYZ9+6o7Mz05vZNcWT - BF2iPHUPomN07NChm5eiwKxL1yCpIAg8dej7zezqKIRveTvf+/39ft97RG2dpu87KUFU - c0OVK6Wnbk5Ni4MfKUUd1E5YphX46WJxjLHruZK/u9fWZ9LYst7HtXb79j21lWVgIeot - trcQ+iGRZgAfmZ8oZYCzwB2Wr9g+ATxYDqwa8COiAw+auTDT0Zx0pbItkVPmoigqr2I7 - Sa77+bnGvou1iYP+XI9m1o69s+qq0UzUtPdEobwPrkQZz19U9mw1FKcN45xIQxop8q7V - 3ytMxxGRKxBKBlI1ZLmfak6ddeB1GLtdupPj+PYQpT7JYKiJtemymR2FfQB2KsvsEPAF - 6PGyYg/ngXth/1tRw5PAJ2E/ZId51q0f9heuU+B7hD014M4UrsXx2oofXi0BQ/dUI2iM - c03E09c5c6SI7zHUGZj3RjmmCzF3lqoTN4A7YR9ZqmYKsV37ruol7nsCd9PjO9GbOQtc - oBxJcrEV2RTQPAlYFH2LsEkOPD7OHlXgd6iYwBy5idzNKPce1REbZ6NSgVZ6jVfGT+O5 - 8cX4ZWwYz4B+rHbXe3z/6eMVdde2Pjz5jXrcOa69nRtVYVZxZQvd/8cyhI/ZJzmmwdOh - WVhr2HbkD5rMTLAMKMR/BT6X+pITVdzV7u24RRLMUD4sbCW6S1RuKdTqPYNKrBwr2AB2 - cJLELFocuFNrujl4d9giem35TVey64b++vZ6+9ryHm3KqCkoE82zRGaUsVuj5N142/1m - kRGfODq+572KWsn+SUUQP4U5WiryFFX0VlDWxG9nDn4btn5cP6Xn9UH9PAk9rZ/Rr+ij - Eb4MdEnPwnNRH6NJ8LBpIeISoIqDM9ROVGONA+Ip8fK0W2SR/Q9AGf1mCmVuZHN0cmVh - bQplbmRvYmoKMTIgMCBvYmoKNzA0CmVuZG9iago5IDAgb2JqClsgL0lDQ0Jhc2VkIDEx - IDAgUiBdCmVuZG9iagoxMyAwIG9iago8PCAvTGVuZ3RoIDE0IDAgUiAvTiAzIC9BbHRl - cm5hdGUgL0RldmljZVJHQiAvRmlsdGVyIC9GbGF0ZURlY29kZSA+PgpzdHJlYW0KeAGF - VM9rE0EU/jZuqdAiCFprDrJ4kCJJWatoRdQ2/RFiawzbH7ZFkGQzSdZuNuvuJrWliOTi - 0SreRe2hB/+AHnrwZC9KhVpFKN6rKGKhFy3xzW5MtqXqwM5+8943731vdt8ADXLSNPWA - BOQNx1KiEWlsfEJq/IgAjqIJQTQlVdvsTiQGQYNz+Xvn2HoPgVtWw3v7d7J3rZrStpoH - hP1A4Eea2Sqw7xdxClkSAog836Epx3QI3+PY8uyPOU55eMG1Dys9xFkifEA1Lc5/TbhT - zSXTQINIOJT1cVI+nNeLlNcdB2luZsbIEL1PkKa7zO6rYqGcTvYOkL2d9H5Os94+wiHC - CxmtP0a4jZ71jNU/4mHhpObEhj0cGDX0+GAVtxqp+DXCFF8QTSeiVHHZLg3xmK79VvJK - gnCQOMpkYYBzWkhP10xu+LqHBX0m1xOv4ndWUeF5jxNn3tTd70XaAq8wDh0MGgyaDUhQ - EEUEYZiwUECGPBoxNLJyPyOrBhuTezJ1JGq7dGJEsUF7Ntw9t1Gk3Tz+KCJxlEO1CJL8 - Qf4qr8lP5Xn5y1yw2Fb3lK2bmrry4DvF5Zm5Gh7X08jjc01efJXUdpNXR5aseXq8muwa - P+xXlzHmgjWPxHOw+/EtX5XMlymMFMXjVfPqS4R1WjE3359sfzs94i7PLrXWc62JizdW - m5dn/WpI++6qvJPmVflPXvXx/GfNxGPiKTEmdornIYmXxS7xkthLqwviYG3HCJ2VhinS - bZH6JNVgYJq89S9dP1t4vUZ/DPVRlBnM0lSJ93/CKmQ0nbkOb/qP28f8F+T3iuefKAIv - bODImbptU3HvEKFlpW5zrgIXv9F98LZua6N+OPwEWDyrFq1SNZ8gvAEcdod6HugpmNOW - ls05Uocsn5O66cpiUsxQ20NSUtcl12VLFrOZVWLpdtiZ0x1uHKE5QvfEp0plk/qv8RGw - /bBS+fmsUtl+ThrWgZf6b8C8/UUKZW5kc3RyZWFtCmVuZG9iagoxNCAwIG9iago3MzcK - ZW5kb2JqCjggMCBvYmoKWyAvSUNDQmFzZWQgMTMgMCBSIF0KZW5kb2JqCjQgMCBvYmoK - PDwgL1R5cGUgL1BhZ2VzIC9NZWRpYUJveCBbMCAwIDYxMiA3OTJdIC9Db3VudCAxIC9L - aWRzIFsgMyAwIFIgXSA+PgplbmRvYmoKMTUgMCBvYmoKPDwgL1R5cGUgL0NhdGFsb2cg - L091dGxpbmVzIDIgMCBSIC9QYWdlcyA0IDAgUiA+PgplbmRvYmoKMiAwIG9iago8PCAv - TGFzdCAxNiAwIFIgL0ZpcnN0IDE3IDAgUiA+PgplbmRvYmoKMTcgMCBvYmoKPDwgL1Bh - cmVudCAxOCAwIFIgL0NvdW50IDAgL0Rlc3QgWyAzIDAgUiAvWFlaIDAgNTQzIDAgXSAv - VGl0bGUgKENhbnZhcyAxKQo+PgplbmRvYmoKMTggMCBvYmoKPDwgPj4KZW5kb2JqCjE2 - IDAgb2JqCjw8IC9QYXJlbnQgMTggMCBSIC9Db3VudCAwIC9EZXN0IFsgMyAwIFIgL1hZ - WiAwIDU0MyAwIF0gL1RpdGxlIChDYW52YXMgMSkKPj4KZW5kb2JqCjE5IDAgb2JqCjw8 - IC9MZW5ndGggMjAgMCBSIC9MZW5ndGgxIDk2MzIgL0ZpbHRlciAvRmxhdGVEZWNvZGUg - Pj4Kc3RyZWFtCngBvVp5fFTV9T/37bNkMjOZfZ9MZiaTfSEhIYEMIQkJEAgJS4IEkkDY - hBoxpoJiowWRiPxEBBSsgkvYigwBYYDCj1IU7KJYFZVqqy1aquZj7Q+1BWbmd96bECGf - 1g9/+Ol7c+7+7j33e88957z7pnPp3e2QAN1AQ92M1o55IF0pLgDSPWdJa0c8nyRGy+d0 - dWK5eLGpAPTieR3zl8TzwhMAcvv8xcsGnk96AUCtXtDeOjdeD9cwLlyABfE8GYZxyoIl - nffE89qDGE9YfMecgfqk+zCfuqT1noHx4QPMu37UuqQ93t4j9pfSccddnQN58fnqjqXt - A+1JI/L3BhAsTYI7QAa3Aw8UqPFuBuAvye3AYK1Yj9fcDMWG2YmlX4NGkPKza/9Hil91 - /+L8P9uv+RXrhX9hgex6ezHmAtEAgJJgfb9i/WCN9BwGSWFoSA9DDVIZUgFSevpoE3ST - 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 - k1JGlqVUTWt4esq6yHDq0u1163oj66ljS/LGP/NG5Kwo5yWx9xk3MxHf9kxghseC+U8K - m9RPGV5kdgq96l2GsHBWeJf5RPU3nXKEwNlNvNKuVZh5s1lP+RMtVplfb7ZYw0R2wL10 - QHvc7GXEXc0MMDI+RZIMd7qG8hHeiCk2AVNyndIHRI2BYOB8hFZhIBrbuJOJliRFKzlX - OFeUUS3uegptNDqZ+Tz10aqcCUdf3LTpefwQeS367YfRa0T7V66TJPZumvXEtb49F+kL - 0S/QlESiL5H0a2iwg6xoF6NTGS/uaxUkQ2cwY5eww0ilCi6bRsXZ9Xwip7LbFMkqym+y - pMjRKroDyYlmT8q/tYrSZtWgkpRUoc1gBdbiY3xgxYmxBgyIWeUD2ijNSZqRaBtFSyiu - HvoOoi0kA+uMH4dEvYbugsZDvbrDW3X0WKUXw2jWvsLgbfceih7u3LKsPqfk4LK3ft89 - c/+xuVvum95L719Xk1oa/RvO8blNswscNZEPxf1gjH1JydgZuKL1LydkyU+qSJiUBb2M - odhIcyq5xoKiil8QA6BX6RNpJ03R1wz4VnzNPX9F3ERGmotPiw6vOi6i2aKARkr71ZGL - 0sbBPRh3HAd8HF8B2sD8nYf27PHpcxMcOucY//0z1q9nZ0Tf2RCpLEpSEGqdTHhgPvXK - BkkXYIBfntvx++i/u8S/6/ghG7+p5eKbdgF+J66ASumr6zj8rjoJv/vW45fc6diK4ElE - /PSDw9MJGDN56uhx09Kr2xd3tXcunNMqtbg+whRMtCB1IHUjPYa0DSmEdBLpHNJHSH8X - u0VSI7mQcpCCSHVILUgdsYEL8BpME+Tx5vyEIfnaIfmJQ/KThuTrh+SnDsmLs7tx/LYh - +blD8hLWN/A7f0j9wiF58Szpxv6l/0rd8PwdQ+o7huQ7xfz/A+fEBWMKZW5kc3RyZWFt - CmVuZG9iagoyMCAwIG9iago2MjUzCmVuZG9iagoyMSAwIG9iago8PCAvVHlwZSAvRm9u - dERlc2NyaXB0b3IgL0FzY2VudCA3NzAgL0NhcEhlaWdodCA3MzcgL0Rlc2NlbnQgLTIz - MCAvRmxhZ3MgMzIKL0ZvbnRCQm94IFstOTUxIC00ODEgMTQ0NSAxMTIyXSAvRm9udE5h - bWUgL0NRVUFKVitIZWx2ZXRpY2EgL0l0YWxpY0FuZ2xlIDAKL1N0ZW1WIDAgL01heFdp - ZHRoIDE1MDAgL1hIZWlnaHQgNjM3IC9Gb250RmlsZTIgMTkgMCBSID4+CmVuZG9iagoy - MiAwIG9iagpbIDcyMiAwIDAgMCAwIDAgMCAwIDU1NiA4MzMgNzIyIDc3OCAwIDAgNzIy - IDAgMCA3MjIgMCAwIDAgMCAwIDAgMCAwIDAgMCAwCjU1NiA1NTYgMCA1NTYgNTU2IDAg - NTU2IDAgMjIyIDAgMCAyMjIgODMzIDAgNTU2IDU1NiAwIDAgMCAyNzggXQplbmRvYmoK - MTAgMCBvYmoKPDwgL1R5cGUgL0ZvbnQgL1N1YnR5cGUgL1RydWVUeXBlIC9CYXNlRm9u - dCAvQ1FVQUpWK0hlbHZldGljYSAvRm9udERlc2NyaXB0b3IKMjEgMCBSIC9XaWR0aHMg - MjIgMCBSIC9GaXJzdENoYXIgNjggL0xhc3RDaGFyIDExNiAvRW5jb2RpbmcgL01hY1Jv - bWFuRW5jb2RpbmcKPj4KZW5kb2JqCjIzIDAgb2JqCihNYWMgT1MgWCAxMC42LjggUXVh - cnR6IFBERkNvbnRleHQpCmVuZG9iagoyNCAwIG9iagooRDoyMDEyMDUyMzA4MTczOVow - MCcwMCcpCmVuZG9iagoxIDAgb2JqCjw8IC9Qcm9kdWNlciAyMyAwIFIgL0NyZWF0aW9u - RGF0ZSAyNCAwIFIgL01vZERhdGUgMjQgMCBSID4+CmVuZG9iagp4cmVmCjAgMjUKMDAw - MDAwMDAwMCA2NTUzNSBmIAowMDAwMDEwMDYxIDAwMDAwIG4gCjAwMDAwMDI3OTMgMDAw - MDAgbiAKMDAwMDAwMDY3MCAwMDAwMCBuIAowMDAwMDAyNjQ0IDAwMDAwIG4gCjAwMDAw - MDAwMjIgMDAwMDAgbiAKMDAwMDAwMDY1MSAwMDAwMCBuIAowMDAwMDAwNzc0IDAwMDAw - IG4gCjAwMDAwMDI2MDggMDAwMDAgbiAKMDAwMDAwMTcxMiAwMDAwMCBuIAowMDAwMDA5 - NzkyIDAwMDAwIG4gCjAwMDAwMDA4ODQgMDAwMDAgbiAKMDAwMDAwMTY5MiAwMDAwMCBu - IAowMDAwMDAxNzQ4IDAwMDAwIG4gCjAwMDAwMDI1ODggMDAwMDAgbiAKMDAwMDAwMjcy - NyAwMDAwMCBuIAowMDAwMDAyOTU2IDAwMDAwIG4gCjAwMDAwMDI4NDEgMDAwMDAgbiAK - MDAwMDAwMjkzNCAwMDAwMCBuIAowMDAwMDAzMDQ5IDAwMDAwIG4gCjAwMDAwMDkzOTIg - MDAwMDAgbiAKMDAwMDAwOTQxMyAwMDAwMCBuIAowMDAwMDA5NjM4IDAwMDAwIG4gCjAw - MDAwMDk5NjcgMDAwMDAgbiAKMDAwMDAxMDAxOSAwMDAwMCBuIAp0cmFpbGVyCjw8IC9T - aXplIDI1IC9Sb290IDE1IDAgUiAvSW5mbyAxIDAgUiAvSUQgWyA8YjZmZmIyZWU5NzJm - Yjg0NDQ2ZmQ1NjE2ZGRhOTg3MWY+CjxiNmZmYjJlZTk3MmZiODQ0NDZmZDU2MTZkZGE5 - ODcxZj4gXSA+PgpzdGFydHhyZWYKMTAxMzYKJSVFT0YKMSAwIG9iago8PC9BdXRob3Ig - KEpvbmF0aGFuIEJhY2hyYWNoKS9DcmVhdGlvbkRhdGUgKEQ6MjAxMjA1MTUxNzUzMDBa - KS9DcmVhdG9yIChPbW5pR3JhZmZsZSBQcm9mZXNzaW9uYWwgNS4zLjYpL01vZERhdGUg - KEQ6MjAxMjA1MjMwNjE1MDBaKS9Qcm9kdWNlciAyMyAwIFIgL1RpdGxlIChub2RlLWhp - ZXJhcmNoeS5ncmFmZmxlKT4+CmVuZG9iagp4cmVmCjEgMQowMDAwMDEwNzk0IDAwMDAw - IG4gCnRyYWlsZXIKPDwvSUQgWzxiNmZmYjJlZTk3MmZiODQ0NDZmZDU2MTZkZGE5ODcx - Zj4gPGI2ZmZiMmVlOTcyZmI4NDQ0NmZkNTYxNmRkYTk4NzFmPl0gL0luZm8gMSAwIFIg - L1ByZXYgMTAxMzYgL1Jvb3QgMTUgMCBSIC9TaXplIDI1Pj4Kc3RhcnR4cmVmCjEwOTkx - CiUlRU9GCg== - - QuickLookThumbnail - - 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 - AAAEAAAHDAAAAAAACAAIAAgACAABAAEAAQAB - - ReadOnly - NO - RowAlign - 1 - RowSpacing - 36 - SheetTitle - Canvas 1 - SmartAlignmentGuidesActive - YES - SmartDistanceGuidesActive - YES - UniqueID - 1 - UseEntirePage - - VPages - 1 - WindowInfo - - CurrentSheet - 0 - ExpandedCanvases - - FitInWindow - - Frame - {{347, 227}, {717, 626}} - ListView - - OutlineWidth - 142 - RightSidebar - - Sidebar - - SidebarWidth - 138 - VisibleRegion - {{1.04853, 1.04853}, {602.903, 542.088}} - Zoom - 0.95371901988983154 - ZoomValues - - - Canvas 1 - 0.0 - 1 - - - - saveQuickLookFiles - YES - - diff --git a/doc/manual/figs/node-hierarchy.pdf b/doc/manual/figs/node-hierarchy.pdf deleted file mode 100644 index 4583c760..00000000 Binary files a/doc/manual/figs/node-hierarchy.pdf and /dev/null differ diff --git a/doc/manual/figs/type-hierarchy.graffle b/doc/manual/figs/type-hierarchy.graffle deleted file mode 100644 index 1e684201..00000000 --- a/doc/manual/figs/type-hierarchy.graffle +++ /dev/null @@ -1,830 +0,0 @@ - - - - - ActiveLayerIndex - 0 - ApplicationVersion - - com.omnigroup.OmniGrafflePro - 139.18.0.187838 - - AutoAdjust - - BackgroundGraphic - - Bounds - {{0, 0}, {677.6772983114447, 626}} - Class - SolidGraphic - ID - 2 - Style - - shadow - - Draws - NO - - stroke - - Draws - NO - - - - BaseZoom - 0 - CanvasOrigin - {0, 0} - CanvasSize - {677.6772983114447, 626} - ColumnAlign - 1 - ColumnSpacing - 36 - CreationDate - 2012-05-15 17:50:34 +0000 - Creator - Jonathan Bachrach - DisplayScale - 1 0/72 in = 1.0000 in - FileType - flat - GraphDocumentVersion - 8 - GraphicsList - - - Bounds - {{274.49999856948853, 262.01600646972656}, {72, 45}} - Class - ShapedGraphic - FontInfo - - Color - - w - 0 - - Font - Helvetica - NSKern - 0.0 - Size - 12 - - ID - 1166 - Shape - Rectangle - Style - - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf390 -\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc - -\f0\fs24 \cf0 \expnd0\expndtw0\kerning0 -Aggregate} - VerticalPad - 0 - - - - Bounds - {{364.49999856948853, 344.01600646972656}, {72, 45}} - Class - ShapedGraphic - FontInfo - - Color - - w - 0 - - Font - Helvetica - NSKern - 0.0 - Size - 12 - - ID - 1173 - Shape - Rectangle - Style - - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf390 -\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc - -\f0\fs24 \cf0 \expnd0\expndtw0\kerning0 -Vec} - VerticalPad - 0 - - - - Bounds - {{274.49999856948853, 344.01600646972656}, {72, 45}} - Class - ShapedGraphic - FontInfo - - Color - - w - 0 - - Font - Helvetica - NSKern - 0.0 - Size - 12 - - ID - 1174 - Shape - Rectangle - Style - - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf390 -\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc - -\f0\fs24 \cf0 \expnd0\expndtw0\kerning0 -Bundle} - VerticalPad - 0 - - - - Bounds - {{229.49999856948855, 426.01600646972656}, {72, 45}} - Class - ShapedGraphic - FontInfo - - Color - - w - 0 - - Font - Helvetica - NSKern - 0.0 - Size - 12 - - ID - 1172 - Shape - Rectangle - Style - - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf390 -\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc - -\f0\fs24 \cf0 \expnd0\expndtw0\kerning0 -SInt} - VerticalPad - 0 - - - - Bounds - {{139.49999856948853, 426.01600646972656}, {72, 45}} - Class - ShapedGraphic - FontInfo - - Color - - w - 0 - - Font - Helvetica - NSKern - 0.0 - Size - 12 - - ID - 1171 - Shape - Rectangle - Style - - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf390 -\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc - -\f0\fs24 \cf0 \expnd0\expndtw0\kerning0 -UInt} - VerticalPad - 0 - - - - Bounds - {{184.49999856948853, 344.01600646972656}, {72, 45}} - Class - ShapedGraphic - FontInfo - - Color - - w - 0 - - Font - Helvetica - NSKern - 0.0 - Size - 12 - - ID - 1170 - Shape - Rectangle - Style - - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf390 -\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc - -\f0\fs24 \cf0 \expnd0\expndtw0\kerning0 -Num} - VerticalPad - 0 - - - - Bounds - {{139.49999856948853, 508.01600646972656}, {72, 45}} - Class - ShapedGraphic - FontInfo - - Color - - w - 0 - - Font - Helvetica - NSKern - 0.0 - Size - 12 - - ID - 1169 - Shape - Rectangle - Style - - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf390 -\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc - -\f0\fs24 \cf0 \expnd0\expndtw0\kerning0 -Bool} - VerticalPad - 0 - - - - Bounds - {{184.49999856948853, 262.01600646972656}, {72, 45}} - Class - ShapedGraphic - FontInfo - - Color - - w - 0 - - Font - Helvetica - NSKern - 0.0 - Size - 12 - - ID - 1168 - Shape - Rectangle - Style - - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf390 -\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc - -\f0\fs24 \cf0 \expnd0\expndtw0\kerning0 -Bits} - VerticalPad - 0 - - - - Bounds - {{229.49999856948855, 180.01600646972656}, {72, 45}} - Class - ShapedGraphic - FontInfo - - Color - - w - 0 - - Font - Helvetica - NSKern - 0.0 - Size - 12 - - ID - 1167 - Shape - Rectangle - Style - - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf390 -\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc - -\f0\fs24 \cf0 \expnd0\expndtw0\kerning0 -Data} - VerticalPad - 0 - - - - Class - LineGraphic - Head - - ID - 1169 - - ID - 1175 - Points - - {175.49997927083118, 471.51600646972724} - {175.49997927083118, 507.51600646977789} - - Style - - stroke - - HeadArrow - 0 - Legacy - - TailArrow - 0 - - - Tail - - ID - 1171 - - - - Class - LineGraphic - Head - - ID - 1170 - - ID - 1176 - Points - - {220.50001566718862, 307.51600646972304} - {220.50001566718862, 343.516006469469} - - Style - - stroke - - HeadArrow - 0 - Legacy - - TailArrow - 0 - - - Tail - - ID - 1168 - - - - Class - LineGraphic - Head - - ID - 1171 - - ID - 1177 - Points - - {207.91189374193721, 389.45434001274441} - {188.08812133658486, 425.57767309141406} - - Style - - stroke - - HeadArrow - 0 - Legacy - - TailArrow - 0 - - - Tail - - ID - 1170 - - - - Class - LineGraphic - Head - - ID - 1172 - - ID - 1178 - Points - - {233.08810841981315, 389.45433997117317} - {252.91188872613353, 425.5776729681487} - - Style - - stroke - - HeadArrow - 0 - Legacy - - TailArrow - 0 - - - Tail - - ID - 1170 - - - - Class - LineGraphic - Head - - ID - 1174 - - ID - 1181 - Points - - {310.50001566718862, 307.51600646972304} - {310.50001566718862, 343.516006469469} - - Style - - stroke - - HeadArrow - 0 - Legacy - - TailArrow - 0 - - - Tail - - ID - 1166 - - - - Class - LineGraphic - Head - - ID - 1168 - - ID - 1191 - Points - - {252.91189374193721, 225.45434001274441} - {233.08812133658483, 261.57767309141406} - - Style - - stroke - - HeadArrow - 0 - Legacy - - TailArrow - 0 - - - Tail - - ID - 1167 - - - - Class - LineGraphic - Head - - ID - 1173 - - ID - 1192 - Points - - {335.56471631066012, 307.35275148695979} - {375.4352722911143, 343.67926152482607} - - Style - - stroke - - HeadArrow - 0 - Legacy - - TailArrow - 0 - - - Tail - - ID - 1166 - - - - Class - LineGraphic - Head - - ID - 1166 - - ID - 1193 - Points - - {278.08810841981312, 225.45433997117314} - {297.9118887261335, 261.5776729681487} - - Style - - stroke - - HeadArrow - 0 - Legacy - - TailArrow - 0 - - - Tail - - ID - 1167 - - - - GridInfo - - GuidesLocked - NO - GuidesVisible - YES - HPages - 2 - ImageCounter - 3 - KeepToScale - - Layers - - - Lock - NO - Name - Layer 1 - Print - YES - View - YES - - - LayoutInfo - - Animate - NO - AutoLayout - 2 - LineLength - 0.4643835723400116 - circoMinDist - 18 - circoSeparation - 0.0 - layoutEngine - dot - neatoSeparation - 0.0 - twopiSeparation - 0.0 - - LinksVisible - NO - MagnetsVisible - NO - MasterSheets - - ModificationDate - 2013-07-30 21:07:34 +0000 - Modifier - Jonathan Bachrach - NotesVisible - NO - Orientation - 2 - OriginVisible - NO - OutlineStyle - Basic - PageBreaks - NO - PrintInfo - - NSBottomMargin - - float - 41 - - NSHorizonalPagination - - coded - BAtzdHJlYW10eXBlZIHoA4QBQISEhAhOU051bWJlcgCEhAdOU1ZhbHVlAISECE5TT2JqZWN0AIWEASqEhAFxlwCG - - NSLeftMargin - - float - 18 - - NSPaperSize - - size - {611.99999713897705, 792} - - NSPrintReverseOrientation - - int - 0 - - NSRightMargin - - float - 18 - - NSTopMargin - - float - 18 - - - PrintOnePage - - ReadOnly - NO - RowAlign - 1 - RowSpacing - 36 - SheetTitle - Canvas 1 - SmartAlignmentGuidesActive - YES - SmartDistanceGuidesActive - YES - UniqueID - 1 - UseEntirePage - - VPages - 1 - WindowInfo - - CurrentSheet - 0 - ExpandedCanvases - - FitInWindow - - Frame - {{324, 186}, {717, 626}} - ListView - - OutlineWidth - 142 - RightSidebar - - Sidebar - - SidebarWidth - 138 - VisibleRegion - {{1.1750433447927242, 1.1750433447927242}, {675.64992325581647, 625.12305942972932}} - Zoom - 0.85103243589401245 - ZoomValues - - - Canvas 1 - 0.0 - 1 - - - - - diff --git a/doc/manual/figs/type-hierarchy.pdf b/doc/manual/figs/type-hierarchy.pdf deleted file mode 100644 index f06dc97d..00000000 Binary files a/doc/manual/figs/type-hierarchy.pdf and /dev/null differ diff --git a/doc/manual/manual.tex b/doc/manual/manual.tex deleted file mode 100644 index f39951cf..00000000 --- a/doc/manual/manual.tex +++ /dev/null @@ -1,1726 +0,0 @@ -\documentclass[10pt,twocolumn]{article} -\setlength\textwidth{6.875in} -\setlength\textheight{8.875in} -% set both margins to 2.5 pc -\setlength{\oddsidemargin}{-0.1875in}% 1 - (8.5 - 6.875)/2 -\setlength{\evensidemargin}{-0.1875in} -\setlength{\marginparwidth}{0pc} -\setlength{\marginparsep}{0pc}% -\setlength{\topmargin}{0in} \setlength{\headheight}{0pt} -\setlength{\headsep}{0pt} -\setlength{\footskip}{37pt}% -\setlength{\columnsep}{0.3125in} -\setlength{\columnwidth}{3.28125in}% (6.875 - 0.3125)/2 = 3.28125in -\setlength{\parindent}{1pc} -\newcommand{\myMargin}{1.00in} -\usepackage[top=\myMargin, left=\myMargin, right=\myMargin, bottom=\myMargin, nohead]{geometry} -\usepackage{epsfig,graphicx} -\usepackage{palatino} -\usepackage{fancybox} -\usepackage[procnames]{listings} -\usepackage{hyperref} - -\newenvironment{commentary} -{ \vspace{-0.1in} - \begin{quotation} - \noindent - \small \em - \rule{\linewidth}{1pt}\\ -} -{ - \end{quotation} -} - -\title{Chisel Manual} -\author{Jonathan Bachrach, Huy Vo, Krste Asanovi\'{c} \\ -EECS Department, UC Berkeley\\ -{\tt \{jrb|huytbvo|krste\}@eecs.berkeley.edu} -} -\date{\today} - -\newenvironment{example}{\VerbatimEnvironment\begin{footnotesize}\begin{Verbatim}}{\end{Verbatim}\end{footnotesize}} -\newcommand{\kode}[1]{\begin{footnotesize}{\tt #1}\end{footnotesize}} - -\def\code#1{{\small\tt #1}} - -\def\note#1{\noindent{\bf [Note: #1]}} -%\def\note#1{} - -\input{../style/scala.tex} - -\lstset{frame=, basicstyle={\footnotesize\ttfamily}} - -\lstset{frame=} - -\begin{document} -\maketitle{} - -% TODO: default -% TODO: enum yields UInt -% TODO: why hardware construction languages - - - -\section{Introduction} - -This document is a manual for {\em Chisel} (Constructing Hardware In a -Scala Embedded Language). Chisel is a hardware construction language -embedded in the high-level programming language Scala. A separate -Chisel tutorial document provides a gentle introduction to using -Chisel, and should be read first. This manual provides a -comprehensive overview and specification of the Chisel language, which -is really only a set of special class definitions, predefined objects, -and usage conventions within Scala. When you write a Chisel program -you are actually writing a Scala program. In this manual, we presume -that you already understand the basics of Scala. If you are -unfamiliar with Scala, we recommend you consult one of the excellent -Scala books (\cite{programming-scala}, \cite{programming-in-scala}). - -\section{Nodes} - -Any hardware design in Chisel is ultimately represented by a graph of -node objects. User code in Chisel generate this graph of nodes, which -is then passed to the Chisel backends to be translated into Verilog or -C++ code. Nodes are defined as follows: - -\begin{scala} -class Node { - // name assigned by user or from introspection - var name: String = "" - // incoming graph edges - def inputs: ArrayBuffer[Node] - // outgoing graph edges - def consumers: ArrayBuffer[Node] - // node specific width inference - def inferWidth: Int - // get width immediately inferrable - def getWidth: Int - // get first raw node - def getRawNode: Node - // convert to raw bits - def toBits: Bits - // convert to raw bits - def fromBits(x: Bits): this.type - // return lit value if inferrable else null - def litOf: Lit - // return value of lit if litOf is non null - def litValue(default: BigInt = BigInt(-1)): BigInt -} -\end{scala} - - -The uppermost levels of the node class hierarchy are shown in -Figure~\ref{fig:node-hierarchy}. The basic categories are: - -\begin{description} -\item[Lit] -- constants or literals, -\item[Op] -- logical or arithmetic operations, -\item[Updateable] -- conditionally updated nodes, -\item[Data] -- typed wires or ports, -\item[Reg] -- positive-edge-triggered registers, and -\item[Mem] -- memories. -\end{description} - -\begin{figure}[h] -\centering -\includegraphics[width=3in]{figs/node-hierarchy.pdf} -\caption{Node hierarchy.} -\label{fig:node-hierarchy} -\end{figure} - -\section{Lits} - -Raw literals are represented as \code{Lit} nodes defined as follows: - -\begin{scala} -class Lit extends Node { - // original value - val inputVal: BigInt -} -\end{scala} - -\noindent -Raw literals contain a collection of bits. -Users do not create raw literals directly, but instead use type -constructors defined in Section~\ref{sec:types}. - -% Constant or literal values are expressed using Scala integers or strings passed to constructors for the types: - -% TODO: isLit and litOf - -\section{Ops} - -Raw operations are represented as \code{Op} nodes defined as follows: - -\begin{scala} -class Op extends Node { - // op name used during emission - val op: String -} -\end{scala} - -\noindent -Ops compute a combinational function of their inputs. - -\section{Types} -\label{sec:types} - -A Chisel graph representing a hardware design contains {\em raw} and -{\em type} nodes. The Chisel type system is maintained separately -from the underlying Scala type system, and so type nodes are -interspersed between raw nodes to allow Chisel to check and respond to -Chisel types. Chisel type nodes are erased before the hardware design -is translated into C++ or Verilog. The \code{getRawNode} operator -defined in the base Node class, skips type nodes and returns the first -raw node found. Figure~\ref{fig:type-hierarchy} shows the built-in -Chisel type hierarchy, with \code{Data} as the topmost node. - -\begin{figure}[h] -\centering -\includegraphics[height=2.5in]{figs/type-hierarchy.pdf} -\caption{Chisel type hierarchy.} -\label{fig:type-hierarchy} -\end{figure} - -\noindent -Built-in scalar types include \code{Bool}, \code{SInt}, -and \code{UInt} and built-in aggregate types \code{Bundle} and -\code{Vec} allow the user to expand the set of Chisel datatypes with -collections of other types. - -\code{Data} itself is a node: -\begin{scala} -abstract class Data extends Node { - override def clone(): this.type = - this.getClass.newInstance. - asInstanceOf[this.type] - // simple conversions - def toSInt: SInt - def toUInt: UInt - def toBool: Bool - def toBits: Bits - // flatten out to leaves of tree - def flatten: Array[(String, Data)] - // port direction if leaf - def dir: PortDir - // change dir to OUTPUT - def asOutput: this.type - // change dir to INPUT - def asInput: this.type - // change polarity of dir - def flip: this.type - // assign to input - def :=[T <: Data](t: T) - // bulk assign to input - def <>(t: Data) -} -\end{scala} -\noindent -The Data class has methods for converting between types and for -delegating port methods to its single input. We will discuss ports in -Section~\ref{sec:ports}. Finally, users can override the \code{clone} -method in their own type nodes (e.g., bundles) in order to reflect -construction parameters that are necessary for cloning. - -Data nodes can be used for four purposes: - -\begin{itemize} -\item {\bf types} -- \kode{UInt(width = 8)} -- record intermediate types in the graph - specifying at minimum bitwidth (described in this section), -\item {\bf wires} -- \kode{UInt(width = 8)} -- serve as forward declarations of data allowing future - conditional updates (described in Section~\ref{sec:wires}), -\item {\bf ports} -- \kode{UInt(dir = OUTPUT, width = 8)} -- are - specialized wires defining module interfaces, and - additionally specify direction (described in - Section~\ref{sec:ports}), and -\item{\bf literals} -- \kode{UInt(1)} or \kode{UInt(1, 8)} -- can be constructed using type object -constructors specifying their value and optional width. -\end{itemize} - -\subsection{Bits} - -In Chisel, a raw collection of bits is represented by the \code{Bits} -type defined as follows: - -\begin{scala} -object Bits { - def apply(dir: PortDir = null, - width: Int = -1): Bits - // create literal from BigInt or Int - def apply(value: BigInt, width: Int = -1): Bits - // create literal from String using - // base_char digit+ string format - def apply(value: String, width: Int = -1): Bits -} - -class Bits extends Data with Updateable { - // bitwise-not - def unary_~(): Bits - // bitwise-and - def & (b: Bits): Bits - // bitwise-or - def | (b: Bits): Bits - // bitwise-xor - def ^ (b: Bits): Bits - // and-reduction - def andR(): Bool - // or-reduction - def orR(): Bool - // xor-reduction - def xorR(): Bool - // logical NOT - def unary_!(): Bool - // logical AND - def && (b: Bool): Bool - // logical OR - def || (b: Bool): Bool - // equality - def ===(b: Bits): Bool - // inequality - def != (b: Bits): Bool - // logical left shift - def << (b: UInt): Bits - // logical right shift - def >> (b: UInt): Bits - // concatenate - def ## (b: Bits): Bits - // extract single bit, LSB is 0 - def apply(x: Int): Bits - // extract bit field from end to start bit pos - def apply(hi: Int, lo: Int): Bits -} - -def Cat[T <: Data](elt: T, elts: T*): Bits -\end{scala} - -\noindent -Bits has methods for simple bit operations. -Note that \code{\#\#} is binary -concatenation, while \code{Cat} is an n-ary concatentation. -To avoid colliding with Scala's builtin \code{==}, -Chisel's bitwise comparison is named \code{===}. - -A field of width \code{n} can be created from a single bit using \code{Fill}: -\begin{scala} -def Fill(n: Int, field: Bits): Bits -\end{scala} - -\noindent -and two inputs can be selected using \code{Mux}: - -\begin{scala} -def Mux[T <: Data](sel: Bits, cons: T, alt: T): T -\end{scala} - -\noindent - -Constant or literal values are expressed using Scala integers or -strings passed to constructors for the types: -\begin{scala} -UInt(1) // decimal 1-bit lit from Scala Int. -UInt("ha") // hex 4-bit lit from string. -UInt("o12") // octal 4-bit lit from string. -UInt("b1010") // binary 4-bit lit from string. -\end{scala} - -\noindent -producing a \code{Lit} as shown in the -leftmost subfigure of Figure~\ref{fig:bits-expressions}. - -Operations return an actual operator node with a type node combining -the input type nodes. See Figure~\ref{fig:bits-expressions} for -successively more complicated examples. - -\begin{figure*} -\begin{center} -\begin{tabular}{ccc} -\includegraphics[height=0.94in]{figs/bits-1.pdf} & -\includegraphics[height=1.96in]{figs/bits-and.pdf} & -\includegraphics[height=3.0in]{figs/bits-or-and.pdf} \\ -\kode{a = UInt(1)} & \kode{b = a \& UInt(2)} & -\kode{b | UInt(3)} \\ -\end{tabular} -\end{center} -\caption{Chisel Op/Lit graphs constructed with algebraic expressions - showing the insertion of type nodes.} -\label{fig:bits-expressions} -\end{figure*} - - -\subsection{Bools} - -Boolean values are represented as \code{Bool}s: - -\begin{scala} -object Bool { - def apply(dir: PortDir = null): Bool - // create literal - def apply(value: Boolean): Bool -} - -class Bool extends UInt -\end{scala} - -\noindent -\code{Bool} is equivalent to \code{UInt(width = 1)}. - -\subsection{Nums} - -\code{Num} is a type node which defines arithmetic operations: - -\begin{scala} -class Num extends Bits { - // Negation - def unary_-(): Bits - // Addition - def +(b: Num): Num - // Subtraction - def -(b: Num): Num - // Multiplication - def *(b: Num): Num - // Greater than - def >(b: Num): Bool - // Less than - def <(b: Num): Bool - // Less than or equal - def <=(b: Num): Bool - // Greater than or equal - def >=(b: Num): Bool -} -\end{scala} - -% // Modulus -% def %(b: Num): Num -% // Division -% def /(b: Num): Num - -Signed and unsigned integers -are considered subsets of fixed-point numbers and are represented by -types \code{SInt} and \code{UInt} respectively: - -\begin{scala} -object SInt { - def apply (dir: PortDir = null, - width: Int = -1): SInt - // create literal - def apply (value: BigInt, width: Int = -1): SInt - def apply (value: String, width: Int = -1): SInt -} - -class SInt extends Num - -object UInt { - def apply(dir: PortDir = null, - width: Int = -1): UInt - // create literal - def apply(value: BigInt, width: Int = -1): UInt - def apply(value: String, width: Int = -1): UInt -} - -class UInt extends Num { - // arithmetic right shift - override def >> (b: UInt): SInt -} -\end{scala} - -\noindent -Signed fixed-point -numbers, including integers, are represented using two's-complement -format. - -\subsection{Bundles} - -Bundles group together several named fields of potentially different -types into a coherent unit, much like a \code{struct} in C: - -\begin{scala} -class Bundle extends Data { - // shallow named bundle elements - def elements: ArrayBuffer[(String, Data)] -} -\end{scala} - -\noindent -The name and type of each element in a Bundle can be obtained with the -\code{elements} method, and the \code{flatten} method returns the -elements at the leaves for nested aggregates. Users can define new -bundles by subclassing \code{Bundle} as follows: - -\begin{scala} -class MyFloat extends Bundle { - val sign = Bool() - val exponent = UInt(width = 8) - val significand = UInt(width = 23) -} -\end{scala} -\noindent -Elements are accessed using Scala field access: - -\begin{scala} -val x = new MyFloat() -val xs = x.sign -\end{scala} - -The names given to a bundle's elements when they are emitted by a C++ -or Verilog backend are obtained from their bundle field names, using -Scala introspection. - -\subsection{Vecs} - -Vecs create an indexable vector of elements: - -\begin{scala} -object Vec { - def apply[T <: Data](elts: Seq[T]): Vec[T] - def apply[T <: Data](elt0: T, elts: T*): Vec[T] - def fill[T <: Data](n: Int)(type: => T): Vec[T] - def tabulate[T <: Data](n: Int) - (type: (Int) => T): Vec[T] - def tabulate[T <: Data](n1: Int, n2: Int) - (type: (Int, Int) => T): Vec[Vec[T]] -} - -class Vec[T <: Data](n: Int, val type: () => T) - extends Data { - def apply(idx: UInt): T - def apply(idx: Int): T - def forall(p: T => Bool): Bool - def exists(p: T => Bool): Bool - def contains[T <: Bits](x: T): Bool - def count(p: T => Bool): UInt - def indexWhere(p: T => Bool): UInt - def lastIndexWhere(p: T => Bool): UInt -} -\end{scala} - -\noindent -with \code{n} elements of type defined with the \code{gen} thunk. -Users can access elements statically with an \code{Int} index or -dynamically using a \code{UInt} index, -where dynamic access creates a virtual type node (representing a read -``port'') that records the read using the given address. In either case, -users can wire to the result of a read as follows: - -\begin{scala} -v(a) := d -\end{scala} - -Read-only memories can be expressed as Vecs of literals: - -\begin{scala} -val rom = Vec(UInt(3), UInt(7), UInt(4), UInt(0)) { UInt(width=3) } -val dout = rom(addr) -\end{scala} - -% TODO: conditionally assigning to elements - -\subsection{Bit Width Inference} - -Users are required to set bit widths of ports and registers, but otherwise, -bit widths on nodes are automatically inferred unless set manually by -the user (using \code{Extract} or \code{Cat}). -The bit-width inference engine starts from the graph's input ports and -calculates node output bit widths from their respective input bit widths according to the following set of rules:\\[-2mm] - -{\small -\begin{tabular}{ll} -{\bf operation} & {\bf bit width} \\ -\verb|z = x + y| & \verb+wz = max(wx, wy)+ \\ -\verb+z = x - y+ & \verb+wz = max(wx, wy)+\\ -\verb+z = x & y+ & \verb+wz = max(wx, wy)+ \\ -\verb+z = Mux(c, x, y)+ & \verb+wz = max(wx, wy)+ \\ -\verb+z = w * y+ & \verb!wz = wx + wy! \\ -\verb+z = x << n+ & \verb!wz = wx + maxNum(n)! \\ -\verb+z = x >> n+ & \verb+wz = wx - minNum(n)+ \\ -\verb+z = Cat(x, y)+ & \verb!wz = wx + wy! \\ -\verb+z = Fill(n, x)+ & \verb+wz = wx * maxNum(n)+ \\ -% \verb+z = x < y+ & \verb+<= > >= && || != ===+ & \verb+wz = 1+ \\ -\end{tabular} -} -\\[1mm] -\noindent -where for instance $wz$ is the bit width of wire $z$, and the \verb+&+ -rule applies to all bitwise logical operations. - -The bit-width inference process continues until no bit width changes. -Except for right shifts by known constant amounts, the bit-width -inference rules specify output bit widths that are never smaller than -the input bit widths, and thus, output bit widths either grow or stay -the same. Furthermore, the width of a register must be specified by -the user either explicitly or from the bitwidth of the reset value. -From these two requirements, we can show that the bit-width inference -process will converge to a fixpoint. - -\begin{example} -Shouldn't & return bitwidth that is min() of inputs? -\end{example} - - -\section{Updateables} - -\label{sec:wires} - -When describing the operation of wire and state nodes, it is often -useful to give the specification as a series of conditional updates to -the output value and to spread out these updates across several -separate statements. For example, the output of a Data node can be -referenced immediately, but its input can be set later. -\code{Updateable} represents a conditionally updateable node, which -accumulates accesses to the node and which can later generate muxes to -combine these accesses in the circuit. - -\begin{scala} -abstract class Updateable extends Node { - // conditional reads - def reads: Queue[(Bool, UInt)] - // conditional writes - def writes: Queue[(Bool, UInt, Node)] - // gen mux integrating all conditional writes - def genMuxes(default: Node) - override def := (x: Node): this.type -} -\end{scala} - -Chisel provides conditional update rules in the form of the -\code{when} construct to support this style of sequential logic -description: - -\begin{scala} -object when { - def apply(cond: Bool)(block: => Unit): when -} - -class when (prevCond: Bool) { - def elsewhen (cond: Bool)(block: => Unit): when - def otherwise (block: => Unit): Unit -} -\end{scala} - -\noindent -\code{when} manipulates a global condition stack with dynamic scope. -Therefore, \code{when} creates a new condition that is in force across -function calls. For example: - -\begin{scala} -def updateWhen (c: Bool, d: Data) = - when (c) { r := d } -when (a) { - updateWhen(b, x) -} -\end{scala} - -\noindent -is the same as: - -\begin{scala} -when (a) { - when (b) { r := x } -} -\end{scala} - -% TODO: talk about conds - -Chisel provides some syntactic sugar for other common forms of -conditional updates: - -\begin{scala} -def unless(c: Bool)(block: => Unit) = - when (!c) { block ) -\end{scala} - -\noindent -and - -\begin{scala} -def otherwise(block: => Unit) = - when (Bool(true)) { block } -\end{scala} - -We introduce the \code{switch} statement for conditional updates -involving a series of comparisons against a common key: - -\begin{scala} -def switch(c: UInt)(block: => Unit): Unit - -def is(v: Bool)(block: => Unit) -\end{scala} - -\section{Forward Declarations} - -Purely combinational circuits are not allowed to have cycles between -nodes, and Chisel will report an error if such a cycle is detected. -Because they do not have cycles, legal combinational circuits can -always be constructed in a feed-forward manner, by adding new nodes -whose inputs are derived from nodes that have already been defined. -Sequential circuits naturally have feedback between nodes, and so it -is sometimes necessary to reference an output wire before the -producing node has been defined. Because Scala evaluates program -statements sequentially, we have allowed data nodes to serve as a wire -providing a declaration of a node that can be used immediately, but -whose input will be set later. For example, in a simple CPU, we need -to define the \verb!pcPlus4! and \verb!brTarget! wires so they can be -referenced before definition: -\begin{scala} -val pcPlus4 = UInt() -val brTarget = UInt() -val pcNext = Mux(pcSel, brTarget, pcPlus4) -val pcReg = RegUpdate(pcNext) -pcPlus4 := pcReg + UInt(4) -... -brTarget := addOut -\end{scala} - -\noindent -The wiring operator -\verb!:=! is used to wire up -the connection after \verb!pcReg! and \verb!addOut! are defined. -After all assignments are made and the circuit is being elaborated, -it is an error if a forward declaration is unassigned. - -\section{Regs} - -The simplest form of state element supported by Chisel is a -positive-edge-triggered register defined as follows: - -\begin{scala} -object Reg { - def apply[T <: Data] - (type: T, next: T = null, init: T = null): T -} - -object RegNext { - def apply[T <: Data] (next: T, init: T = null): T -} - -object RegInit { - def apply[T <: Data] (init: T): T -} - -class Reg extends Updateable -\end{scala} - -\noindent -where it can be constructed as follows: - -\begin{scala} -val r1 = RegUpdate(io.in) -val r2 = RegReset(UInt(1, 8)) -val r3 = RegUpdate(io.in, UInt(1)) -val r4 = Reg(UInt(width = 8)) -\end{scala} - -\noindent -where \code{resetVal} is the value a reg takes on when implicit -\code{reset} is \code{Bool(true)}. - -\section{Mems} - -Chisel supports random-access memories via the Mem construct. Writes to Mems -are positive-edge-triggered and reads are either combinational or -positive-edge-triggered. - -\begin{scala} -object Mem { - def apply[T <: Data](type: T, depth: Int, - seqRead: Boolean = false): Mem -} - -class Mem[T <: Data](type: T, depth: Int, - seqRead: Boolean = false) - extends Updateable { - def apply(idx: UInt): T -} -\end{scala} - -Ports into Mems are created by applying a \code{UInt} index. A 32-entry -register file with one write port and two combinational read ports might be -expressed as follows: - -\begin{scala} -val rf = Mem(UInt(width = 64), 32) -when (wen) { rf(waddr) := wdata } -val dout1 = rf(waddr1) -val dout2 = rf(waddr2) -\end{scala} - -If the optional parameter seqRead is set, Chisel will attempt to infer -sequential read ports when a Reg is assigned the output of a Mem. A one-read, -one-write SRAM might be described as follows: - -\begin{scala} -val ram1r1w = - Mem(UInt(width = 32), 1024, seqRead = true) -val dout = Reg(UInt()) -when (wen) { ram1r1w(waddr) := wdata } -when (ren) { dout := ram1r1w(raddr) } -\end{scala} - -Single-ported SRAMs can be inferred when the read and write conditions are -mutually exclusive in the same \code{when} chain: - -\begin{scala} -val ram1p = - Mem(UInt(width = 32), 1024, seqRead = true) -val dout = Reg(UInt()) -when (wen) { ram1p(waddr) := wdata } -.elsewhen (ren) { dout := ram1p(raddr) } -\end{scala} - -If the same Mem address is both written and sequentially read on the same clock -edge, or if a sequential read enable is cleared, then the read data is -implementation-defined. - -Mem also supports write masks for subword writes. A given bit is written if -the corresponding mask bit is set. - -\begin{scala} -val ram = Mem(UInt(width = 32), 256) -when (wen) { ram.write(waddr, wdata, wmask) } -\end{scala} - -\section{Ports} -\label{sec:ports} - -Ports are \code{Data} derived nodes used as interfaces to hardware -modules. A port is a directional version of a primitive -\code{Data} object. Port directions are defined as follows: - -\begin{scala} -trait PortDir -object INPUT extends PortDir -object OUTPUT extends PortDir -\end{scala} - -\noindent -Aggregate ports can be recursively constructed using either a vec or -bundle with instances of \code{Port}s as leaves. - -\section{Modules} - -In Chisel, {\em modules} are very similar to {\em modules} in -Verilog, defining a hierarchical structure in the generated circuit. -The hierarchical module namespace is accessible in downstream tools -to aid in debugging and physical layout. A user-defined module is -defined as a {\em class} which: -\begin{itemize} -\item inherits from \code{Module}, -\item contains an interface Bundle stored in a field named \code{io}, and -\item wires together subcircuits in its constructor. -\end{itemize} - -Users write their own modules by subclassing Module which is -defined as follows: - -\begin{scala} -abstract class Module { - val io: Bundle - var name: String = "" - def compileV: Unit - def compileC: Unit -} -\end{scala} - -\noindent -and defining their own \code{io} field. For example, to define a two -input mux, we would define a module as follows: - -\begin{scala} -class Mux2 extends Module { - val io = new Bundle{ - val sel = Bool(INPUT) - val in0 = Bool(INPUT) - val in1 = Bool(INPUT) - val out = Bool(OUTPUT) - } - io.out := (io.sel & io.in1) | (~io.sel & io.in0) -} -\end{scala} - -\noindent -The \code{:=} assignment operator, used in the body of a -module definition, is a special operator in Chisel that wires the input of -left-hand side to the output of the right-hand side. It is typically -used to connect an output port to its definition. - -The \code{<>} operator bulk connects interfaces of opposite gender between -sibling modules or interfaces of same gender between parent/child modules. -Bulk connections connect leaf ports using pathname matching. -Connections are only made if one of the ports is non-null, -allowing users to repeatedly bulk-connect partially filled interfaces. -After all connections are made and the circuit is being elaborated, -Chisel warns users if ports have other than exactly one connection to them. - -The names given to the nodes and submodules stored in a module -when they are emitted by a C++ or Verilog backend are obtained from -their module field names, using Scala introspection. - -% TODO: what is same name -- is it a pathname? - -\section{BlackBox} - -Black boxes allow users to define interfaces to circuits defined -outside of Chisel. The user defines: - -\begin{itemize} -\item a module as a subclass of \code{BlackBox} and -\item an \code{io} field with the interface. -\end{itemize} - -\noindent -For example, one could define a simple ROM blackbox as: - -\begin{scala} -class RomIo extends Bundle { - val isVal = Bool(INPUT) - val raddr = UInt(INPUT, 32) - val rdata = UInt(OUTPUT, 32) -} - -class Rom extends BlackBox { - val io = new RomIo() -} -\end{scala} - -\section{Printf and Sprintf} - -Chisel provides the ability to format and print strings for debugging -purposes. The \code{printf} and \code{sprintf} construct are similar to their -C namesakes: they take a format string and a variable number of arguments, -then print or return a string, respectively. During simulation, \code{printf} -prints the formatted string to the console on rising clock edges. -\code{sprintf}, on the other hand, returns the formatted string as a bit -vector. - -Supported format specifiers are \code{\%b} (binary number), \code{\%d} -(decimal number), \code{\%x} (hexadecimal number), and \code{\%s} (string -consisting of a sequence of 8-bit extended ASCII characters). (\code{\%\%} -specifies a literal \code{\%}.) Unlike in C, there are no width modifiers: the -bit width of the corresponding argument determines the width in the string -representation. - -The following example prints the line \code{"0x4142 16706 AB"} on cycles when -\code{c} is true: - -\begin{scala} -val x = Bits(0x4142) -val s1 = sprintf("%x %s", x, x); -when (c) { printf("%d %s\n", x, s1); } -\end{scala} - -\section{Assert} - -Runtime assertions are provided by the \code{assert} construct. During -simulation, if an assertion's argument is false on a rising clock edge, -an error is printed and simulation terminates. For example, the following -will terminate simulation after ten clock cycles: - -\begin{scala} -val x = Reg(init = UInt(0, 4)) -x := x + UInt(1) -assert(x < UInt(10)) -\end{scala} - -\section{Main and Testing} - -In order to construct a circuit, -the user calls \code{chiselMain} from their top level \code{main} function: - -\begin{scala} -object chiselMain { - def apply[T <: Module] - (args: Array[String], comp: () => T): T -} -\end{scala} - -\noindent -which when run creates C++ files named -\code{{\it module\_name}.cpp} and \code{{\it module\_name}.h} in -the directory specified with -\code{-{-}targetDir {\it dir\_name}} argument. - -% \begin{scala} -% class TestIO -% (val format: String, val args: Seq[Data] = null) -% -% class Scanner extends TestIO -% -% class Printer extends TestIO -% -% object chiselMainDebug { -% def apply[T <: Module] -% (args: Array[String], comp: () => T)( -% scanner: T => TestIO, -% printer: T => TestIO) -% } -% \end{scala} -% -% \noindent -% -% We can use the \code{chiselMainDebug} call and \code{TestIO} objects as follows: -% -% \begin{scala} -% object tutorial { -% def main(args: Array[String]) = { -% val dargs = args ++ Array("--genHarness") -% chiselMainDebug(dargs, () => new Mux2())( -% c => Scanner("%x %x %x", -% c.io.sel, c.io.in0, c.io.in1), -% c => Printer("%x %x %x %x", -% c.io.sel, c.io.in0, c.io.in1, -% c.io.out)) -% } -% } -% \end{scala} -% -% \noindent -% where the first three hex numbers from each line are read in from -% standard input and bound to the \code{sel}, \code{in0}, and -% \code{in1} inputs of the multiplexer circuit, and the multiplexer -% inputs and \code{out} are printed out in hex format. -% -% Alternatively, a user can specify the scanned inputs and printed -% outputs using aggregate data and one format directive per aggregate. -% For example, the following accomplishes the same scanning / printing -% as above: -% -% \begin{scala} -% object tutorial { -% def main(args: Array[String]) = { -% val dargs = args ++ Array("--genHarness") -% chiselMainDebug(dargs, () => new Mux2())( -% c => Scanner("%x", c.io), -% c => Printer("%x", c.io) -% } -% } -% \end{scala} -% -% Using \code{--generate-harness} for \code{Mux2} -% creates a \code{Mux2-emulator.cpp} and \code{Mux2-makefile} in directory -% specified by \code{--targetDir}. The user can then compile it using: -% -% \begin{scala} -% make -f Mux2-makefile -% \end{scala} -% -% \noindent -% -% A user can test the multiplexer by creating a test file called -% \code{test.out} containing: -% \begin{scala} -% 0 0 0 0 -% 0 0 1 0 -% 0 1 0 1 -% 0 1 1 1 -% 1 0 0 0 -% 1 0 1 1 -% 1 1 0 0 -% 1 1 1 1 -% \end{scala} -% -% \noindent -% and can be compared using a script as follows -% -% \begin{scala} -% cut -f 1,2,3 -d " " < test | Mux2 > test.out -% diff test.out test -% \end{scala} - -\begin{figure} -\begin{center} -\includegraphics[width=0.45\textwidth]{../tutorial/figs/DUT.pdf} -\end{center} -\caption{DUT run using a Tester object in Scala with stdin and stdout connected} -\label{fig:dut} -\end{figure} - -Testing is a crucial part of circuit design, -and thus in Chisel we provide a mechanism for -testing circuits by providing test vectors within Scala using -subclasses of the \code{Tester} class: - -\begin{scala} -class Tester[T <: Module] - (val c: T, val isTrace: Boolean = true) { - var t: Int - var ok: Boolean - val rnd: Random - def int(x: Boolean): BigInt - def int(x: Int): BigInt - def int(x: Bits): BigInt - def reset(n: Int = 1) - def step(n: Int): Int - def pokeAt(data: Mem[T], index: Int, x: BigInt) - def poke(data: Bits, x: BigInt) - def poke(data: Aggregate, x: Array[BigInt]) - def peekAt(data: Mem[T], index: Int) - def peek(data: Bits): BigInt - def peek(data: Aggregate): Array[BigInt] - def expect (good: Boolean, msg: String): Boolean - def expect (data: Bits, target: BigInt): Boolean -} -\end{scala} - -\noindent -which binds a tester to a module -and allows users to write tests using the given debug protocol. In particular, users utilize: -\begin{itemize} -\item \code{poke} to set input port and state values, -\item \code{step} to execute the circuit one time unit, -\item \code{peek} to read port and state values, and -\item \code{expect} to compare peeked circuit values to expected arguments. -\end{itemize} - -\noindent -Users connect tester instances to modules using: - -\begin{scala} -object chiselMainTest { - def apply[T <: Module] - (args: Array[String], comp: () => T)( - tester: T => Tester[T]): T -} -\end{scala} - -\noindent -When \code{-{-}test} is given as an argument to \code{chiselMain}, a -tester instance runs the Design Under Test (DUT) in a separate -process with \code{stdin} and \code{stdout} connected so that debug commands can -be sent to the DUT and responses can be received from the DUT as shown in -Figure~\ref{fig:dut}. -\noindent - -For example, in the following: - -\begin{scala} -class Mux2Tests(c: Mux2) extends Tester(c) { - val n = pow(2, 3).toInt - for (s <- 0 until 2) { - for (i0 <- 0 until 2) { - for (i1 <- 0 until 2) { - poke(c.io.sel, s) - poke(c.io.in1, i1) - poke(c.io.in0, i0) - step(1) - expect(c.io.out, (if (s == 1) i1 else i0)) - } - } - } -} -\end{scala} - -\noindent -assignments for each input of \verb+Mux2+ is set to the appropriate values using \verb+poke+. For this particular example, we are testing the \verb+Mux2+ by hardcoding the inputs to some known values and checking if the output corresponds to the known one. To do this, on each iteration we generate appropriate inputs to the module and tell the simulation to assign these values to the inputs of the device we are testing \verb+c+, step the circuit, and test the expected value. -Finally, the following shows how the tester is invoked: - -\begin{scala} -chiselMainTest(args + "--test", () => new Mux2()){ - c => new Mux2Tests(c) -} -\end{scala} - -Finally, command arguments for \code{chiselMain*} are as follows: \\ - -\begin{tabular}{lll} -\verb+--targetDir+ & target pathname prefix \\ -\verb+--genHarness+ & generate harness file for C++ \\ -\verb+--debug+ & put all wires in C++ class file \\ -\verb+--compile+ & compiles generated C++ \\ -\verb+--test+ & runs tests using C++ app \\ -\verb+--backend v+ & generate verilog \\ -\verb+--backend c+ & generate C++ (default)\\ -\verb+--vcd+ & enable vcd dumping \\ -\end{tabular} - - -\section{C++ Emulator} - -The C++ emulator is based on a fast multiword library using -C++ templates. -A single word is defined by \code{val\_t} as follows: - -\begin{cpp} -typedef uint64_t val_t; -typedef int64_t sval_t; -typedef uint32_t half_val_t; -\end{cpp} - -\noindent -and multiwords are defined by \code{dat\_t} as follows: - -\begin{cpp} -template -class dat_t { - public: - const static int n_words; - inline int width ( void ); - inline int n_words_of ( void ); - inline bool to_bool ( void ); - inline val_t lo_word ( void ); - inline unsigned long to_ulong ( void ); - std::string to_str (); - dat_t (); -template - dat_t (const dat_t& src); - dat_t (const dat_t& src); - dat_t (val_t val); -template - dat_t mask(dat_t fill, int n); -template - dat_t mask(int n); -template - dat_t mask(void); - dat_t operator + ( dat_t o ); - dat_t operator - ( dat_t o ); - dat_t operator - ( ); - dat_t operator * ( dat_t o ); - dat_t fix_times_fix( dat_t o ); - dat_t ufix_times_fix( dat_t o ); - dat_t fix_times_ufix( dat_t o ); - dat_t<1> operator < ( dat_t o ); - dat_t<1> operator > ( dat_t o ); - dat_t<1> operator >= ( dat_t o ); - dat_t<1> operator <= ( dat_t o ); - dat_t<1> gt ( dat_t o ); - dat_t<1> gte ( dat_t o ); - dat_t<1> lt ( dat_t o ); - dat_t<1> lte ( dat_t o ); - dat_t operator ^ ( dat_t o ); - dat_t operator & ( dat_t o ); - dat_t operator | ( dat_t o ); - dat_t operator ~ ( void ); - dat_t<1> operator ! ( void ); - dat_t<1> operator && ( dat_t<1> o ); - dat_t<1> operator || ( dat_t<1> o ); - dat_t<1> operator == ( dat_t o ); - dat_t<1> operator == ( datz_t o ); - dat_t<1> operator != ( dat_t o ); - dat_t operator << ( int amount ); - dat_t operator << ( dat_t o ); - dat_t operator >> ( int amount ); - dat_t operator >> ( dat_t o ); - dat_t rsha ( dat_t o); - dat_t& operator = ( dat_t o ); - dat_t fill_bit(val_t bit); - dat_t fill_byte - (val_t byte, int nb, int n); -template - dat_t fill( void ); -template - dat_t fill( dat_t n ); -template - dat_t extract(); -template - dat_t extract(val_t e, val_t s); -template - dat_t extract - (dat_t e, dat_t s); -template - dat_t inject - (dat_t src, val_t e, val_t s); -template - dat_t inject - (dat_t src, - dat_t e, dat_t s); -template - dat_t log2(); - dat_t<1> bit(val_t b); - val_t msb(); -template - dat_t<1> bit(dat_t b) -} -\end{cpp} - -\begin{cpp} -template - dat_t DAT(dat_t dat); -template - dat_t LIT(val_t value); -template dat_t - mux ( dat_t<1> t, dat_t c, dat_t a ) -\end{cpp} - -\noindent -where \code{w} is the bit width parameter. - -The Chisel compiler compiles top level modules into a single flattened \code{mod\_t} -class that can be created and executed: - -\begin{cpp} -class mod_t { - public: - // initialize module - virtual void init (void) { }; - // compute all combinational logic - virtual void clock_lo (dat_t<1> reset) { }; - // commit state updates - virtual void clock_hi (dat_t<1> reset) { }; - // print printer specd node values to stdout - virtual void print (FILE* f) { }; - // scan scanner specd node values from stdin - virtual bool scan (FILE* f) { return true; }; - // dump vcd file - virtual void dump (FILE* f, int t) { }; -}; -\end{cpp} - -Either the Chisel compiler can create a harness or the user can write -a harness themselves. The following is an example of a harness for a -CPU module: - -\begin{cpp} -#include "cpu.h" - -int main (int argc, char* argv[]) { - cpu_t* c = new cpu_t(); - int lim = (argc > 1) ? atoi(argv[1]) : -1; - c->init(); - for (int t = 0; lim < 0 || t < lim; t++) { - dat_t<1> reset = LIT<1>(t == 0); - if (!c->scan(stdin)) break; - c->clock_lo(reset); - c->clock_hi(reset); - c->print(stdout); - } -} -\end{cpp} - -\section{Verilog} - -Chisel generates Verilog when the \code{--v} argument is passed into -\code{chiselMain}. For example, from SBT, the following - -\begin{scala} -run --v -\end{scala} - -\noindent -would produce a single Verilog file named \code{{\it module-name}.v} in -the target directory. -The file will contain one module per module defined as submodules of -the top level module created in \code{chiselMain}. Modules with -the same interface and body are cached and reused. - -\section{Multiple Clock Domains} - -Chisel 2.0 introduced support of multiple clock domains. - -\subsection{Creating Clock domains} - -In order to use multiple clock domains, users must create multiple clocks. -In Chisel, clocks are first class nodes created with a reset signal parameter and defined as follows: - -\begin{scala} -class Clock (reset: Bool) extends Node { - def reset: Bool // returns reset pin -} -\end{scala} - -\noindent -% Having reset in clock makes it easier to pass around. -In Chisel there is a builtin implicit clock that state elements use by default: - -\begin{scala} -var implicitClock = new Clock( implicitReset ) -\end{scala} - -The clock for state elements and modules can be defined using an additional named parameter called clock: - -\begin{scala} -Reg(... clock: Clock = implicitClock) -Mem(... clock: Clock = implicitClock) -Module(... clock: Clock = implicitClock) -\end{scala} - -\subsection{Crossing Clock Domains} - -There are two ways that circuits can be defined to send data between clock domains. -The first and most primitive way is by using a synchronizer circuit comprised of two registers as follows: - -\begin{scala} -// signalA is in clock domain clockA, -// want a version in clockB as signalB -val s1 = Reg(init = UInt(0), clock = clockB) -val s2 = Reg(init = UInt(0), clock = clockB) -s1 := signalA -s2 := s1; -signalB := s2 -\end{scala} - -\noindent -Due to metastability issues, this technique is limited to communicating one bit data between domains. - -The second and more general way to send data between domains is by using an asynchronous queue: - -\begin{scala} -class AsyncQueue[T<:Data](gen: T, depth: Int, enq_clk: Clock, deq_clock: Clock) - extends Module -\end{scala} - -\noindent -We can then get a version of signalA from clock domains clockA to clockB by specifying the standard queue parameters and the two clocks and then using the standard decoupled ready/valid signals: - -\begin{scala} -val queue = new AsyncQueue(Uint(width = 32), 2, clockA, clockB) -fifo.enq.bits := signalA -signalB := fifo.deq.bits -fifo.valid := condA -fifo.ready := condB -... -\end{scala} - -\subsection{Backend Specific Multiple Clock Domains} - -Clock domains can be mapped to both the C++ and Verilog backends in a domain-specific manner. For the purposes of showing how to drive a multi clock design, consider the example of hardware with two modules communicating using an AsyncQueue with each module on separate clocks: \verb+fastClock+ and \verb+slowClock+. - -\subsubsection{C++} - -In the C++ backend, for every clock \verb+i+ there is a -\begin{itemize} -\item \verb+uint64_t clk_i+ field representing the clock \verb+i+'s period, -\item \verb+uint63_t clk_i_cnt+ field representing the clock \verb+i+'s current count, -\item \verb+clock_lo_i+ and \verb+clock_hi_i+, -\item \verb+int reset()+ function which ensures that all \verb+clock_lo+ and \verb+clock_hi+ functions are called at least once, and -\item \verb+int clock(reset)+ function which computes min delta, invokes appropriate \verb+clock_lo+ and \verb+clock_hi+'s and returns min delta used. -\end{itemize} - -\noindent -In order to set up a C++ simulation, the user -\begin{itemize} -\item initializes all period fields to desired period -\item initializes all count fields to desired phase, -\item calls \verb+reset+ and then -\item repeated calls clock to step the simulation. -\end{itemize} - -\noindent -The following is a C++ example of a main function for the \verb+slowClock+ / \verb+fastClock+ example: - -\begin{scala} -int main(int argc, char** argv) { - ClkDomainTest_t dut; - dut.init(1); - dut.clk = 2; - dut.clk_cnt = 1; - dut.fastClock = 4; - dut.fastClock_cnt = 0; - dut.slowClock = 6; - dut.slowClock_cnt = 0; - for (int i = 0; i < 12; i ++) - dut.reset(); - for (int i = 0; i < 96; i ++) - dut.clock(LIT<1>(0)); -} -\end{scala} - -\subsubsection{Verilog} - -In Verilog, - -\begin{itemize} -\item Chisel creates a new port for each clock / reset, -\item Chisel wires all the clocks to the top module, and -\item the user must create an \verb+always+ block clock driver for every clock \verb+i+. -\end{itemize} - -\noindent -The following is a Verilog example of a top level harness to drive the \verb+slowClock+ / \verb+fastClock+ example circuit: - -\begin{scala} -module emulator; - reg fastClock = 0, slowClock = 0, - resetFast = 1, resetSlow = 1; - wire [31:0] add, mul, test; - always #2 fastClock = ~fastClock; - always #4 slowClock = ~slowClock; - initial begin - #8 - resetFast = 0; - resetSlow = 0; - #400 - $finish; - end - ClkDomainTest dut ( - .fastClock(fastClock), - .slowClock(slowClock), - .io_resetFast(resetFast), - .io_resetSlow(resetSlow), - .io_add(add), .io_mul(mul), .io_test(test)); -endmodule -\end{scala} - -\noindent -See \url{http://www.asic-world.com/verilog/verifaq2.html} for more information about simulating clocks in Verilog. - - -\section{Extra Stuff} - -\lstset{language=scala} - -\begin{scala} -def ListLookup[T <: Bits] - (addr: UInt, default: List[T], - mapping: Array[(UInt, List[T])]): List[T] - -def Lookup[T <: Data] - (addr: UInt, default: T, - mapping: Seq[(UInt, T)]): T - -// n-way multiplexor -def MuxCase[T <: Data] - (default: T, mapping: Seq[(Bool, T)]): T - -// n-way indexed multiplexer: -def MuxLookup[S <: UInt, T <: Data] - (key: S, default: T, mapping: Seq[(S, T)]): T -\end{scala} - -% TODO: PROBE -% \begin{scala} -% Probe -% \end{scala} - -\begin{scala} -// create n enum values of given type -def Enum[T <: UInt] - (n: Int)(type: => T): List[T] - -// create enum values of given type and names -def Enum[T <: UInt] - (l: Symbol *)(type: => T): Map[Symbol, T] - -// create enum values of given type and names -def Enum[T <: UInt] - (l: List[Symbol])(type: => T): Map[Symbol, T] -\end{scala} - -% \section{Name Mangling} -% -% \begin{itemize} -% \item separate and escape sequence -% \item module prefix -% \item vec element suffixes -% \item naming from fields -% \item bundle field paths -% \item target language reserve word avoidance -% \end{itemize} - -\section{Standard Library} - -\subsection{Math} - -\begin{scala} -// Returns the log base 2 of the input -// Scala Integer rounded up -def log2Up(in: Int): Int - -// Returns the log base 2 of the input -// Scala Integer rounded down -def log2Down(in: Int): Int - -// Returns true if the input Scala Integer -// is a power of 2 -def isPow2(in: Int): Boolean - -// linear feedback shift register -def LFSR16(increment: Bool = Bool(true)): UInt -\end{scala} - -\subsection{Sequential} - -\begin{scala} -// Returns the n-cycle delayed version -// of the input signal -// Has an optional enable signal defaulting to true -def ShiftRegister[T <: Data](in: T, n: Int, en = Bool(true)): T - -def Counter(cond: Bool, n: Int) = { - val c = RegReset(UInt(0, log2Up(n))) - val wrap = c === UInt(n-1) - when (cond) { - c := Mux(Bool(!isPow2(n)) && wrap, UInt(0), - c + UInt(1)) - } - (c, wrap && cond) -} -\end{scala} - -\subsection{UInt} - -\begin{scala} -// Returns the number of bits set in the -// input signal. Causes an exception if -// the input is wider than 32 bits. -def PopCount(in: UInt): UInt - -// Returns the reverse the input signal -def Reverse(in: UInt): UInt - -// returns the one hot encoding of -// the input UInt -def UIntToOH(in: UInt, width: Int): UInt - -// does the inverse of UIntToOH -def OHToUInt(in: UInt): UInt -def OHToUInt(in: Seq[Bool]): UInt - -// Builds a Mux tree out of the input -// signal vector using a one hot encoded -// select signal. Returns the output of -// the Mux tree -def Mux1H[T <: Data] - (sel: UInt, in: Vec[T]): T -def Mux1H[T <: Data] - (sel: Vec[Bool], in: Vec[T]): T - -// Builds a Mux tree under the -// assumption that multiple -// select signals can be enabled. -// Priority is given to the first -// select signal. Returns the output -// of the Mux tree. -def PriorityMux[T <: Data] - (sel: UInt, in: Seq[T]): T -def PriorityMux[T <: Data] - (sel: Seq[UInt], in: Seq[T]): T - -// Returns the bit position of the -// trailing 1 in the input vector with -// the assumption that multiple bits of -// the input bit vector can be set -def PriorityEncoder(in: UInt): UInt -def PriorityEncoder(in: Seq[Bool]): UInt - -// Returns the bit position of the -// trailing 1 in the input vector with -// the assumption that only one bit in -// the input vector can be set -def PriorityEncoderOH(in: UInt): UInt -def PriorityEncoderOH(in: Seq[Boo]): UInt -\end{scala} - -\subsection{Decoupled} - -\begin{scala} -// Adds a ready-valid handshaking -// protocol to any interface. The -// standard used is that the -// consumer uses the flipped -// interface. -class DecoupledIO[+T <: Data](type: T) - extends Bundle { - val ready = Bool(INPUT) - val valid = Bool(OUTPUT) - val bits = data.asOutput -} - -// Adds a valid protocol to any -// interface. The standard used is -// that the consumer uses the -// fliped interface. -class ValidIO[+T <: Data](type: T) - extends Bundle { - val valid = Bool(OUTPUT) - val bits = data.asOutput -} - -// Hardware module that is used to -// sequence n producers into 1 consumer. -// Priority is given to lower -// producer -// Example usage: -// val arb = new Arbiter(UInt(), 2) -// arb.io.in(0) <> producer0.io.out -// arb.io.in(1) <> producer1.io.out -// consumer.io.in <> arb.io.out -class Arbiter[T <: Data](type: T, n: Int) - extends Module - -// Hardware module that is used to -// sequence n producers into 1 consumer. -// Producers are chosen in round robin -// order -// Example usage: -// val arb = new RRArbiter(UInt(), 2) -// arb.io.in(0) <> producer0.io.out -// arb.io.in(1) <> producer1.io.out -// consumer.io.in <> arb.io.out -class RRArbiter[T <: Data](type: T, n: Int) - extends Module - -// Generic hardware queue. Required -// parameter entries controls the -// depth of the queues. The width of -// the queue is determined from the -// inputs. -// Example usage: -// val q = new Queue(UInt(), 16) -// q.io.enq <> producer.io.out -// consumer.io.in <> q.io.deq -class Queue[T <: Data] - (type: T, entries: Int, - pipe: Boolean = false, - flow: Boolean = false - flushable: Boolean = false) - extends Module - -// A hardware module that delays data -// coming down the pipeline by the -// number of cycles set by the -// latency parameter. Functionality -// is similar to ShiftRegister but -// this exposes a Pipe interface. -// Example usage: -// val pipe = new Pipe(UInt()) -// pipe.io.enq <> produce.io.out -// consumer.io.in <> pipe.io.deq -class Pipe[T <: Data] - (type: T, latency: Int = 1) extends Module - -\end{scala} - -% henry - -% \section{Acknowlegements} -% -% Many people have helped out in the design of Chisel, and we thank them -% for their patience, bravery, and belief in a better way. Many -% Berkeley EECS students in the Isis group gave weekly feedback as the -% design evolved including but not limited to Yunsup Lee, Andrew -% Waterman, Scott Beamer, Chris Celio, etc. Yunsup Lee gave us feedback -% in response to the first RISC-V implementation, called TrainWreck, -% translated from Verilog to Chisel. Andrew Waterman and Yunsup Lee -% helped us get our Verilog backend up and running and Chisel TrainWreck -% running on an FPGA. Brian Richards was the first actual Chisel user, -% first translating (with Huy Vo) John Hauser's FPU Verilog code to -% Chisel, and later implementing generic memory blocks. Brian gave many -% invaluable comments on the design and brought a vast experience in -% hardware design and design tools. Chris Batten shared his fast -% multiword C++ template library that inspired our fast emulation -% library. Huy Vo became our undergraduate research assistant and was -% the first to actually assist in the Chisel implementation. We -% appreciate all the EECS students who participated in the Chisel -% bootcamp and proposed and worked on hardware design projects all of -% which pushed the Chisel envelope. We appreciate the work that James -% Martin and Alex Williams did in writing and translating network and -% memory controllers and non-blocking caches. Finally, Chisel's -% functional programming and bit-width inference ideas were inspired by -% earlier work on a hardware description language called Gel~\cite{gel} designed in -% collaboration with Dany Qumsiyeh and Mark Tobenkin. -% -% % \note{Who else?} -% -\begin{thebibliography}{50} -\bibitem{chisel-dac12} Bachrach, J., Vo, H., Richards, B., Lee, Y., Waterman, - A., Avi\v{z}ienis, Wawrzynek, J., Asanovi\'{c} \textsl{Chisel: - Constructing Hardware in a Scala Embedded Language} -in DAC '12. -\bibitem{programming-in-scala}Odersky, M., Spoon, L., Venners, - B. \textsl{Programming in Scala} by Artima. -\bibitem{programming-scala}Payne, A., Wampler, D. - \textsl{Programming Scala} by O'Reilly books. -% \bibitem{gel} Bachrach, J., Qumsiyeh, D., Tobenkin, M. \textsl{Hardware Scripting in Gel}. -% in Field-Programmable Custom Computing Machines, 2008. FCCM '08. 16th. -\end{thebibliography} - - -\end{document} diff --git a/doc/parameters/beramono.sty b/doc/parameters/beramono.sty deleted file mode 100644 index fcbc324c..00000000 --- a/doc/parameters/beramono.sty +++ /dev/null @@ -1,32 +0,0 @@ -\ProvidesPackage{beramono}[2004/01/31 (WaS)] -\RequirePackage{keyval} -\define@key{Fvm}{scaled}[.9]{% - \def\fvm@Scale{#1}} -\def\ProcessOptionsWithKV#1{% - \let\@tempc\relax - \let\Fvm@tempa\@empty - \@for\CurrentOption:=\@classoptionslist\do{% - \@ifundefined{KV@#1@\CurrentOption}% - {}% - {% - \edef\Fvm@tempa{\Fvm@tempa,\CurrentOption,}% - \@expandtwoargs\@removeelement\CurrentOption - \@unusedoptionlist\@unusedoptionlist - }% - }% - \edef\Fvm@tempa{% - \noexpand\setkeys{#1}{% - \Fvm@tempa\@ptionlist{\@currname.\@currext}% - }% - }% - \Fvm@tempa - \let\CurrentOption\@empty -} -\ProcessOptionsWithKV{Fvm} -\AtEndOfPackage{% - \let\@unprocessedoptions\relax -} -\renewcommand{\ttdefault}{fvm} -\endinput -%% -%% End of file `beramono.sty'. diff --git a/doc/parameters/figs/alter.pdf b/doc/parameters/figs/alter.pdf deleted file mode 100644 index ea4ce36e..00000000 Binary files a/doc/parameters/figs/alter.pdf and /dev/null differ diff --git a/doc/parameters/figs/alterchain.pdf b/doc/parameters/figs/alterchain.pdf deleted file mode 100644 index 1bcc03c2..00000000 Binary files a/doc/parameters/figs/alterchain.pdf and /dev/null differ diff --git a/doc/parameters/figs/alterview.pdf b/doc/parameters/figs/alterview.pdf deleted file mode 100644 index 3f11b56e..00000000 Binary files a/doc/parameters/figs/alterview.pdf and /dev/null differ diff --git a/doc/parameters/figs/bex1.png b/doc/parameters/figs/bex1.png deleted file mode 100644 index 822da1da..00000000 Binary files a/doc/parameters/figs/bex1.png and /dev/null differ diff --git a/doc/parameters/figs/ex1.pdf b/doc/parameters/figs/ex1.pdf deleted file mode 100644 index 9b6985e5..00000000 Binary files a/doc/parameters/figs/ex1.pdf and /dev/null differ diff --git a/doc/parameters/figs/ex2.pdf b/doc/parameters/figs/ex2.pdf deleted file mode 100644 index fb09855b..00000000 Binary files a/doc/parameters/figs/ex2.pdf and /dev/null differ diff --git a/doc/parameters/figs/ex3.pdf b/doc/parameters/figs/ex3.pdf deleted file mode 100644 index d815664a..00000000 Binary files a/doc/parameters/figs/ex3.pdf and /dev/null differ diff --git a/doc/parameters/figs/ex4.pdf b/doc/parameters/figs/ex4.pdf deleted file mode 100644 index 6bf1ffef..00000000 Binary files a/doc/parameters/figs/ex4.pdf and /dev/null differ diff --git a/doc/parameters/figs/ex5.pdf b/doc/parameters/figs/ex5.pdf deleted file mode 100644 index 699ca2eb..00000000 Binary files a/doc/parameters/figs/ex5.pdf and /dev/null differ diff --git a/doc/parameters/figs/ex6.pdf b/doc/parameters/figs/ex6.pdf deleted file mode 100644 index 247834af..00000000 Binary files a/doc/parameters/figs/ex6.pdf and /dev/null differ diff --git a/doc/parameters/figs/figs.graffle b/doc/parameters/figs/figs.graffle deleted file mode 100644 index 4fdb8cde..00000000 --- a/doc/parameters/figs/figs.graffle +++ /dev/null @@ -1,4719 +0,0 @@ - - - - - ApplicationVersion - - com.omnigroup.OmniGrafflePro - 139.18.0.187838 - - CreationDate - 2014-08-26 00:25:08 +0000 - Creator - adamiz - FileType - flat - GraphDocumentVersion - 8 - GuidesLocked - NO - GuidesVisible - YES - ImageCounter - 3 - LinksVisible - NO - MagnetsVisible - NO - MasterSheets - - ModificationDate - 2014-08-30 01:30:50 +0000 - Modifier - adamiz - NotesVisible - NO - OriginVisible - NO - PageBreaks - NO - PrintInfo - - NSBottomMargin - - float - 41 - - NSHorizonalPagination - - coded - BAtzdHJlYW10eXBlZIHoA4QBQISEhAhOU051bWJlcgCEhAdOU1ZhbHVlAISECE5TT2JqZWN0AIWEASqEhAFxlwCG - - NSLeftMargin - - float - 18 - - NSPaperSize - - size - {612, 792} - - NSPrintReverseOrientation - - int - 0 - - NSRightMargin - - float - 18 - - NSTopMargin - - float - 18 - - - ReadOnly - NO - Sheets - - - ActiveLayerIndex - 0 - AutoAdjust - - BackgroundGraphic - - Bounds - {{0, 0}, {1423, 1085}} - Class - SolidGraphic - ID - 2 - Style - - shadow - - Draws - NO - - stroke - - Draws - NO - - - - BaseZoom - 0 - CanvasOrigin - {0, 0} - CanvasSize - {1423, 1085} - ColumnAlign - 1 - ColumnSpacing - 36 - DisplayScale - 1 0/72 in = 1.0000 in - GraphicsList - - - Class - Group - Graphics - - - Bounds - {{294.63357925415039, 380.70932470185664}, {57.756828308105469, 24.292869750392498}} - Class - ShapedGraphic - ID - 1265 - Shape - Rectangle - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1265\cocoasubrtf210 -\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc - -\f0\fs24 \cf0 D Cache} - - - - Bounds - {{294.63357925415039, 404.67831339018437}, {57.756828308105469, 63.636363983154297}} - Class - ShapedGraphic - FontInfo - - Color - - w - 0 - - Font - Helvetica - NSKern - 0.0 - Size - 12 - - ID - 1266 - Shape - Rectangle - Style - - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1265\cocoasubrtf210 -\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;\red239\green31\blue29;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc - -\f0\fs24 \cf2 sets\ -ways} - VerticalPad - 0 - - - - ID - 1264 - - - Class - Group - Graphics - - - Bounds - {{218.63357925415039, 380.70932470185664}, {57.756828308105469, 24.292869750392498}} - Class - ShapedGraphic - ID - 1196 - Shape - Rectangle - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1265\cocoasubrtf210 -\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc - -\f0\fs24 \cf0 I Cache} - - - - Bounds - {{218.63357925415039, 404.67831339018437}, {57.756828308105469, 63.636363983154297}} - Class - ShapedGraphic - FontInfo - - Color - - w - 0 - - Font - Helvetica - NSKern - 0.0 - Size - 12 - - ID - 1197 - Shape - Rectangle - Style - - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1265\cocoasubrtf210 -\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;\red239\green31\blue29;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc - -\f0\fs24 \cf2 sets\ -ways} - VerticalPad - 0 - - - - ID - 1195 - - - Class - Group - Graphics - - - Bounds - {{130.46661376953125, 385.03609664606915}, {76.090758527787159, 24.292869750392498}} - Class - ShapedGraphic - ID - 1232 - Shape - Rectangle - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1265\cocoasubrtf210 -\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc - -\f0\fs24 \cf0 Small Core} - - - - Bounds - {{130.46661451908778, 409.32894849074296}, {76.090758527787159, 54.658956938383128}} - Class - ShapedGraphic - FontInfo - - Color - - b - 0.113725 - g - 0.121569 - r - 0.937255 - - Font - Helvetica - NSKern - 0.0 - Size - 12 - - ID - 1233 - Shape - Rectangle - Style - - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1265\cocoasubrtf210 -\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;\red239\green31\blue29;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc - -\f0\fs24 \cf2 \expnd0\expndtw0\kerning0 -fpu} - VerticalPad - 0 - - - - ID - 1231 - - - Bounds - {{214.95525328036354, 292.36556616240142}, {65.113480255679178, 24.292869750392498}} - Class - ShapedGraphic - ID - 1193 - Shape - Rectangle - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1265\cocoasubrtf210 -\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc - -\f0\fs24 \cf0 Tile} - - - - Class - LineGraphic - Head - - ID - 1231 - - ID - 1326 - Points - - {239.24083045264209, 317.07606303961256} - {194.5014370674246, 385.03609664606915} - - Style - - stroke - - HeadArrow - FilledArrow - Legacy - - LineType - 1 - TailArrow - 0 - - - Tail - - ID - 1193 - - - - Class - LineGraphic - Head - - ID - 1195 - - ID - 1327 - Points - - {247.51201592475354, 317.15843591847334} - {247.5121290749658, 380.70932470185664} - - Style - - stroke - - HeadArrow - FilledArrow - Legacy - - LineType - 1 - TailArrow - 0 - - - Tail - - ID - 1193 - - - - Class - LineGraphic - Head - - ID - 1264 - - ID - 1328 - Points - - {255.47229818124524, 317.08084490040147} - {295.77052266344117, 380.70932470185664} - - Style - - stroke - - HeadArrow - FilledArrow - Legacy - - LineType - 1 - TailArrow - 0 - - - Tail - - ID - 1193 - - - - GridInfo - - HPages - 3 - KeepToScale - - Layers - - - Lock - NO - Name - Layer 1 - Print - YES - View - YES - - - LayoutInfo - - Animate - NO - AutoLayout - 2 - LineLength - 0.4643835723400116 - circoMinDist - 18 - circoSeparation - 0.0 - layoutEngine - dot - neatoSeparation - 0.0 - twopiSeparation - 0.0 - - Orientation - 2 - OutlineStyle - Basic - PrintOnePage - - RowAlign - 1 - RowSpacing - 36 - SheetTitle - Simple parameters - UniqueID - 1 - VPages - 2 - - - ActiveLayerIndex - 0 - AutoAdjust - - BackgroundGraphic - - Bounds - {{0, 0}, {943, 785}} - Class - SolidGraphic - FontInfo - - Font - Helvetica - Size - 11 - - ID - 2 - Style - - shadow - - Draws - NO - - stroke - - Draws - NO - - - - BaseZoom - 0 - CanvasOrigin - {0, 0} - CanvasSize - {943, 785} - ColumnAlign - 1 - ColumnSpacing - 36 - DisplayScale - 1 0/72 in = 1.0000 in - GraphicsList - - - Class - Group - Graphics - - - Bounds - {{385.1055793762207, 380.70932470185664}, {57.756828308105469, 24.292869750392498}} - Class - ShapedGraphic - ID - 1265 - Shape - Rectangle - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1265\cocoasubrtf210 -\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc - -\f0\fs24 \cf0 D Cache} - - - - Bounds - {{385.1055793762207, 404.67831339018437}, {57.756828308105469, 63.636363983154297}} - Class - ShapedGraphic - FontInfo - - Color - - w - 0 - - Font - Helvetica - NSKern - 0.0 - Size - 12 - - ID - 1266 - Shape - Rectangle - Style - - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1265\cocoasubrtf210 -\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;\red239\green31\blue29;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc - -\f0\fs24 \cf2 sets\ -ways} - VerticalPad - 0 - - - - ID - 1264 - - - Class - Group - Graphics - - - Bounds - {{309.1055793762207, 380.70932470185664}, {57.756828308105469, 24.292869750392498}} - Class - ShapedGraphic - ID - 1196 - Shape - Rectangle - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1265\cocoasubrtf210 -\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc - -\f0\fs24 \cf0 I Cache} - - - - Bounds - {{309.1055793762207, 404.67831339018437}, {57.756828308105469, 63.636363983154297}} - Class - ShapedGraphic - FontInfo - - Color - - w - 0 - - Font - Helvetica - NSKern - 0.0 - Size - 12 - - ID - 1197 - Shape - Rectangle - Style - - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1265\cocoasubrtf210 -\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;\red239\green31\blue29;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc - -\f0\fs24 \cf2 sets\ -ways} - VerticalPad - 0 - - - - ID - 1195 - - - Class - Group - Graphics - - - Bounds - {{220.4763916642375, 385.03609664606915}, {71.015203032513696, 24.292869750392498}} - Class - ShapedGraphic - ID - 1449 - Shape - Rectangle - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1265\cocoasubrtf210 -\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc - -\f0\fs24 \cf0 Small Core} - - - - Bounds - {{220.4763923637957, 409.32894849074296}, {71.015203032513696, 54.658956938383128}} - Class - ShapedGraphic - FontInfo - - Color - - b - 0.113725 - g - 0.121569 - r - 0.937255 - - Font - Helvetica - NSKern - 0.0 - Size - 12 - - ID - 1450 - Shape - Rectangle - Style - - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1265\cocoasubrtf210 -\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;\red239\green31\blue29;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc - -\f0\fs24 \cf2 \expnd0\expndtw0\kerning0 -fpu} - VerticalPad - 0 - - - - ID - 1448 - - - Class - Group - Graphics - - - Bounds - {{132.4763916642375, 385.03609664606915}, {71.015203032513696, 24.292869750392498}} - Class - ShapedGraphic - ID - 1232 - Shape - Rectangle - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1265\cocoasubrtf210 -\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc - -\f0\fs24 \cf0 Big Core} - - - - Bounds - {{132.4763923637957, 409.32894849074296}, {71.015203032513696, 54.658956938383128}} - Class - ShapedGraphic - FontInfo - - Color - - b - 0.113725 - g - 0.121569 - r - 0.937255 - - Font - Helvetica - NSKern - 0.0 - Size - 12 - - ID - 1233 - Shape - Rectangle - Style - - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1265\cocoasubrtf210 -\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;\red239\green31\blue29;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc - -\f0\fs24 \cf2 \expnd0\expndtw0\kerning0 -iq_depth\ -lsq_depth} - VerticalPad - 0 - - - - ID - 1231 - - - Class - Group - Graphics - - - Bounds - {{253.59713745117188, 265.03609664606915}, {86.77371130341065, 24.292869750392498}} - Class - ShapedGraphic - ID - 1443 - Shape - Rectangle - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1265\cocoasubrtf210 -\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc - -\f0\fs24 \cf0 Tile} - - - - Bounds - {{253.59713830596434, 289.32894849074296}, {86.77371130341065, 54.658956938383128}} - Class - ShapedGraphic - FontInfo - - Color - - b - 0.113725 - g - 0.121569 - r - 0.937255 - - Font - Helvetica - NSKern - 0.0 - Size - 12 - - ID - 1444 - Shape - Rectangle - Style - - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1265\cocoasubrtf210 -\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;\red239\green31\blue29;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc - -\f0\fs24 \cf2 \expnd0\expndtw0\kerning0 -which_core} - VerticalPad - 0 - - - - ID - 1442 - - - Class - LineGraphic - Head - - ID - 1264 - - ID - 1445 - Points - - {335.47317142973168, 343.9879054291261} - {385.1055793762207, 394.89271290345039} - - Style - - stroke - - HeadArrow - FilledArrow - Legacy - - LineType - 1 - TailArrow - 0 - - - Tail - - ID - 1442 - - - - Class - LineGraphic - Head - - ID - 1195 - - ID - 1446 - Points - - {310.47336583106994, 343.98790542912616} - {323.02149876478444, 380.70932470185659} - - Style - - stroke - - HeadArrow - FilledArrow - Legacy - - LineType - 1 - TailArrow - 0 - - - Tail - - ID - 1442 - - - - Class - LineGraphic - Head - - ID - 1231 - - ID - 1447 - Points - - {254.25909655536935, 343.98790542912604} - {203.49159539630938, 390.89481834992336} - - Style - - stroke - - HeadArrow - FilledArrow - Legacy - - LineType - 1 - Pattern - 1 - TailArrow - 0 - - - Tail - - ID - 1442 - - - - Class - LineGraphic - Head - - ID - 1448 - - ID - 1454 - Points - - {283.4972540181634, 343.9879054291261} - {269.47335080633479, 385.03609664606915} - - Style - - stroke - - HeadArrow - FilledArrow - Legacy - - LineType - 1 - Pattern - 1 - TailArrow - 0 - - - Tail - - ID - 1442 - - - - GridInfo - - HPages - 2 - KeepToScale - - Layers - - - Lock - NO - Name - Layer 1 - Print - YES - View - YES - - - LayoutInfo - - Animate - NO - AutoLayout - 2 - LineLength - 0.4643835723400116 - circoMinDist - 18 - circoSeparation - 0.0 - layoutEngine - dot - neatoSeparation - 0.0 - twopiSeparation - 0.0 - - Orientation - 2 - OutlineStyle - Basic - PrintOnePage - - RowAlign - 1 - RowSpacing - 36 - SheetTitle - Disjoint parameter sets - UniqueID - 2 - VPages - 2 - - - ActiveLayerIndex - 0 - AutoAdjust - - BackgroundGraphic - - Bounds - {{0, 0}, {943, 785}} - Class - SolidGraphic - ID - 2 - Style - - shadow - - Draws - NO - - stroke - - Draws - NO - - - - BaseZoom - 0 - CanvasOrigin - {0, 0} - CanvasSize - {943, 785} - ColumnAlign - 1 - ColumnSpacing - 36 - DisplayScale - 1 0/72 in = 1.0000 in - GraphicsList - - - Class - Group - Graphics - - - Bounds - {{376.1055793762207, 352.6973236642591}, {57.756828308105469, 24.292869750392498}} - Class - ShapedGraphic - ID - 1392 - Shape - Rectangle - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1265\cocoasubrtf210 -\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc - -\f0\fs24 \cf0 Memory} - - - - Bounds - {{376.1055793762207, 376.6663123525866}, {57.756828308105469, 63.636363983154297}} - Class - ShapedGraphic - FontInfo - - Color - - w - 0 - - Font - Helvetica - NSKern - 0.0 - Size - 12 - - ID - 1393 - Shape - Rectangle - Style - - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1265\cocoasubrtf210 -\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;\red239\green31\blue29;\red0\green0\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc - -\f0\fs24 \cf2 size\ -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc -\cf3 width} - VerticalPad - 0 - - - - ID - 1391 - - - Class - Group - Graphics - - - Bounds - {{218.1055793762207, 476.69732366425922}, {57.756828308105469, 24.292869750392498}} - Class - ShapedGraphic - ID - 1386 - Shape - Rectangle - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1265\cocoasubrtf210 -\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc - -\f0\fs24 \cf0 Memory} - - - - Bounds - {{218.1055793762207, 500.6663123525866}, {57.756828308105469, 63.636363983154297}} - Class - ShapedGraphic - FontInfo - - Color - - w - 0 - - Font - Helvetica - NSKern - 0.0 - Size - 12 - - ID - 1387 - Shape - Rectangle - Style - - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1265\cocoasubrtf210 -\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;\red239\green31\blue29;\red0\green0\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc - -\f0\fs24 \cf2 size\ -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc -\cf3 width} - VerticalPad - 0 - - - - ID - 1385 - - - Class - Group - Graphics - - - Bounds - {{300.1055793762207, 352.6973236642591}, {57.756828308105469, 24.292869750392498}} - Class - ShapedGraphic - ID - 1383 - Shape - Rectangle - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1265\cocoasubrtf210 -\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc - -\f0\fs24 \cf0 Memory} - - - - Bounds - {{300.1055793762207, 376.6663123525866}, {57.756828308105469, 63.636363983154297}} - Class - ShapedGraphic - FontInfo - - Color - - w - 0 - - Font - Helvetica - NSKern - 0.0 - Size - 12 - - ID - 1384 - Shape - Rectangle - Style - - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1265\cocoasubrtf210 -\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;\red239\green31\blue29;\red0\green0\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc - -\f0\fs24 \cf2 size\ -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc -\cf3 width} - VerticalPad - 0 - - - - ID - 1382 - - - Class - Group - Graphics - - - Bounds - {{218.1055793762207, 357.02408221779592}, {57.756828308105469, 24.292869750392498}} - Class - ShapedGraphic - ID - 1293 - Shape - Rectangle - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1265\cocoasubrtf210 -\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc - -\f0\fs24 \cf0 LSQ} - - - - Bounds - {{218.1055793762207, 381.31696084382099}, {57.756828308105469, 54.658956938383128}} - Class - ShapedGraphic - FontInfo - - Color - - b - 0.113725 - g - 0.121569 - r - 0.937255 - - Font - Helvetica - NSKern - 0.0 - Size - 12 - - ID - 1294 - Shape - Rectangle - Style - - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1265\cocoasubrtf210 -\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;\red239\green31\blue29;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc - -\f0\fs24 \cf2 depth} - VerticalPad - 0 - - - - ID - 1292 - - - Class - Group - Graphics - - - Bounds - {{142.1055793762207, 357.02408221779592}, {57.756828308105469, 24.292869750392498}} - Class - ShapedGraphic - ID - 1226 - Shape - Rectangle - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1265\cocoasubrtf210 -\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc - -\f0\fs24 \cf0 IQ} - - - - Bounds - {{142.1055793762207, 381.31696084382088}, {57.756828308105469, 54.658956938383128}} - Class - ShapedGraphic - FontInfo - - Color - - b - 0.113725 - g - 0.121569 - r - 0.937255 - - Font - Helvetica - NSKern - 0.0 - Size - 12 - - ID - 1227 - Shape - Rectangle - Style - - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1265\cocoasubrtf210 -\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;\red239\green31\blue29;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc - -\f0\fs24 \cf2 \expnd0\expndtw0\kerning0 -depth} - VerticalPad - 0 - - - - ID - 1225 - - - Class - Group - Graphics - - - Bounds - {{142.1055793762207, 476.6973236642591}, {57.756828308105469, 24.292869750392498}} - Class - ShapedGraphic - ID - 1361 - Shape - Rectangle - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1265\cocoasubrtf210 -\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc - -\f0\fs24 \cf0 Memory} - - - - Bounds - {{142.1055793762207, 500.6663123525866}, {57.756828308105469, 63.636363983154297}} - Class - ShapedGraphic - FontInfo - - Color - - w - 0 - - Font - Helvetica - NSKern - 0.0 - Size - 12 - - ID - 1362 - Shape - Rectangle - Style - - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1265\cocoasubrtf210 -\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;\red239\green31\blue29;\red0\green0\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc - -\f0\fs24 \cf2 size\ -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc -\cf3 width} - VerticalPad - 0 - - - - ID - 1360 - - - Class - Group - Graphics - - - Bounds - {{376.1055793762207, 228.69732366425899}, {57.756828308105469, 24.292869750392498}} - Class - ShapedGraphic - ID - 1265 - Shape - Rectangle - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1265\cocoasubrtf210 -\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc - -\f0\fs24 \cf0 D Cache} - - - - Bounds - {{376.1055793762207, 252.66631235258671}, {57.756828308105469, 63.636363983154297}} - Class - ShapedGraphic - FontInfo - - Color - - w - 0 - - Font - Helvetica - NSKern - 0.0 - Size - 12 - - ID - 1266 - Shape - Rectangle - Style - - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1265\cocoasubrtf210 -\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;\red239\green31\blue29;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc - -\f0\fs24 \cf2 sets\ -ways} - VerticalPad - 0 - - - - ID - 1264 - - - Class - Group - Graphics - - - Bounds - {{300.1055793762207, 228.69732366425899}, {57.756828308105469, 24.292869750392498}} - Class - ShapedGraphic - ID - 1196 - Shape - Rectangle - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1265\cocoasubrtf210 -\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc - -\f0\fs24 \cf0 I Cache} - - - - Bounds - {{300.1055793762207, 252.66631235258671}, {57.756828308105469, 63.636363983154297}} - Class - ShapedGraphic - FontInfo - - Color - - w - 0 - - Font - Helvetica - NSKern - 0.0 - Size - 12 - - ID - 1197 - Shape - Rectangle - Style - - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1265\cocoasubrtf210 -\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;\red239\green31\blue29;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc - -\f0\fs24 \cf2 sets\ -ways} - VerticalPad - 0 - - - - ID - 1195 - - - Class - Group - Graphics - - - Bounds - {{197.95362472534165, 233.0240956084715}, {84.060736781795853, 24.292869750392498}} - Class - ShapedGraphic - ID - 1333 - Shape - Rectangle - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1265\cocoasubrtf210 -\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc - -\f0\fs24 \cf0 Big Core} - - - - Bounds - {{197.95362555340935, 257.31694745314536}, {84.060736781795853, 54.658956938383128}} - Class - ShapedGraphic - FontInfo - - Color - - b - 0.113725 - g - 0.121569 - r - 0.937255 - - Font - Helvetica - NSKern - 0.0 - Size - 12 - - ID - 1334 - Shape - Rectangle - Style - - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1265\cocoasubrtf210 -\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;\red239\green31\blue29;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc - -\f0\fs24 \cf2 \expnd0\expndtw0\kerning0 -iq_depth\ -lsq_depth} - VerticalPad - 0 - - - - ID - 1332 - - - Bounds - {{296.42725372314453, 168.35356512480377}, {65.113479614257812, 24.292869750392498}} - Class - ShapedGraphic - ID - 1377 - Shape - Rectangle - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1265\cocoasubrtf210 -\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc - -\f0\fs24 \cf0 Tile} - - - - Class - LineGraphic - Head - - ID - 1225 - - ID - 1380 - Points - - {218.01818168299752, 311.9759043915285} - {192.95175664608902, 357.02408221779586} - - Style - - stroke - - HeadArrow - FilledArrow - Legacy - - LineType - 1 - TailArrow - 0 - - - Tail - - ID - 1332 - - - - Class - LineGraphic - Head - - ID - 1292 - - ID - 1381 - Points - - {242.21244237601843, 311.9759043915285} - {244.75545086251691, 357.02408221779586} - - Style - - stroke - - HeadArrow - FilledArrow - Legacy - - LineType - 1 - TailArrow - 0 - - - Tail - - ID - 1332 - - - - Class - LineGraphic - Head - - ID - 1360 - - ID - 1388 - Points - - {170.98413743668584, 435.97591778220402} - {170.98428588342901, 476.6973236642591} - - Style - - stroke - - HeadArrow - FilledArrow - Legacy - - LineType - 1 - TailArrow - 0 - - - Tail - - ID - 1225 - - - - Class - LineGraphic - Head - - ID - 1385 - - ID - 1389 - Points - - {246.98413743668584, 435.97591778220414} - {246.98428588342901, 476.69732366425922} - - Style - - stroke - - HeadArrow - FilledArrow - Legacy - - LineType - 1 - TailArrow - 0 - - - Tail - - ID - 1292 - - - - Class - LineGraphic - Head - - ID - 1382 - - ID - 1390 - Points - - {328.98367355057167, 316.30267633574101} - {328.98340768671648, 352.6973236642591} - - Style - - stroke - - HeadArrow - FilledArrow - Legacy - - LineType - 1 - TailArrow - 0 - - - Tail - - ID - 1195 - - - - Class - LineGraphic - Head - - ID - 1391 - - ID - 1394 - Points - - {404.98367355057167, 316.30267633574101} - {404.98340768671648, 352.6973236642591} - - Style - - stroke - - HeadArrow - FilledArrow - Legacy - - LineType - 1 - TailArrow - 0 - - - Tail - - ID - 1264 - - - - Class - LineGraphic - Head - - ID - 1264 - - ID - 1395 - Points - - {339.33643064540007, 193.03191599325183} - {376.10557937622065, 237.54200360969685} - - Style - - stroke - - HeadArrow - FilledArrow - Legacy - - LineType - 1 - TailArrow - 0 - - - Tail - - ID - 1377 - - - - Class - LineGraphic - Head - - ID - 1195 - - ID - 1396 - Points - - {328.98398554662987, 193.14643488528665} - {328.98396310349642, 228.69732366425896} - - Style - - stroke - - HeadArrow - FilledArrow - Legacy - - LineType - 1 - TailArrow - 0 - - - Tail - - ID - 1377 - - - - Class - LineGraphic - Head - - ID - 1332 - - ID - 1397 - Points - - {316.886019359702, 193.00579930138588} - {278.17275494486813, 233.0240956084715} - - Style - - stroke - - HeadArrow - FilledArrow - Legacy - - LineType - 1 - TailArrow - 0 - - - Tail - - ID - 1377 - - - - GridInfo - - HPages - 2 - KeepToScale - - Layers - - - Lock - NO - Name - Layer 1 - Print - YES - View - YES - - - LayoutInfo - - Animate - NO - AutoLayout - 2 - LineLength - 0.4643835723400116 - circoMinDist - 18 - circoSeparation - 0.0 - layoutEngine - dot - neatoSeparation - 0.0 - twopiSeparation - 0.0 - - Orientation - 2 - OutlineStyle - Basic - PrintOnePage - - RowAlign - 1 - RowSpacing - 36 - SheetTitle - Adding location-independent parameters - UniqueID - 3 - VPages - 2 - - - ActiveLayerIndex - 0 - AutoAdjust - - BackgroundGraphic - - Bounds - {{0, 0}, {928, 789}} - Class - SolidGraphic - ID - 2 - Style - - shadow - - Draws - NO - - stroke - - Draws - NO - - - - BaseZoom - 0 - CanvasOrigin - {0, 0} - CanvasSize - {928, 789} - ColumnAlign - 1 - ColumnSpacing - 36 - DisplayScale - 1 0/72 in = 1.0000 in - GraphicsList - - - Class - Group - Graphics - - - Bounds - {{361.18390732149192, 505.10237767934234}, {57.756828308105469, 24.292869750392498}} - Class - ShapedGraphic - ID - 1392 - Shape - Rectangle - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1265\cocoasubrtf210 -\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc - -\f0\fs24 \cf0 Memory} - - - - Bounds - {{361.18390732149192, 529.07136636766984}, {57.756828308105469, 63.636363983154297}} - Class - ShapedGraphic - FontInfo - - Color - - w - 0 - - Font - Helvetica - NSKern - 0.0 - Size - 12 - - ID - 1393 - Shape - Rectangle - Style - - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1265\cocoasubrtf210 -\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;\red239\green31\blue29;\red0\green0\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc - -\f0\fs24 \cf2 size\ -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc -\cf3 ecc} - VerticalPad - 0 - - - - ID - 1391 - - - Class - Group - Graphics - - - Bounds - {{208.18390732149197, 629.10237767934257}, {57.756828308105469, 24.292869750392498}} - Class - ShapedGraphic - ID - 1386 - Shape - Rectangle - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1265\cocoasubrtf210 -\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc - -\f0\fs24 \cf0 Memory} - - - - Bounds - {{208.18390732149197, 653.07136636766995}, {57.756828308105469, 63.636363983154297}} - Class - ShapedGraphic - FontInfo - - Color - - w - 0 - - Font - Helvetica - NSKern - 0.0 - Size - 12 - - ID - 1387 - Shape - Rectangle - Style - - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1265\cocoasubrtf210 -\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;\red239\green31\blue29;\red0\green0\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc - -\f0\fs24 \cf2 size\ -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc -\cf3 ecc} - VerticalPad - 0 - - - - ID - 1385 - - - Class - Group - Graphics - - - Bounds - {{285.18390732149192, 505.10237767934234}, {57.756828308105469, 24.292869750392498}} - Class - ShapedGraphic - ID - 1383 - Shape - Rectangle - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1265\cocoasubrtf210 -\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc - -\f0\fs24 \cf0 Memory} - - - - Bounds - {{285.18390732149192, 529.07136636766984}, {57.756828308105469, 63.636363983154297}} - Class - ShapedGraphic - FontInfo - - Color - - w - 0 - - Font - Helvetica - NSKern - 0.0 - Size - 12 - - ID - 1384 - Shape - Rectangle - Style - - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1265\cocoasubrtf210 -\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;\red239\green31\blue29;\red0\green0\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc - -\f0\fs24 \cf2 size\ -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc -\cf3 ecc} - VerticalPad - 0 - - - - ID - 1382 - - - Class - Group - Graphics - - - Bounds - {{208.18390732149197, 509.42913623287916}, {57.756828308105469, 24.292869750392498}} - Class - ShapedGraphic - ID - 1293 - Shape - Rectangle - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1265\cocoasubrtf210 -\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc - -\f0\fs24 \cf0 LSQ} - - - - Bounds - {{208.18390732149197, 533.72201485890412}, {57.756828308105469, 54.658956938383128}} - Class - ShapedGraphic - FontInfo - - Color - - b - 0.113725 - g - 0.121569 - r - 0.937255 - - Font - Helvetica - NSKern - 0.0 - Size - 12 - - ID - 1294 - Shape - Rectangle - Style - - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1265\cocoasubrtf210 -\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;\red239\green31\blue29;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc - -\f0\fs24 \cf2 depth} - VerticalPad - 0 - - - - ID - 1292 - - - Class - Group - Graphics - - - Bounds - {{132.18390732149197, 509.42913623287916}, {57.756828308105469, 24.292869750392498}} - Class - ShapedGraphic - ID - 1226 - Shape - Rectangle - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1265\cocoasubrtf210 -\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc - -\f0\fs24 \cf0 IQ} - - - - Bounds - {{132.18390732149197, 533.72201485890412}, {57.756828308105469, 54.658956938383128}} - Class - ShapedGraphic - FontInfo - - Color - - b - 0.113725 - g - 0.121569 - r - 0.937255 - - Font - Helvetica - NSKern - 0.0 - Size - 12 - - ID - 1227 - Shape - Rectangle - Style - - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1265\cocoasubrtf210 -\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;\red239\green31\blue29;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc - -\f0\fs24 \cf2 \expnd0\expndtw0\kerning0 -depth} - VerticalPad - 0 - - - - ID - 1225 - - - Class - Group - Graphics - - - Bounds - {{132.18390732149197, 629.10237767934223}, {57.756828308105469, 24.292869750392498}} - Class - ShapedGraphic - ID - 1361 - Shape - Rectangle - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1265\cocoasubrtf210 -\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc - -\f0\fs24 \cf0 Memory} - - - - Bounds - {{132.18390732149197, 653.07136636766973}, {57.756828308105469, 63.636363983154297}} - Class - ShapedGraphic - FontInfo - - Color - - w - 0 - - Font - Helvetica - NSKern - 0.0 - Size - 12 - - ID - 1362 - Shape - Rectangle - Style - - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1265\cocoasubrtf210 -\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;\red239\green31\blue29;\red0\green0\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc - -\f0\fs24 \cf2 size\ -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc -\cf3 ecc} - VerticalPad - 0 - - - - ID - 1360 - - - Class - Group - Graphics - - - Bounds - {{361.18390732149192, 381.10237767934234}, {57.756828308105469, 24.292869750392498}} - Class - ShapedGraphic - ID - 1265 - Shape - Rectangle - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1265\cocoasubrtf210 -\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc - -\f0\fs24 \cf0 D Cache} - - - - Bounds - {{361.18390732149192, 405.07136636767007}, {57.756828308105469, 63.636363983154297}} - Class - ShapedGraphic - FontInfo - - Color - - w - 0 - - Font - Helvetica - NSKern - 0.0 - Size - 12 - - ID - 1266 - Shape - Rectangle - Style - - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1265\cocoasubrtf210 -\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;\red239\green31\blue29;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc - -\f0\fs24 \cf2 sets\ -ways} - VerticalPad - 0 - - - - ID - 1264 - - - Class - Group - Graphics - - - Bounds - {{285.18390732149192, 381.10237767934234}, {57.756828308105469, 24.292869750392498}} - Class - ShapedGraphic - ID - 1196 - Shape - Rectangle - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1265\cocoasubrtf210 -\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc - -\f0\fs24 \cf0 I Cache} - - - - Bounds - {{285.18390732149192, 405.07136636767007}, {57.756828308105469, 63.636363983154297}} - Class - ShapedGraphic - FontInfo - - Color - - w - 0 - - Font - Helvetica - NSKern - 0.0 - Size - 12 - - ID - 1197 - Shape - Rectangle - Style - - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1265\cocoasubrtf210 -\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;\red239\green31\blue29;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc - -\f0\fs24 \cf2 sets\ -ways} - VerticalPad - 0 - - - - ID - 1195 - - - Class - Group - Graphics - - - Bounds - {{194.75621872285924, 385.42914962355485}, {80.612204711274501, 24.292869750392498}} - Class - ShapedGraphic - ID - 1333 - Shape - Rectangle - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1265\cocoasubrtf210 -\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc - -\f0\fs24 \cf0 Big Core} - - - - Bounds - {{194.75621951695584, 409.72200146822871}, {80.612204711274501, 54.658956938383128}} - Class - ShapedGraphic - FontInfo - - Color - - b - 0.113725 - g - 0.121569 - r - 0.937255 - - Font - Helvetica - NSKern - 0.0 - Size - 12 - - ID - 1334 - Shape - Rectangle - Style - - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1265\cocoasubrtf210 -\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;\red239\green31\blue29;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc - -\f0\fs24 \cf2 \expnd0\expndtw0\kerning0 -iq_depth\ -lsq_depth} - VerticalPad - 0 - - - - ID - 1332 - - - Bounds - {{281.50558166841574, 282.75861913988717}, {65.113479614257812, 24.292869750392498}} - Class - ShapedGraphic - ID - 1377 - Shape - Rectangle - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1265\cocoasubrtf210 -\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc - -\f0\fs24 \cf0 Tile} - - - - Class - LineGraphic - Head - - ID - 1225 - - ID - 1380 - Points - - {211.47609516335541, 464.38095840661191} - {184.56052391706112, 509.42913623287916} - - Style - - stroke - - HeadArrow - FilledArrow - Legacy - - LineType - 1 - TailArrow - 0 - - - Tail - - ID - 1332 - - - - Class - LineGraphic - Head - - ID - 1292 - - ID - 1381 - Points - - {235.67100430655034, 464.38095840661191} - {236.36560656667797, 509.42913623287916} - - Style - - stroke - - HeadArrow - FilledArrow - Legacy - - LineType - 1 - TailArrow - 0 - - - Tail - - ID - 1332 - - - - Class - LineGraphic - Head - - ID - 1360 - - ID - 1388 - Points - - {161.06233503210461, 588.3809717972872} - {161.06233503210461, 629.10237767934223} - - Style - - stroke - - HeadArrow - FilledArrow - Legacy - - LineType - 1 - TailArrow - 0 - - - Tail - - ID - 1225 - - - - Class - LineGraphic - Head - - ID - 1385 - - ID - 1389 - Points - - {237.06233503210461, 588.3809717972872} - {237.06233503210461, 629.10237767934268} - - Style - - stroke - - HeadArrow - FilledArrow - Legacy - - LineType - 1 - TailArrow - 0 - - - Tail - - ID - 1292 - - - - Class - LineGraphic - Head - - ID - 1382 - - ID - 1390 - Points - - {314.06234107334649, 468.70773035082436} - {314.06234107334649, 505.10237767934234} - - Style - - stroke - - HeadArrow - FilledArrow - Legacy - - LineType - 1 - TailArrow - 0 - - - Tail - - ID - 1195 - - - - Class - LineGraphic - Head - - ID - 1391 - - ID - 1394 - Points - - {390.06234107334649, 468.70773035082436} - {390.06234107334649, 505.10237767934234} - - Style - - stroke - - HeadArrow - FilledArrow - Legacy - - LineType - 1 - TailArrow - 0 - - - Tail - - ID - 1264 - - - - Class - LineGraphic - Head - - ID - 1264 - - ID - 1395 - Points - - {321.41566245820957, 307.48313727490483} - {364.45460300234242, 381.10237767934228} - - Style - - stroke - - HeadArrow - FilledArrow - Legacy - - LineType - 1 - TailArrow - 0 - - - Tail - - ID - 1377 - - - - Class - LineGraphic - Head - - ID - 1195 - - ID - 1396 - Points - - {314.06233371625194, 307.55148889519205} - {314.06233371625194, 381.10237767934228} - - Style - - stroke - - HeadArrow - FilledArrow - Legacy - - LineType - 1 - TailArrow - 0 - - - Tail - - ID - 1377 - - - - Class - LineGraphic - Head - - ID - 1332 - - ID - 1397 - Points - - {306.41686612918278, 307.47870995912245} - {259.01882944549004, 385.42914962355485} - - Style - - stroke - - HeadArrow - FilledArrow - Legacy - - LineType - 1 - TailArrow - 0 - - - Tail - - ID - 1377 - - - - GridInfo - - HPages - 2 - KeepToScale - - Layers - - - Lock - NO - Name - Layer 1 - Print - YES - View - YES - - - LayoutInfo - - Animate - NO - AutoLayout - 2 - LineLength - 0.4643835723400116 - circoMinDist - 18 - circoSeparation - 0.0 - layoutEngine - dot - neatoSeparation - 0.0 - twopiSeparation - 0.0 - - Orientation - 2 - OutlineStyle - Basic - PrintOnePage - - RowAlign - 1 - RowSpacing - 36 - SheetTitle - Adding location-specific parameters - UniqueID - 5 - VPages - 2 - - - ActiveLayerIndex - 0 - AutoAdjust - - BackgroundGraphic - - Bounds - {{0, 0}, {943, 785}} - Class - SolidGraphic - ID - 2 - Style - - shadow - - Draws - NO - - stroke - - Draws - NO - - - - BaseZoom - 0 - CanvasOrigin - {0, 0} - CanvasSize - {943, 785} - ColumnAlign - 1 - ColumnSpacing - 36 - DisplayScale - 1 0/72 in = 1.0000 in - GraphicsList - - - Class - Group - Graphics - - - Bounds - {{247.69789886474612, 357.04009444880353}, {80.612204711274501, 24.292869750392498}} - Class - ShapedGraphic - ID - 1333 - Shape - Rectangle - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1265\cocoasubrtf210 -\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc - -\f0\fs24 \cf0 Big Core} - - - - Bounds - {{247.69789965884272, 381.33294629347739}, {80.612204711274501, 54.658956938383128}} - Class - ShapedGraphic - FontInfo - - Color - - b - 0.113725 - g - 0.121569 - r - 0.937255 - - Font - Helvetica - NSKern - 0.0 - Size - 12 - - ID - 1334 - Shape - Rectangle - Style - - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1265\cocoasubrtf210 -\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;\red239\green31\blue29;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc - -\f0\fs24 \cf2 #arch_reg\ -#phy_reg\ -rob_size} - VerticalPad - 0 - - - - ID - 1332 - - - Bounds - {{255.44726181030276, 296.3695639651358}, {65.113479614257812, 24.292869750392498}} - Class - ShapedGraphic - ID - 1377 - Shape - Rectangle - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1265\cocoasubrtf210 -\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc - -\f0\fs24 \cf0 Tile} - - - - Class - LineGraphic - Head - - ID - 1332 - - ID - 1397 - Points - - {288.00401526031152, 321.16243374149587} - {288.00401526031152, 357.04009444880353} - - Style - - stroke - - HeadArrow - FilledArrow - Legacy - - LineType - 1 - TailArrow - 0 - - - Tail - - ID - 1377 - - - - GridInfo - - HPages - 2 - KeepToScale - - Layers - - - Lock - NO - Name - Layer 1 - Print - YES - View - YES - - - LayoutInfo - - Animate - NO - AutoLayout - 2 - LineLength - 0.4643835723400116 - circoMinDist - 18 - circoSeparation - 0.0 - layoutEngine - dot - neatoSeparation - 0.0 - twopiSeparation - 0.0 - - Orientation - 2 - OutlineStyle - Basic - PrintOnePage - - RowAlign - 1 - RowSpacing - 36 - SheetTitle - Deriving Top-level Parameters - UniqueID - 7 - VPages - 2 - - - ActiveLayerIndex - 0 - AutoAdjust - - BackgroundGraphic - - Bounds - {{0, 0}, {1423, 1085}} - Class - SolidGraphic - ID - 2 - Style - - shadow - - Draws - NO - - stroke - - Draws - NO - - - - BaseZoom - 0 - CanvasOrigin - {0, 0} - CanvasSize - {1423, 1085} - ColumnAlign - 1 - ColumnSpacing - 36 - DisplayScale - 1 0/72 in = 1.0000 in - GraphicsList - - - Class - Group - Graphics - - - Bounds - {{297.12559127807617, 380.70932470185664}, {57.756828308105469, 24.292869750392498}} - Class - ShapedGraphic - ID - 1265 - Shape - Rectangle - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1265\cocoasubrtf210 -\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc - -\f0\fs24 \cf0 D Cache} - - - - Bounds - {{297.12559127807617, 404.67831339018437}, {57.756828308105469, 63.636363983154297}} - Class - ShapedGraphic - FontInfo - - Color - - w - 0 - - Font - Helvetica - NSKern - 0.0 - Size - 12 - - ID - 1266 - Shape - Rectangle - Style - - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1265\cocoasubrtf210 -\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;\red239\green31\blue29;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc - -\f0\fs24 \cf2 sets} - VerticalPad - 0 - - - - ID - 1264 - - - Class - Group - Graphics - - - Bounds - {{221.12559127807617, 380.70930541438798}, {57.756828308105469, 24.292869750392498}} - Class - ShapedGraphic - ID - 1196 - Shape - Rectangle - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1265\cocoasubrtf210 -\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc - -\f0\fs24 \cf0 I Cache} - - - - Bounds - {{221.12559127807617, 404.67829410271571}, {57.756828308105469, 63.636363983154297}} - Class - ShapedGraphic - FontInfo - - Color - - w - 0 - - Font - Helvetica - NSKern - 0.0 - Size - 12 - - ID - 1197 - Shape - Rectangle - Style - - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1265\cocoasubrtf210 -\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;\red239\green31\blue29;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc - -\f0\fs24 \cf2 sets} - VerticalPad - 0 - - - - ID - 1195 - - - Class - Group - Graphics - - - Bounds - {{244.61714935302734, 265.03609664606915}, {86.77371130341065, 24.292869750392498}} - Class - ShapedGraphic - ID - 1443 - Shape - Rectangle - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1265\cocoasubrtf210 -\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc - -\f0\fs24 \cf0 Tile} - - - - Bounds - {{244.6171502078198, 289.32894849074296}, {86.77371130341065, 54.658956938383128}} - Class - ShapedGraphic - FontInfo - - Color - - b - 0.113725 - g - 0.121569 - r - 0.937255 - - Font - Helvetica - NSKern - 0.0 - Size - 12 - - ID - 1444 - Shape - Rectangle - Style - - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1265\cocoasubrtf210 -\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;\red239\green31\blue29;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc - -\f0\fs24 \cf2 \expnd0\expndtw0\kerning0 -ic_sets\ -dc_sets} - VerticalPad - 0 - - - - ID - 1442 - - - Class - LineGraphic - Head - - ID - 1264 - - ID - 1445 - Points - - {300.88107480695737, 343.9879054291261} - {312.85962908723855, 380.70932470185664} - - Style - - stroke - - HeadArrow - FilledArrow - Legacy - - LineType - 1 - TailArrow - 0 - - - Tail - - ID - 1442 - - - - Class - LineGraphic - Head - - ID - 1195 - - ID - 1446 - Points - - {275.61916900984426, 343.9879054291261} - {264.09850750696683, 380.70930541438793} - - Style - - stroke - - HeadArrow - FilledArrow - Legacy - - LineType - 1 - TailArrow - 0 - - - Tail - - ID - 1442 - - - - GridInfo - - HPages - 3 - KeepToScale - - Layers - - - Lock - NO - Name - Layer 1 - Print - YES - View - YES - - - LayoutInfo - - Animate - NO - AutoLayout - 2 - LineLength - 0.4643835723400116 - circoMinDist - 18 - circoSeparation - 0.0 - layoutEngine - dot - neatoSeparation - 0.0 - twopiSeparation - 0.0 - - Orientation - 2 - OutlineStyle - Basic - PrintOnePage - - RowAlign - 1 - RowSpacing - 36 - SheetTitle - Renaming Parameters - UniqueID - 8 - VPages - 2 - - - ActiveLayerIndex - 0 - AutoAdjust - - BackgroundGraphic - - Bounds - {{0, 0}, {1423, 1085}} - Class - SolidGraphic - ID - 2 - Style - - shadow - - Draws - NO - - stroke - - Draws - NO - - - - BaseZoom - 0 - CanvasOrigin - {0, 0} - CanvasSize - {1423, 1085} - ColumnAlign - 1 - ColumnSpacing - 36 - DisplayScale - 1 0/72 in = 1.0000 in - GraphicsList - - - Bounds - {{347.13099670410156, 465.36297607421875}, {155.74600219726562, 41.13702392578125}} - Class - ShapedGraphic - FitText - Clip - Flow - Clip - ID - 18 - Shape - Rectangle - Style - - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1265\cocoasubrtf210 -\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc - -\f0\fs24 \cf0 case 'width' => 128\ -case 'location' => 'cache'} - VerticalPad - 0 - - - - Bounds - {{73.130996704101562, 465.36297607421875}, {155.74600219726562, 41.13702392578125}} - Class - ShapedGraphic - FitText - Clip - Flow - Clip - ID - 17 - Shape - Rectangle - Style - - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1265\cocoasubrtf210 -\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc - -\f0\fs24 \cf0 case 'width' => 64\ -case 'location' => 'core'} - VerticalPad - 0 - - - - Bounds - {{296.75399780273438, 285.75}, {256.5, 89.5}} - Class - ShapedGraphic - ID - 15 - Shape - RoundRect - Style - - Text - - Align - 0 - Text - {\rtf1\ansi\ansicpg1252\cocoartf1265\cocoasubrtf210 -\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural - -\f0\fs24 \cf0 case 'width' => site('location') match \ - \{\ - case 'core => 64\ - case 'cache => 128\ - \}} - VerticalPad - 0 - - - - Bounds - {{296.75399780273438, 411.5}, {256.5, 36}} - Class - ShapedGraphic - FontInfo - - Color - - w - 0 - - Font - Helvetica - NSKern - 0.0 - Size - 12 - - ID - 14 - Shape - RoundRect - Style - - Text - - Align - 0 - Text - {\rtf1\ansi\ansicpg1252\cocoartf1265\cocoasubrtf210 -\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural - -\f0\fs24 \cf0 \expnd0\expndtw0\kerning0 - case 'location' => 'cache'} - VerticalPad - 0 - - - - Bounds - {{22.753997802734379, 285.75}, {256.5, 89.5}} - Class - ShapedGraphic - ID - 8 - Shape - RoundRect - Style - - Text - - Align - 0 - Text - {\rtf1\ansi\ansicpg1252\cocoartf1265\cocoasubrtf210 -\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural - -\f0\fs24 \cf0 case 'width' => site('location') match \ - \{\ - case 'core => 64\ - case 'cache => 128\ - \}} - VerticalPad - 0 - - - - Bounds - {{22.753997802734379, 411.5}, {256.5, 36}} - Class - ShapedGraphic - ID - 7 - Shape - RoundRect - Style - - Text - - Align - 0 - Text - {\rtf1\ansi\ansicpg1252\cocoartf1265\cocoasubrtf210 -\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural - -\f0\fs24 \cf0 case 'location' => 'core'} - VerticalPad - 0 - - - - Class - LineGraphic - Head - - ID - 7 - - ID - 9 - Points - - {151.00770863622569, 375.75000000073703} - {151.01059939602146, 411.00000005269834} - - Style - - stroke - - HeadArrow - 0 - Legacy - - TailArrow - FilledArrow - - - Tail - - ID - 8 - - - - Class - LineGraphic - Head - - ID - 14 - - ID - 16 - Points - - {425.00771041829984, 375.75000000073805} - {425.01060256634128, 411.00000005276996} - - Style - - stroke - - HeadArrow - 0 - Legacy - - TailArrow - FilledArrow - - - Tail - - ID - 15 - - - - GridInfo - - HPages - 3 - KeepToScale - - Layers - - - Lock - NO - Name - Layer 1 - Print - YES - View - YES - - - LayoutInfo - - Animate - NO - AutoLayout - 2 - LineLength - 0.4643835723400116 - circoMinDist - 18 - circoSeparation - 0.0 - layoutEngine - dot - neatoSeparation - 0.0 - twopiSeparation - 0.0 - - Orientation - 2 - OutlineStyle - Basic - PrintOnePage - - RowAlign - 1 - RowSpacing - 36 - SheetTitle - Site - UniqueID - 9 - VPages - 2 - - - ActiveLayerIndex - 0 - AutoAdjust - - BackgroundGraphic - - Bounds - {{0, 0}, {1423, 1085}} - Class - SolidGraphic - ID - 2 - Style - - shadow - - Draws - NO - - stroke - - Draws - NO - - - - BaseZoom - 0 - CanvasOrigin - {0, 0} - CanvasSize - {1423, 1085} - ColumnAlign - 1 - ColumnSpacing - 36 - DisplayScale - 1 0/72 in = 1.0000 in - GraphicsList - - - Bounds - {{123.12300109863281, 411.13702392578125}, {155.74600219726562, 49.86297607421875}} - Class - ShapedGraphic - FitText - Clip - Flow - Clip - ID - 17 - Shape - Rectangle - Style - - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1265\cocoasubrtf210 -\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc - -\f0\fs24 \cf0 case 'sets' => 128\ -case 'ways' => 4\ -case 'size' => 512} - VerticalPad - 0 - - - - Bounds - {{67.123001098632798, 337.85900115966797}, {267.74600219726562, 57.25}} - Class - ShapedGraphic - ID - 8 - Shape - RoundRect - Style - - Text - - Align - 0 - Text - {\rtf1\ansi\ansicpg1252\cocoartf1265\cocoasubrtf210 -\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural - -\f0\fs24 \cf0 case 'sets' => 128\ -case 'ways' => 4\ -case 'size' => here('sets')*here('ways')} - VerticalPad - 0 - - - - GridInfo - - HPages - 3 - KeepToScale - - Layers - - - Lock - NO - Name - Layer 1 - Print - YES - View - YES - - - LayoutInfo - - Animate - NO - AutoLayout - 2 - LineLength - 0.4643835723400116 - circoMinDist - 18 - circoSeparation - 0.0 - layoutEngine - dot - neatoSeparation - 0.0 - twopiSeparation - 0.0 - - Orientation - 2 - OutlineStyle - Basic - PrintOnePage - - RowAlign - 1 - RowSpacing - 36 - SheetTitle - Here - UniqueID - 11 - VPages - 2 - - - ActiveLayerIndex - 0 - AutoAdjust - - BackgroundGraphic - - Bounds - {{0, 0}, {1423, 1085}} - Class - SolidGraphic - ID - 2 - Style - - shadow - - Draws - NO - - stroke - - Draws - NO - - - - BaseZoom - 0 - CanvasOrigin - {0, 0} - CanvasSize - {1423, 1085} - ColumnAlign - 1 - ColumnSpacing - 36 - DisplayScale - 1 0/72 in = 1.0000 in - GraphicsList - - - Bounds - {{73.130996704101562, 490.5}, {155.74600219726562, 64.5}} - Class - ShapedGraphic - FitText - Clip - Flow - Clip - ID - 14 - Shape - Rectangle - Style - - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1265\cocoasubrtf210 -\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc - -\f0\fs24 \cf0 case 'fpu' => true\ -case 'depth' => 10\ -case 'width' => 32\ -case 'size' => 320} - VerticalPad - 0 - - - - Bounds - {{22.753997802734382, 437.17549896240234}, {256.5, 24.625}} - Class - ShapedGraphic - FontInfo - - Color - - w - 0 - - Font - Helvetica - NSKern - 0.0 - Size - 12 - - ID - 12 - Shape - RoundRect - Style - - Text - - Align - 0 - Text - {\rtf1\ansi\ansicpg1252\cocoartf1265\cocoasubrtf210 -\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural - -\f0\fs24 \cf0 \expnd0\expndtw0\kerning0 -case 'size' => 320} - VerticalPad - 0 - - - - Bounds - {{22.753997802734382, 360.92549896240234}, {256.5, 39.125}} - Class - ShapedGraphic - FontInfo - - Color - - w - 0 - - Font - Helvetica - NSKern - 0.0 - Size - 12 - - ID - 10 - Shape - RoundRect - Style - - Text - - Align - 0 - Text - {\rtf1\ansi\ansicpg1252\cocoartf1265\cocoasubrtf210 -\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural - -\f0\fs24 \cf0 \expnd0\expndtw0\kerning0 -case 'depth' => 10\ -case 'width' => 32} - VerticalPad - 0 - - - - Bounds - {{22.753997802734382, 270.86299896240234}, {256.5, 53.25}} - Class - ShapedGraphic - ID - 8 - Shape - RoundRect - Style - - Text - - Align - 0 - Text - {\rtf1\ansi\ansicpg1252\cocoartf1265\cocoasubrtf210 -\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural - -\f0\fs24 \cf0 case 'fpu' => true\ -case 'depth' => 5\ -case 'width' => 64} - VerticalPad - 0 - - - - Class - LineGraphic - Head - - ID - 10 - - ID - 11 - Points - - {151.01882096820287, 324.6129988676123} - {151.03839164571983, 360.42549970766987} - - Style - - stroke - - HeadArrow - 0 - Legacy - - TailArrow - FilledArrow - - - Tail - - ID - 8 - - - - Class - LineGraphic - Head - - ID - 12 - - ID - 13 - Points - - {151.00900155701197, 400.550498966335} - {151.01801143238467, 436.67549925046814} - - Style - - stroke - - HeadArrow - 0 - Legacy - - TailArrow - FilledArrow - - - Tail - - ID - 10 - - - - GridInfo - - HPages - 3 - KeepToScale - - Layers - - - Lock - NO - Name - Layer 1 - Print - YES - View - YES - - - LayoutInfo - - Animate - NO - AutoLayout - 2 - LineLength - 0.4643835723400116 - circoMinDist - 18 - circoSeparation - 0.0 - layoutEngine - dot - neatoSeparation - 0.0 - twopiSeparation - 0.0 - - Orientation - 2 - OutlineStyle - Basic - PrintOnePage - - RowAlign - 1 - RowSpacing - 36 - SheetTitle - Alter - UniqueID - 10 - VPages - 2 - - - SmartAlignmentGuidesActive - YES - SmartDistanceGuidesActive - YES - UseEntirePage - - WindowInfo - - CurrentSheet - 7 - ExpandedCanvases - - Frame - {{-242, 900}, {1920, 1178}} - ListView - - OutlineWidth - 231 - RightSidebar - - Sidebar - - SidebarWidth - 267 - VisibleRegion - {{0.5, 0.5}, {703.5, 534.5}} - Zoom - 2 - ZoomValues - - - Simple parameters - 1.8300000429153442 - 1.6799999475479126 - - - Disjoint parameter sets - 0.94999998807907104 - 1.1399999856948853 - - - Adding location-independent parameters - 0.0 - 1 - - - Adding location-specific parameters - 0.94999998807907104 - 0.93999999761581421 - - - Deriving Top-level Parameters - 0.94999998807907104 - 1 - - - Renaming Parameters - 2 - 0.94999998807907104 - - - Site - 2 - 1 - - - Alter - 2 - 1 - - - Here - 2 - 1 - - - - - diff --git a/doc/parameters/figs/figs.png b/doc/parameters/figs/figs.png deleted file mode 100644 index 822da1da..00000000 Binary files a/doc/parameters/figs/figs.png and /dev/null differ diff --git a/doc/parameters/figs/here.pdf b/doc/parameters/figs/here.pdf deleted file mode 100644 index d4cb2c8e..00000000 Binary files a/doc/parameters/figs/here.pdf and /dev/null differ diff --git a/doc/parameters/figs/sitea.pdf b/doc/parameters/figs/sitea.pdf deleted file mode 100644 index 80d271d9..00000000 Binary files a/doc/parameters/figs/sitea.pdf and /dev/null differ diff --git a/doc/parameters/figs/siteb.pdf b/doc/parameters/figs/siteb.pdf deleted file mode 100644 index 3ced9736..00000000 Binary files a/doc/parameters/figs/siteb.pdf and /dev/null differ diff --git a/doc/parameters/parameters.pdf b/doc/parameters/parameters.pdf deleted file mode 100644 index 459f4249..00000000 Binary files a/doc/parameters/parameters.pdf and /dev/null differ diff --git a/doc/parameters/parameters.tex b/doc/parameters/parameters.tex deleted file mode 100644 index a27aa8d9..00000000 --- a/doc/parameters/parameters.tex +++ /dev/null @@ -1,805 +0,0 @@ -\documentclass[10pt,twocolumn]{article} -\setlength\textwidth{6.875in} -\setlength\textheight{8.875in} -% set both margins to 2.5 pc -\setlength{\oddsidemargin}{-0.1875in}% 1 - (8.5 - 6.875)/2 -\setlength{\evensidemargin}{-0.1875in} -\setlength{\marginparwidth}{0pc} -\setlength{\marginparsep}{0pc}% -\setlength{\topmargin}{0in} \setlength{\headheight}{0pt} -\setlength{\headsep}{0pt} -\setlength{\footskip}{37pt}% -\setlength{\columnsep}{0.3125in} -\setlength{\columnwidth}{3.28125in}% (6.875 - 0.3125)/2 = 3.28125in -\setlength{\parindent}{1pc} -\newcommand{\myMargin}{1.00in} -\usepackage[top=\myMargin, left=\myMargin, right=\myMargin, bottom=\myMargin, nohead]{geometry} -\usepackage{epsfig,graphicx} -\usepackage{palatino} -\usepackage{fancybox} -\usepackage[procnames]{listings} -\usepackage{hyperref} - -\newenvironment{commentary} -{ \vspace{-0.1in} - \begin{quotation} - \noindent - \small \em - \rule{\linewidth}{1pt}\\ -} -{ - \end{quotation} -} - -\title{Advanced Parameterization Manual} -\author{Adam Izraelevitz \\ -EECS Department, UC Berkeley\\ -{\tt adamiz@eecs.berkeley.edu} -} -\date{\today} - -\newenvironment{example}{\VerbatimEnvironment\begin{footnotesize}\begin{Verbatim}}{\end{Verbatim}\end{footnotesize}} -\newcommand{\kode}[1]{\begin{footnotesize}{\tt #1}\end{footnotesize}} - -\def\code#1{{\small\tt #1}} - -\def\note#1{\noindent{\bf [Note: #1]}} -%\def\note#1{} - -\input{../style/scala.tex} - -\lstset{frame=, basicstyle={\footnotesize\ttfamily}} - -\lstset{frame=} - -\begin{document} -\maketitle{} - - -\section{Introduction} - -This document is a manual for using the advanced parameter library within {\em Chisel}. For more general information regarding {\em Chisel} as a hardware construction language, please see the Getting Started documentation. - -As hardware designs grow in complexity, modularity becomes necessary for maintaince and verification. The primary use case for {\em Chisel} is describing diverse and highly-parameterized hardware generators, and we quickly realized that the traditional parameterization method forces brittleness into a design's source code and limits component reuse. - -The outline of this document is as follows: in Section \ref{sec:advanced}, we describe the basic objects and methods for the advanced parameterization mechanism, as well as the required boilerplate to use it. In Section \ref{sec:examples}, a series of increasingly complex examples of design patterns are described. For each example, we propose the simplest parameterization scheme which solves the problem. As the examples build in complexity, so do the parameterization requirements, until we we arrive at the described advanced parameterization mechanism. The next section, Section \ref{sec:knobs}, introduces the concept of \code{Knobs} and their relationship to design constraints and the \code{Parameters} object. Finally, in Section \ref{sec:heuristics}, we explain multiple design heuristics which should be followed when using advanced parameterization. - -\section{Advanced Parameterization} -\label{sec:advanced} - -Every {\em Chisel} Module has a member \code{params} of class \code{Parameters} that provides the mechanism for passing parameters between modules. - -This section describes the following features: (1) the \code{Parameters} class and associated methods/members; (2) the basic usage model; (3) syntactic sugar; (4) boilerplate code for exposing parameters to external users/programs; (5) advanced functionality via Views (site, here, up). - -\subsection{Classes and Methods} -The \code{Parameters} class has the following base methods: - - \begin{scala} -class Parameters { - // returns a value of type T - def apply[T](key:Any):T - - // returns new Parameters class - def alter(mask:(Any,View,View,View)=>Any):Parameters - - // returns a Module's Parameters instance - def params:Parameters -} - \end{scala} -\code{View} is a class containing a base method: - \begin{scala} -class View { - // returns a value of type T - def apply[T](key:Any):T -} - \end{scala} -\code{Parameters} has a factory object containing one basic method: - \begin{scala} -object Parameters { - // returns an empty Parameters instance - def empty:Parameters -} - \end{scala} - -The \code{Module} factory object now has an additional apply method: - \begin{scala} -object Module { - // returns a new Module of type T, initialized with a Parameters instance if _p !=None. - def apply[T<:Module](c: =>T)(implicit _p: Option[Parameters] = None):T -} - \end{scala} - -\subsection{Basic Usage Model} - -This example shows the simplest usage of (1) quering params, (2) altering a Parameters object, and (3) passing a Parameters object to a Module: - -\begin{scala} -class Tile extends Module { - val width = params[Int]('width') -} -object Top { - val parameters = Parameters.empty - val tile_parameters = parameters.alter( (key,site,here,up) => { - case 'width' => 64 - }) - def main(args:Array[String]) = { - chiselMain(args,()=>Module(new Tile)(Some(tile_parameters))) - } -} -\end{scala} - -Within the Module \code{Tile}, the \code{params} member is queried by calling Parameters.apply with the key and return value type. - -In \code{Top}, an empty parameters is created by calling Parameters.empty; then it is altered with a function of type \code{(Any,View,View,View) => Any} to return a new Parameters instance, which is assigned to \code{tile\_parameters}. - -After wrapping \code{tile\_parameters} within \code{Some:Option[Parameters]}, it is passed as a second argument to the Module object when passed to \code{chiselMain}. - -\subsection{Syntactic Sugar: Field[T]} - -The simple example requires the return type \code{Int} must be included as an argument to the apply method, otherwise the Scala compiler will throw an error: - -\begin{scala} -class Tile extends Module { - val width = params[Int]('width') -} -\end{scala} - -Alternatively, one can create a case object for each key which extends \code{Field[T]} and pass that directly into \code{params} apply method. Because \code{Field} contains the return type information, the type does not need to be passed: - -\begin{scala} -case object Width extends Field[Int] -class Tile extends Module { - val width = params(Width) -} -\end{scala} - -For the rest of the document, assume the key to every query is a case class that extends \code{Field[T]} with the correct return type. - -\subsection{Syntactic Sugar: Passing and Altering} - -\begin{figure}[h] -\centering -\includegraphics[width=3in]{figs/alter} -\caption{An example of Memory's key/value chain and flat map.} -\label{fig:alter} -\end{figure} - -As a module hierarchy is formed, \code{Parameters} objects are passed between a parent module and a child module. If specified by the programmer, these objects can be copied and altered prior to instantiating the child. - -Anytime an alteration is performed, {\em Chisel} internally copies the existing chain of key/value mappings and attaches the provided key/value mappings to the bottom of this chain. When a query is evaluated, it first queries the chain's bottom key/value mapping. If there is no match, the query is then evaluated on the next key/value mapping in the chain, and so forth. If a query reaches the top of the chain with no matches, {\em Chisel} triggers a \code{ParameterUndefinedException}. - -When instantiating a child, the parent can pass its \code{Parameters} object one of two ways: -\begin{enumerate} - \item Explicitly pass its \code{Parameters} object to its child via a second argument to the Module factory, wrapped in \code{Option[Parameters]}: -\begin{scala} -class Tile extends Module { - val width = params(Width) - val core = Module(new Core)(Some(params)) - // Explicit passing of Tile's params to Core -} -\end{scala} - \item Implicitly pass its \code{Parameters} object to its child: -\begin{scala} -class Tile extends Module { - val width = params(Width) - val core = Module(new Core) - // Implicit passing of Tile's params to Core -} -\end{scala} -\end{enumerate} - -If a parent wants to copy/alter the child's dictionary, the parent has two methods to do so: -\begin{enumerate} - \item Provide a PartialFunction mapping as an argument to the Module factory. Internally, {\em Chisel} will copy the parent's \code{Parameters} object and apply the alteration: -\begin{scala} -class Tile extends Module { - val width = params(Width) - val core = Module(new Core,{case Width => 32}) - // Provide PartialFunction to Module factory constructor to alter Core's \code{Parameters} object -} -\end{scala} - \item Call the \code{Parameter.alter} function, which returns a new \code{Parameters} object. This approach gives the programmer access to the new \code{Parameters} object, as well as the ability to use \code{site}, \code{here}, and \code{up} (see Sections \ref{sec::site}, \ref{sec::here}, \ref{sec::up}) : -\begin{scala} -class Tile extends Module { - val width = params(Width) - val core_params = params.alter( - (pname,site,here,up) => pname match { - case Width => 32 - }) - val core = Module(new Core)(Some(core_params)) - // Use the Parameter.alter method to return an altered Parameter object. Only use when site, here, or up mechanisms are needed -} -\end{scala} -\end{enumerate} -A more complicated example of a alteration chain is shown in Figure \ref{fig:alter} and describe below: -\begin{scala} -class Tile extends Module { - ... - val core = Module(new Core, {case FPU => true; case QDepth => 20; case Width => 64}) -} -class Core extends Module { - val fpu = params(FPU) - val width = params(Width) - val depth = params(Depth) - val queue = Module(new Queue,{case Depth => depth*2; case Width => 32}) -} -class Queue extends Module { - val depth = params(Depth) - val width = params(Width) - val mem = Module(new Memory,{case Size => depth * width}) -} -class Memory extends Module { - val size = params(Size) - val width = params(Width) -} -\end{scala} - -\subsection{ChiselConfig and Boilerplate} -\label{sec::config} - -{\em Chisel}'s mechanism to seed the top-level parameters is through a \code{ChiselConfig} object. \code{ChiselConfig.topDefinitions} contains the highest parameter definitions and is of the following form: -\begin{scala} -case object Width extends Field[Int] -class DefaultConfig extends ChiselConfig { - val topDefinitions:World.TopDefs = { - (pname,site,here) => pname match { - case Width => 32 - } - } -} -\end{scala} -Normally, a design calls \code{chiselMain.apply} to instantiate a design. To use {\em Chisel}'s parameterization mechanism and correctly seed a \code{ChiselConfig}, one should instead call \code{chiselMain.run} with the design NOT surrounded by the \code{Module} factory. The reason for this change is to preserve backwards compatibility with existing designs, although we intend to fix this in future releases. - -An example of calling \code{chiselMain.run} is as follows: -\begin{scala} -object Run { - def main(args: Array[String]): Unit = { - chiselMain.run(args, () => new Tile()) - } -} -\end{scala} -To instantiate a design with a specific \code{ChiselConfig}, simply call the {\em Chisel} compiler with the \code{-{-}configInstance {\it project\_name.configClass\_name}} argument. - -\subsection{Using site} -\label{sec::site} - -\begin{figure*} -\begin{center} -\begin{tabular}{cc} -\includegraphics[height=2.0in]{figs/sitea} & -\includegraphics[height=2.0in]{figs/siteb} \\ -(a) Core's key/value chain and flat map & (b) Cache's key/value chain and flat map \\ -\end{tabular} -\end{center} -\caption{For (a), site(Location) will return Core, while in (b) site(Location) will return Cache.} -\label{fig:site} -\end{figure*} -To help the designer express dependencies between parameters, we added the \code{site} mechanism. To understand its function, remember that conceptually, a queried Module's params member first looks at the bottom key/value mapping in its chain of key/value mappings. If there is no match, the query moves up the chain. - -Suppose we have some modules which have following form: - -\begin{scala} -class Core extends Module { - val data_width = params(Width) - ... -} -class Cache extends Module { - val line_width = params(Width) - ... -} -\end{scala} -Unfortunately, both have identical queries for \code{Width} but, for this example's sake, have different semantic meaning. Inside a core, \code{Width} means the word size, while in the \code{Cache}, \code{Width} means the width of a cache line. We want to be able to easily tailor the parameter's response to either query. - -The \code{site} mechanism allows a key/value mapping in the middle of the chain to make its own queries that start at the bottom of the chain. - -Consider the following example: -\begin{scala} -class DefaultConfig extends ChiselConfig { - val top:World.TopDefs = { - (pname,site,here) => pname match { - case Width => site(Location) match { - case 'core' => 64 // data width - case 'cache' => 128 // cache line width - } - } - } -} -class Tile extends Module { - val core = Module(new Core, {case Location => 'core'}) - val cache = Module(new Cache, {case Location => 'cache'}) -} -\end{scala} -The top-level key/value mapping is using \code{site} to query the bottom of the chain for \code{Location}. Depending on what value returns (either \code{'core'} or \code{'cache'}), the top-level key/value mapping produces a different value (Figure \ref{fig:site}). - -\subsection{Using here} -\label{sec::here} - -\begin{figure}[h] -\centering -\includegraphics[width=3in]{figs/here} -\caption{Instead of using 128 or 4 directly, we can access it via here(Sets) and here(Ways), respectively.} -\label{fig:alter} -\end{figure} - -If a parameter is a deterministic function of other parameters expressed at the same group in the key/value mapping chain, one does not want to duplicate a value, as giving a new value would require multiple changes. Instead, one can use the \code{here} mechanism to query the same group of key/value mappings that \code{here} was called: - -\begin{scala} -class Tile extends Module { - val cache_params = params.alter( - (pname, site, here, up) => pname match { - case Sets => 128 - case Ways => 4 - case Size => here(Sets)*here(Ways) - }) - val cache = Module(new Cache)(cache_params) -} -\end{scala} - -\subsection{Using up} -\label{sec::up} - -The \code{up} mechanism enables the user to query the parent group of key/value mappings. It is equivalent to calling \code{Parameters.apply} directly, but can be done within calling \code{Parameters.alter}. For an example use, see Section \ref{sec::rename}. - -\section{Examples} -\label{sec:examples} - -The three goals of any parameterization scheme are: (1) all searchable parameters are exposed at the top level; (2) source code must never change when evaluating different points; (3) adding new parameters requires little source code change. After each example is described, we present the simplest parameterization scheme that supports the desired design space without violating any of the three goals. As examples grow in complexity, so too must the simplest parameterization scheme, until we arrive at the current advanced parameterization method. - -\subsection{Simple Parameters} - -\begin{figure}[h] -\centering -\includegraphics[width=3in]{figs/ex1} -\caption{For a few number of parameters, the simplest scheme is to pass them directly via constructor arguments.} -\label{fig:ex1} -\end{figure} - -In this simple design, we only vary core and cache-specific parameters. The most straightforward parameterization scheme is passing all parameters via arguments to \code{Tile}'s constructor. These values are then passed to \code{Core} and \code{Cache} via their respective constructors: - -\begin{scala} -class Tile (val fpu:Boolean, val ic_sets:Int, val ic_ways:Int, val dc_sets:Int, val dc_ways:Int) extends Module { - val core = Module(new Core(fpu)) - val icache = Module(new Cache(ic_sets,ic_ways) - val dcache = Module(new Cache(dc_sets,dc_ways)) - ... -} -class Core (val fpu:Boolean) {...} -class Cache(val sets:Int, val ways:Int) extends Module {...} -\end{scala} - -No source code changes are necessary to explore our parameter space, and all searchable parameters are exposed at the top. In addition, adding a new parameter, because this example is simple, requires very few changes to our source code. - -\subsection{Disjoint Parameter Sets} - -\begin{figure}[h] -\centering -\includegraphics[width=3in]{figs/ex2} -\caption{For disjoint parameter sets, we can group sets of parameters into configuration objects to pass as constructor arguments.} -\label{fig:ex2} -\end{figure} - -In this next design, we are designing a chip which could instantiate different cores, each with its own set of parameters. If we apply our simple solution, the number of arguments to \code{Tile}'s constructor would be huge as it must contain all parameters for all possible cores (which would likely be much greater than two cores!). - -One could propose that a better solution would be to group parameters into configuration objects. For example, we could group all \code{BigCore} parameters into a \code{BigCoreConfig} case class, and all \code{SmallCore} parameters into a \code{SmallCoreConfig} class, both of which extend \code{CoreConfig}. In addition, we have our caches and \code{Tile} accept a \code{CacheConfig} and \code{TileConfig}, respectively, within their constructors. - -\begin{scala} -abstract class CoreConfig {} -case class BigCoreConfig(iq_depth:Int, lsq_depth:Int) extends CoreConfig -case class SmallCoreConfig(fpu:Boolean) extends CoreConfig -case class CacheConfig(sets:Int, ways:Int) -case class TileConfig(cc:CoreConfig, icc:CacheConfig, dcc:CacheConfig) - -class Tile (val tc:TileConfig) extends Module { - val core = tc.cc match { - case bcc:BigCoreConfig => Module(new BigCore(tc.bcc)) - case scc:SmallCoreConfig => Module(new SmallCore(tc.scc)) - } - val icache = Module(new Cache(tc.icc) - val dcache = Module(new Cache(tc.dcc)) - ... -} -... -\end{scala} - -\subsection{Location-Independent Parameters} - -\begin{figure}[h] -\centering -\includegraphics[width=3in]{figs/ex3} -\caption{For location-independent parameters, every module has a parameter dictionary, which they can copy and alter before passing to each child module.} -\label{fig:ex3} -\end{figure} - -The subtle reason why nested configuration objects are extremely brittle is the structure of the nested configuration objects encodes the module hierarchy. Given a new design described in Figure \ref{fig:ex3}, we assume that \code{BigCore}'s IQ and LSQ, as well as the icache and dcache, instantiate a \code{Memory} module. This Memory module contains a \code{width} parameter, and in order for the design to function correctly, all of Memory widths must be set to the same value. To ensure this requirement, the follow code might be written: - -\begin{scala} -case class MemConfig(size:Int, banks:Int, width:Int) -case class CacheConfig(sets:Int, ways:Int, mc:MemConfig) -case class QueueConfig(depth:Int, mc:MemConfig) -case class BigCoreConfig(iqc:QueueConfig, lsqc:QueueConfig, mc:MemConfig) - -case class TileConfig(cc:CoreConfig, icc:CacheConfig, dcc:CacheConfig) - -class Tile (val tc:TileConfig) extends Module { - val core = tc.cc match { - case bcc:BigCoreConfig => Module(new BigCore(tc.bcc)) - case scc:SmallCoreConfig => Module(new SmallCore(tc.scc)) - } - val icache = Module(new Cache(tc.icc) - val dcache = Module(new Cache(tc.dcc)) - - require(tc.dcc.mc.width == tc.icc.mc.width) - require(tc.bcc.iqc.mc.width == tc.bcc.lsqc.mc.width) - require(tc.dcc.mc.width == tc.bcc.lsqc.mc.width) - ... -} -... -\end{scala} - -The series of require statements is extremely brittle, as any change in our design's hierarchy requires massive rewrites of all of these statements. Omitting the require statements is not a viable option; these statements are necessary to enforce this fundamental design requirement. - -This flaw in configuration objects leads us towards the first functionality of our custom parameterization solution, namely a copy/alter dictionary of type \code{Parameters}. We use this key-value structure (map or dictionary) to store a module's parameters. - -To parameterize the design in Figure \ref{fig:ex3}, we implicitly pass the \code{Parameters} object and, if an alter is needed, provide a \code{PartialFunction} to the \code{Module} factory. Recall from Section \ref{sec:advanced} that the class \code{MyConfig} (extends \code{ChiselConfig}) must be passed to the {\em Chisel} compiler via the \code{-{-}configInstance} flag to seed the top-level parameters: -\begin{scala} -class DefaultConfig() extends ChiselConfig { - val top:World.TopDefs = { - (pname,site,here) => pname match { - case IQ_depth => 10 - case LSQ_depth =>10 - case Ic_sets => 128 - case Ic_ways => 2 - case Dc_sets => 512 - case Dc_ways => 4 - case Width => 64 - // since any module querying Width should return 64, the name should NOT be unique to modules - } - } -} -class Tile extends Module { - val core = Module(new Core)(params) - val ic_sets = params(Ic_sets) - val ic_ways = params(Ic_ways) - val icache = Module(new Cache, {case Sets => ic_sets; case Ways => ic_ways}) - // we can rename Ic_sets to Sets, effectively isolating Cache's query keys from any design hierarchy dependence - val dc_sets = params(Dc_sets) - val dc_ways = params(Dc_ways) - val dcache = Module(new Cache, {case Sets => dc_sets; case Ways => dc_ways}) - // similarly we rename Dc_sets to Sets and Dc_ways to Ways -} -class Core extends Module { - val iqdepth = params(IQ_depth) - val iq = Module(new Queue, {case Depth => iqdepth}) - val lsqdepth = params(LSQ_depth) - val lsq = Module(new Queue, {case Depth => lsqdepth}) - ... -} -class Queue extends Module { - val depth = params(Depth) - val mem = Module(new Memory,{case Size => depth}) - ... -} -class Cache extends Module { - val sets = params(Sets) - val ways = params(Ways) - val mem = Module(new Memory,{case Size => sets*ways}) -} -class Memory extends Module { - val size = params(Size) - val width = params(Width) -} -\end{scala} - -Although this parameterization method is reasonably verbose, it scales well with adding parameters, requires no source changes, and allows a single parameter, such as \code{Width}, to change all leaf modules. - -\subsection{Location-Specific Parameters} - -\begin{figure}[h] -\centering -\includegraphics[width=3in]{figs/ex4} -\caption{For location-dependent parameters, we can use the \code{site} mechanism to customize these parameters at the top level.} -\label{fig:ex4} -\end{figure} - -As we saw in the previous section, copying and altering a \code{Parameters} object can be verbose. If we wanted to add an ECC parameter to our \code{Memory} module, which depends on where the \code{Memory} is instantiated, we would change source code in multiple parents to rename each parameter (e.g. ECC\_icache => ECC). - -In the example depicted in Figure \ref{fig:ex4}, we instead use the \code{site} functionality of our \code{Parameters} object to obtain location-specific information, and tailor the value we return to that location-specific value. After adding the location-specific information, we drastically reduce the amount of code changes necessary: - -\begin{scala} -class DefaultConfig() extends ChiselConfig { - val top:World.TopDefs = { - (pname,site,here) => pname match { - case Depth => site(Queue_type) match { - case 'iq' => 20 - case 'lsq' => 10 - } - case Sets => site(Cache_type) match { - case 'i' => 128 - case 'd' => 512 - } - case Ways => site(Cache_type) match { - case 'i' => 2 - case 'd' => 4 - } - case Width => 64 - // since any module querying Width should return 64, the name should NOT be unique to modules - case ECC => site(Location) match { - 'incore' => false - 'incache' => true - } - } - } -} -class Tile (val params:Parameters) extends Module { - val core = Module(new Core,{Location => 'incore'}) - // we can give core and its child modules a location identifier - - val cacheparams = params.alter({Location => 'incache'}) - // we can give both caches and all their child modules a location identifier - val icache = Module(new ICache)(cacheparams) - val dcache = Module(new DCache)(cacheparams) -} -class Core extends Module { - val iq = Module(new IQ) - val lsq = Module(new LSQ) - ... -} -class IQ extends Module { - val depth = params(Depth) - val mem = Module(new Memory, {Size = depth}) - // in some cases, using copy/alter is preferred instead of \code{site} (see Design Heuristics for more details) - ... -} -class LSQ extends Module { - val depth = params(Depth) - val mem = Module(new Memory, {Size = depth}) - ... -} -class ICache extends Module { - val sets = params(Sets) - val ways = params(Ways) - val mem = Module(new Memory,{Size => sets*ways}) -} -class DCache extends Module { - val sets = params(Sets) - val ways = params(Ways) - val mem = Module(new Memory, {Size => sets*ways}) -} -class Memory extends Module { - val size = params(Size) - val ecc = params(ECC) -} -\end{scala} - -\subsection{Derivative Parameters} - -\begin{figure}[h] -\centering -\includegraphics[width=1.5in]{figs/ex5} -\caption{To derive a parameter from another top-level parameter, we can use the here functionality to avoid duplicating a parameter value.} -\label{fig:ex5} -\end{figure} - -In Figure \ref{fig:ex5}, we always want our ROB to be four-thirds the size of the difference between the number physical registers and the number of architectural registers. If we express this in \code{MyConfig.top}, it could look like the following: - -\begin{scala} -case object NUM_arch_reg extends Field[Int] -case object NUM_phy_reg extends Field[Int] -case object ROB_size extends Field[Int] -class DefaultConfig() extends ChiselConfig { - val top:World.TopDefs = { - (pname,site,here) => pname match { - case NUM_arch_reg => 32 - case NUM_phy_reg => 64 - case ROB_size => 4*(64-32)/3 - } -} -\end{scala} -However, if we later increase the number of physical registers, we need to remember to update the value in the derivation of the ROB size. To avoid this potential error, one should use the 'here' functionality to query the same group of parameters: - -\begin{scala} -class DefaultConfig() extends ChiselConfig { - val top:World.TopDefs = { - (pname,site,here) => pname match { - case NUM_arch_reg => 32 - case NUM_phy_reg => 64 - case ROB_size => 4*(here(NUM_phy_reg) - here(NUM_arch_reg))/3 - } -} -\end{scala} - -\subsection{Renaming Parameters} -\label{sec::rename} - -\begin{figure}[h] -\centering -\includegraphics[width=1.5in]{figs/ex6} -\caption{To rename or programmatically alter a parameter based on the previous value, one can use the up mechanism to query the parent's \code{Parameters} object.} -\label{fig:ex6} -\end{figure} - -In Figure \ref{fig:ex6}, both cache modules query for a \code{sets} parameter. However, \code{Tile} has \code{ic\_sets} and \code{dc\_sets} as parameters. To rename the parameters, we can read the parent value and alter the child's \code{Parameters} object: - -\begin{scala} -class Tile extends Module { - val ic_sets = params(Ic_sets) - val ic = Module(new Cache,{case Sets => ic_sets}) - val dc_sets = params(Ic_sets) - val dc = Module(new Cache,{case Sets => dc_sets}) - ... -} -\end{scala} -Alternatively, we can use the 'up' mechanism within the Parameters.alter method to query the parent module's Parameter object: -\begin{scala} -class Tile extends Module { - val ic_params = params.alter( - (pname,site,here,up) => pname match { - case Sets => up(Ic_sets) - } - ) - val ic = Module(new Cache)(ic_params) - ... -} -\end{scala} -In general one should never use the \code{up} mechanism as it is more verbose. However, it can be useful if the parent is making significant changes to a child's \code{Parameters} object, as all changes can be contained the \code{Parameter.alter} method because one has access to all three central mechanisms (\code{up}, \code{site}, and \code{here}). - -\section{External Interface} -\label{sec:knobs} - -So far, this document has only describe mechanisms to manipulate parameters at a top-level class (\code{ChiselConfig}). However, to actually generate multiple C++ or Verilog designs, we need to manually change these parameters. - -One would prefer to express design constraints (parameter ranges, dependencies, constraints) and leave the actual instantiation of a specific design separate from the expression of the valid design space. - -With that motivation, {\em Chisel} has an additional feature based around the concept of ``Knobs,'' or parameters that are created specifically to explore a design space. This section will describe Knobs and their uses, the Dump Object, adding constraints to parameters/Knobs, and the two modes to running the Chisel compiler: --configCollect and --configInstance. - -\subsection{Knobs} -A generator has some parameters that are fixed, and others that dictate the specific design point being generated. These generator-level parameters, called Knobs, have an additional key-value mapping to allow external programs and users to easily overwrite their values. - -Knobs can only be instantiated within a \code{ChiselConfig} subclass's \code{topDefinitions}: - -\begin{scala} -package example -class MyConfig extends ChiselConfig { - val topDefinitions:World.TopDefs = { - (pname,site,here) => pname match { - case NTiles => Knob('NTILES') - case .... => .... // other non-generator parameters go here - } - } - override val knobValues:Any=>Any = { - case 'NTILES' => 1 // generator parameter assignment - } -} -\end{scala} - -When the query \code{NTiles} matches within topDefinitions, the \code{Knob('NTILES')} is returned. Internally, Chisel will lookup \code{'NTILES'} within MyConfig.knobValues and return 1. As described in Section \ref{sec::config}, the flag required to execute a generator with this specific config is: - -\code{sbt run ... -{-}configInstance example.MyConfig} - -Suppose we wanted to instantiate a new design that had two tiles: simply use Scala's class inheritance and overwrite the knobValues method: - -\begin{scala} -package example -class MyConfig2 extends MyConfig { - override val knobValues:Any=>Any = { - case 'NTILES' => 2 // will generate new design with 2 tiles - } -} -\end{scala} - -Notice that both classes can exist in the source code, so both designs can be instantiated from the commandline. For the new design with two tiles, simply call: - -\code{sbt run ... -{-}configInstance example.MyConfig2} - -\subsection{Dump} - -Downstream from Chisel, other tools might need to know specific parameter/Knob assignments. If so, just pass the Knob/value to the Dump object, which will write the name and value to a file, then return the Knob/value: - -\begin{scala} -package example -class MyConfig extends ChiselConfig { - val topDefinitions:World.TopDefs = { - (pname,site,here) => pname match { - case Width => Dump('Width',64) // will return 64. Requires naming the parameter as the 1st argument - case NTiles => Dump(Knob('NTILES')) // will return Knob('NTILES'), no name needed - } - } - override val knobValues:Any=>Any = { - case 'NTILES' => 1 // generator parameter assignment - } -} -\end{scala} - -The name and value of each dumped parameter will be written to a \code{*.knb} file located in the directory set by \code{-{-}targetDir {\it path}}. - -\subsection{Constraints} - -Now that external programs/users can easily overwrite a configuration's \code{knobValue} method, we have provided a mechanism for defining legal ranges for Knobs. Within a \code{ChiselConfig}, one can overwrite another method called \code{topConstraints}: - -\begin{scala} -package example -class MyConfig extends ChiselConfig { - val topDefinitions:World.TopDefs = { - (pname,site,here) => pname match { - case NTiles => Knob('NTILES') - } - } - override val topConstraints:List[ViewSym=>Ex[Boolean]] - = List( { ex => ex(NTiles) > 0 }, - { ex => ex(NTiles) <= 4 }) - override val knobValues:Any=>Any = { - case 'NTILES' => 1 // generator parameter assignment - } -} -\end{scala} - -Now, if someone tried to instantiate our design with the following configuration and command, it would fail: - -\begin{scala} -package example -class BadConfig extends ChiselConfig { - override val knobValues:Any=>Any = { - case 'NTILES' => 5 // would violate our constraint, throws an error - } -} - -// throws 'Constriant failed' error -sbt run ... --configInstance example.BadConfig -\end{scala} - -Constraints can be declared anywhere in the design, not just at the top level, by calling a Parameter's \code{constrain} method: - -\begin{scala} -package example -class MyConfig extends ChiselConfig { - val topDefinitions:World.TopDefs = { - (pname,site,here) => pname match { - case NTiles => Knob('NTILES') - } - } - override val knobValues:Any=>Any = { - case 'NTILES' => 1 // generator parameter assignment - } -} -class Tile extends Module { - params.constrain( ex => ex(NTiles) > 0 ) - params.constrain( ex => ex(NTiles) <= 4 ) -} -object Run { - def main(args: Array[String]): Unit = { - chiselMain.run(args, () => new Tile()) - } -} - -sbt runMain example.Run ... --configInstance example.MyConfig -\end{scala} - -Finally, if a designer wants to know a design's constraints, they can execute Chisel with the \code{-{-}configCollect {\it project\_name.config\_name}} flag, which will dump a list of the constraints to a \code{*.cst} file, located in the path specificed by \code{-{-}targetDir {\it path}}: - -\begin{scala} -sbt runMain example.Run ... --configCollect example.MyConfig --targetDir -\end{scala} - -\section{Design Heuristics} -\label{sec:heuristics} - -TODO - - -% \section{Acknowlegements} -% -\begin{thebibliography}{50} -\bibitem{chisel-dac12} Bachrach, J., Vo, H., Richards, B., Lee, Y., Waterman, - A., Avi\v{z}ienis, Wawrzynek, J., Asanovi\'{c} \textsl{Chisel: - Constructing Hardware in a Scala Embedded Language} -in DAC '12. -\bibitem{programming-in-scala}Odersky, M., Spoon, L., Venners, - B. \textsl{Programming in Scala} by Artima. -\bibitem{programming-scala}Payne, A., Wampler, D. - \textsl{Programming Scala} by O'Reilly books. -% \bibitem{gel} Bachrach, J., Qumsiyeh, D., Tobenkin, M. \textsl{Hardware Scripting in Gel}. -% in Field-Programmable Custom Computing Machines, 2008. FCCM '08. 16th. -\end{thebibliography} - - -\end{document} diff --git a/doc/style/scala.tex b/doc/style/scala.tex deleted file mode 100644 index 26299e9d..00000000 --- a/doc/style/scala.tex +++ /dev/null @@ -1,64 +0,0 @@ -% "define" Scala -\usepackage[T1]{fontenc} -\usepackage[scaled=0.82]{beramono} -\usepackage{microtype} - -\sbox0{\small\ttfamily A} -\edef\mybasewidth{\the\wd0 } - -\lstdefinelanguage{scala}{ - morekeywords={abstract,case,catch,class,def,% - do,else,extends,false,final,finally,% - for,if,implicit,import,match,mixin,% - new,null,object,override,package,% - private,protected,requires,return,sealed,% - super,this,throw,trait,true,try,% - type,val,var,while,with,yield}, - sensitive=true, - morecomment=[l]{//}, - morecomment=[n]{/*}{*/}, - morestring=[b]", - morestring=[b]', - morestring=[b]""" -} - -\usepackage{color} -\definecolor{dkgreen}{rgb}{0,0.6,0} -\definecolor{gray}{rgb}{0.5,0.5,0.5} -\definecolor{mauve}{rgb}{0.58,0,0.82} - -% Default settings for code listings -\lstset{frame=tb, - language=scala, - aboveskip=3mm, - belowskip=3mm, - showstringspaces=false, - columns=fixed, % basewidth=\mybasewidth, - basicstyle={\small\ttfamily}, - numbers=none, - numberstyle=\footnotesize\color{gray}, - % identifierstyle=\color{red}, - keywordstyle=\color{blue}, - commentstyle=\color{dkgreen}, - stringstyle=\color{mauve}, - frame=single, - breaklines=true, - breakatwhitespace=true, - procnamekeys={def, val, var, class, trait, object, extends}, - procnamestyle=\ttfamily\color{red}, - tabsize=2 -} - -\lstnewenvironment{scala}[1][] -{\lstset{language=scala,#1}} -{} -\lstnewenvironment{cpp}[1][] -{\lstset{language=C++,#1}} -{} -\lstnewenvironment{bash}[1][] -{\lstset{language=bash,#1}} -{} -\lstnewenvironment{verilog}[1][] -{\lstset{language=verilog,#1}} -{} - diff --git a/doc/style/talk.tex b/doc/style/talk.tex deleted file mode 100644 index 19584954..00000000 --- a/doc/style/talk.tex +++ /dev/null @@ -1,38 +0,0 @@ -\lstset{basicstyle={\footnotesize\ttfamily}} - -\usetheme[height=8mm]{Rochester} -\setbeamersize{text margin left=3mm} -\setbeamersize{text margin right=3mm} -\setbeamertemplate{navigation symbols}{} - -\definecolor{Cobalt}{rgb}{0.25,0.125,0.70} -\definecolor{RedOrange}{rgb}{0.8,0.25,0.0} -% \definecolor{RedOrange}{rgb}{0.8,0.775,0.25} -\def\frametitledefaultcolor{Cobalt} -\def\frametitleproblemcolor{RedOrange} - -\lstset{basicstyle={\footnotesize\ttfamily}} - -\setbeamertemplate{frametitle} -{ -\vskip-7mm -\textbf{\insertframetitle}\hfill\insertframenumber -} -\setbeamercolor{frametitle}{bg=\frametitledefaultcolor} - -\newenvironment{sample}{\VerbatimEnvironment\begin{footnotesize}\begin{semiverbatim}}{\end{semiverbatim}\end{footnotesize}} - -\newenvironment{FramedSemiVerb}% -{\begin{Sbox}\begin{minipage}{.94\textwidth}\begin{semiverbatim}}% -{\end{semiverbatim}\end{minipage}\end{Sbox} -\setlength{\fboxsep}{8pt}\fbox{\TheSbox}} - -\newenvironment{FramedVerb}% -{\VerbatimEnvironment -\begin{Sbox}\begin{minipage}{.94\textwidth}\begin{Verbatim}}% -{\end{Verbatim}\end{minipage}\end{Sbox} -\setlength{\fboxsep}{8pt}\fbox{\TheSbox}} - -% \newenvironment{sample}{\VerbatimEnvironment\begin{footnotesize}\begin{Verbatim}}{\end{Verbatim}\end{footnotesize}} -\newcommand{\code}[1]{\begin{footnotesize}{\tt #1}\end{footnotesize}} -\newcommand{\comment}[1]{{\color{Green}\it\smaller #1}} diff --git a/doc/talks/aspire/figs/design-loop-compile-test-debug-eval.pdf b/doc/talks/aspire/figs/design-loop-compile-test-debug-eval.pdf deleted file mode 100644 index b5501b26..00000000 Binary files a/doc/talks/aspire/figs/design-loop-compile-test-debug-eval.pdf and /dev/null differ diff --git a/doc/talks/aspire/figs/design-loop-debug.graffle b/doc/talks/aspire/figs/design-loop-debug.graffle deleted file mode 100644 index c1dc927a..00000000 Binary files a/doc/talks/aspire/figs/design-loop-debug.graffle and /dev/null differ diff --git a/doc/talks/aspire/figs/design-loop-debug.pdf b/doc/talks/aspire/figs/design-loop-debug.pdf deleted file mode 100644 index a438f224..00000000 Binary files a/doc/talks/aspire/figs/design-loop-debug.pdf and /dev/null differ diff --git a/doc/talks/aspire/figs/design-loop-program-compile-test-debug-eval.graffle b/doc/talks/aspire/figs/design-loop-program-compile-test-debug-eval.graffle deleted file mode 100644 index 1f40bee1..00000000 Binary files a/doc/talks/aspire/figs/design-loop-program-compile-test-debug-eval.graffle and /dev/null differ diff --git a/doc/talks/aspire/figs/design-loop-program-compile-test-debug-eval.pdf b/doc/talks/aspire/figs/design-loop-program-compile-test-debug-eval.pdf deleted file mode 100644 index fac9140e..00000000 Binary files a/doc/talks/aspire/figs/design-loop-program-compile-test-debug-eval.pdf and /dev/null differ diff --git a/doc/talks/aspire/figs/design-loop-program-eval.graffle b/doc/talks/aspire/figs/design-loop-program-eval.graffle deleted file mode 100644 index 3772a375..00000000 Binary files a/doc/talks/aspire/figs/design-loop-program-eval.graffle and /dev/null differ diff --git a/doc/talks/aspire/figs/design-loop-program-eval.pdf b/doc/talks/aspire/figs/design-loop-program-eval.pdf deleted file mode 100644 index 996c66ee..00000000 Binary files a/doc/talks/aspire/figs/design-loop-program-eval.pdf and /dev/null differ diff --git a/doc/talks/aspire/figs/design-loop-programming.graffle b/doc/talks/aspire/figs/design-loop-programming.graffle deleted file mode 100644 index a6019efa..00000000 Binary files a/doc/talks/aspire/figs/design-loop-programming.graffle and /dev/null differ diff --git a/doc/talks/aspire/figs/design-loop-programming.pdf b/doc/talks/aspire/figs/design-loop-programming.pdf deleted file mode 100644 index 7b4e497e..00000000 Binary files a/doc/talks/aspire/figs/design-loop-programming.pdf and /dev/null differ diff --git a/doc/talks/aspire/figs/design-loop-test-debug-eval.graffle b/doc/talks/aspire/figs/design-loop-test-debug-eval.graffle deleted file mode 100644 index 68054330..00000000 Binary files a/doc/talks/aspire/figs/design-loop-test-debug-eval.graffle and /dev/null differ diff --git a/doc/talks/aspire/figs/design-loop-test-debug-eval.pdf b/doc/talks/aspire/figs/design-loop-test-debug-eval.pdf deleted file mode 100644 index fcf33206..00000000 Binary files a/doc/talks/aspire/figs/design-loop-test-debug-eval.pdf and /dev/null differ diff --git a/doc/talks/aspire/figs/design-loop-test.graffle b/doc/talks/aspire/figs/design-loop-test.graffle deleted file mode 100644 index cd53f6b3..00000000 Binary files a/doc/talks/aspire/figs/design-loop-test.graffle and /dev/null differ diff --git a/doc/talks/aspire/figs/design-loop-test.pdf b/doc/talks/aspire/figs/design-loop-test.pdf deleted file mode 100644 index ed85b178..00000000 Binary files a/doc/talks/aspire/figs/design-loop-test.pdf and /dev/null differ diff --git a/doc/talks/aspire/figs/design-loop.graffle b/doc/talks/aspire/figs/design-loop.graffle deleted file mode 100644 index 4f0b4748..00000000 Binary files a/doc/talks/aspire/figs/design-loop.graffle and /dev/null differ diff --git a/doc/talks/aspire/figs/design-loop.pdf b/doc/talks/aspire/figs/design-loop.pdf deleted file mode 100644 index 01c18086..00000000 Binary files a/doc/talks/aspire/figs/design-loop.pdf and /dev/null differ diff --git a/doc/talks/dac12/dac12-talk.tex b/doc/talks/dac12/dac12-talk.tex deleted file mode 100644 index dabf7ead..00000000 --- a/doc/talks/dac12/dac12-talk.tex +++ /dev/null @@ -1,645 +0,0 @@ -\documentclass[xcolor=pdflatex,dvipsnames,table]{beamer} -\usepackage{epsfig,graphicx} -\usepackage{palatino} -\usepackage{fancybox} -\usepackage{relsize} -\usepackage[procnames]{listings} - -\input{../../style/scala.tex} -\input{../../style/talk.tex} - -% \def\poster{1} - -\title{Chisel: Constructing Hardware In a Scala Embedded Language} -\author[Jonathan Bachrach et al]{Jonathan Bachrach, Huy Vo, Brian Richards, \\ -Yunsup Lee, Andrew Waterman, Rimas Avizienis, \\ -John Wawrzynek, Krste Asanovic} -\date{\today} -\institute[UC Berkeley]{EECS UC Berkeley} - -\begin{document} - -\begin{frame} -\titlepage -\end{frame} - -\begin{frame}[fragile] -\frametitle{21st Century Architecture Design} -{\Large\textbf{Harder to get hardware / software efficiency gains}} -\vskip5mm -\begin{itemize} -\item Need massive design-space exploration -\begin{itemize} -\item Hardware and software codesign and cotuning -\end{itemize} -\item Need meaningful results -\begin{itemize} -\item Cycle counts -\item Cycle time, power and area -\item Real chips -\end{itemize} -\item Traditional architectural simulators, hardware-description - languages, and tools are inadequate -\begin{itemize} -\item Slow -\item Inaccurate -\item Error prone -\item Difficult to modify and parameterize -\end{itemize} -\end{itemize} -\end{frame} - -\begin{frame}[fragile] -\frametitle{Bottom Line -- Shorten Design Loop} -{\LARGE\textbf{If you make it}} -\vskip2mm -\begin{itemize} -\item Easier to make design changes -\begin{itemize} -\item Fewer lines of design code ( \textbf{>> 3x} ) -\item More reusable code -\item Parameterize designs -\end{itemize} -\item Faster to test results ( \textbf{>> 8x} ) -\begin{itemize} -\item Fast compilation -\item Fast simulation -\item Easy testing -\item Easy verification -\end{itemize} -\end{itemize} -\vskip0.8cm -{\LARGE\textbf{Then you can}} -\begin{itemize} -\item Explore more design space -\end{itemize} - -\end{frame} - -\begin{frame}[fragile] -\frametitle{Chisel is ...} - -\begin{columns}[c] - -\column{0.55\textwidth} - -\begin{itemize} -\item Best of hardware and software design ideas -\item Embedded within Scala language to leverage mindshare and language design -\item Algebraic construction and wiring -\item Hierarchical, object oriented, and functional construction -\item Abstract data types and interfaces -\item Bulk connections -\item Multiple targets -\begin{itemize} -\item Simulation and synthesis -\item Memory IP is target-specific -\end{itemize} -\end{itemize} - -\column{0.40\textwidth} - -\begin{center} -single source \\ -\includegraphics[width=0.99\textwidth]{./figs/targets.pdf} \\ -multiple targets \\ -\end{center} - -\end{columns} - -\end{frame} - -\begin{frame}[fragile] -\frametitle{The Scala Programming Language} - -\begin{columns}[c] - -\column{0.75\textwidth} - -\begin{itemize} -\item Compiled to JVM -\begin{itemize} -\item Good performance -\item Great Java interoperability -\item Mature debugging, execution environments -\end{itemize} -\item Object Oriented -\begin{itemize} -\item Factory Objects, Classes -\item Traits, overloading etc -\end{itemize} -\item Functional -\begin{itemize} -\item Higher order functions -\item Anonymous functions -\item Currying etc -\end{itemize} -\item Extensible -\begin{itemize} -\item Domain Specific Languages (DSLs) -\end{itemize} -\end{itemize} - -\column{0.25\textwidth} - -\begin{center} -\includegraphics[height=0.4\textheight]{../../bootcamp/figs/programming-scala.pdf} \\ -\includegraphics[height=0.4\textheight]{../../bootcamp/figs/programming-in-scala.pdf} -\end{center} - -\end{columns} -\end{frame} - - -\begin{frame}[fragile]{Primitive Datatypes} -\begin{itemize} -\item{Chisel has 4 primitive datatypes} -\begin{description} -\item[Bits] -- raw collection of bits -\item[Fix] -- signed fixed-point number -\item[UFix] -- unsigned fixed-point number -\item[Bool] -- Boolean value -\end{description} -\item Can do arithmetic and logic with these datatypes -\end{itemize} - -\textbf{Example Literal Constructions} -\begin{scala} -val sel = Bool(false) -val a = UFix(25) -val b = Fix(-35) -\end{scala} -where \verb+val+ is a Scala keyword used to declare variables whose values won't change -\end{frame} - -\begin{frame}[fragile]{Aggregate Data Types} - -\textbf{Bundle} - -\begin{itemize} -\item User-extendable collection of values with named fields -\item Similar to structs -\end{itemize} - -\begin{footnotesize} -% \textbf{Bundle Example} -\begin{scala} -class MyFloat extends Bundle{ - val sign = Bool() - val exponent = UFix(width=8) - val significand = UFix(width=23) -} -\end{scala} -\end{footnotesize} - -\textbf{Vec} - -\begin{itemize} -\item Create indexable collection of values -\item Similar to array -\end{itemize} - -\begin{footnotesize} -% \textbf{Vec Example} -\begin{scala} -val myVec = Vec(5){ Fix(width=23) } -\end{scala} -\end{footnotesize} - -\end{frame} - -\begin{frame}[fragile] -\frametitle{Example} -\begin{columns} - -\column{0.45\textwidth} - -\begin{footnotesize} -\begin{scala} -class GCD extends Component { - val io = new Bundle { - val a = UFix(INPUT, 16) - val b = UFix(INPUT, 16) - val z = UFix(OUTPUT, 16) - val valid = Bool(OUTPUT) } - val x = Reg(resetVal = io.a) - val y = Reg(resetVal = io.b) - when (x > y) { - x := x - y - } .otherwise { - y := y - x - } - io.z := x - io.valid := y === UFix(0) -} -\end{scala} -\end{footnotesize} - -\column{0.45\textwidth} - -\begin{center} -\includegraphics[width=0.9\textwidth]{../../bootcamp/figs/gcd.pdf} -\end{center} - -\end{columns} -\end{frame} - -\begin{frame}[fragile]{Polymorphism and Parameterization} -\begin{itemize} -\item Chisel users can define their own parameterized functions -\begin{itemize} -\item Parameterization encourages reusability -\item Data types can be inferred and propagated -\end{itemize} -\end{itemize} - -\textbf{Example Shift Register:} -\begin{scala} -def delay[T <: Bits](x: T, n: Int): T = - if(n == 0) x else Reg(delay(x, n - 1)) -\end{scala} -where -\begin{itemize} -\item The input \verb+x+ is delayed n cycles -\item \verb+x+ can by of any type that extends from \verb+Bits+ -\end{itemize} - -\end{frame} - -\begin{frame}[fragile]{Abstract Data Types} -\begin{itemize} -\item The user can construct new data types -\begin{itemize} -\item Allows for compact, readable code -\end{itemize} -\item Example: Complex numbers -\begin{itemize} -\item Useful for FFT, Correlator, other DSP -\item Define arithmetic on complex numbers -\end{itemize} -\end{itemize} - -\begin{footnotesize} -\begin{scala} -class Complex(val real: Fix, val imag: Fix) - extends Bundle { - def + (b: Complex): Complex = - new Complex(real + b.real, imag + b.imag) - ... -} -val a = new Complex(Fix(32), Fix(-16)) -val b = new Complex(Fix(-15), Fix(21)) -val c = a + b -\end{scala} -\end{footnotesize} - -\end{frame} - -\begin{frame}[fragile, shrink] -\frametitle{Functional Composition} - -% \begin{itemize} -% \item natural -% \item reusable -% \item composable -% \end{itemize} -% \vskip1cm - -\begin{Large} -\begin{columns} - -\column{0.45\textwidth} -\verb+Map(ins, x => x * y)+ \\ -\begin{center} -\includegraphics[height=0.6\textheight]{../../bootcamp/figs/map.pdf} \\[2cm] -\end{center} - -\column{0.45\textwidth} -\vskip2mm -\verb+Chain(n, in, x => f(x))+ \\ -\begin{center} -\includegraphics[width=0.9\textwidth]{../../bootcamp/figs/chain.pdf} \\ -\end{center} - -\verb+Reduce(data, Max)+ \\ -\begin{center} -\includegraphics[width=0.9\textwidth]{../../bootcamp/figs/reduce.pdf} \\ -\end{center} - - -\end{columns} - -\end{Large} - -\end{frame} - -\begin{frame}[fragile]{Generator} -\begin{footnotesize} -\begin{scala} -class Cache(cache_type: Int = DIR_MAPPED, - associativity: Int = 1, - line_size: Int = 128, - cache_depth: Int = 16, - write_policy: Int = WRITE_THRU - ) extends Component { - val io = new Bundle() { - val cpu = new IoCacheToCPU() - val mem = new IoCacheToMem().flip() - } - val addr_idx_width = log2(cache_depth).toInt - val addr_off_width = log2(line_size/32).toInt - val addr_tag_width = 32 - addr_idx_width - addr_off_width - 2 - val log2_assoc = log2(associativity).toInt - ... - if (cache_type == DIR_MAPPED) - ... -\end{scala} -\end{footnotesize} - -\end{frame} - -\begin{frame}[fragile]{Testing} - -\begin{columns} -\column{0.45\textwidth} -{\lstset{basicstyle={\tiny\ttfamily}} -\begin{scala} -package Tutorial { -import Chisel._ -import scala.collection.mutable.HashMap -import scala.util.Random - -class Combinational extends Component { - val io = new Bundle { - val x = UFix(INPUT, 16) - val y = UFix(INPUT, 16) - val z = UFix(OUTPUT, 16) } - io.z := io.x + io.y -} - -class CombinationalTests(c: Combinational) - extends Tester(c, Array(c.io)) { - defTests { - var allGood = true - val vars = new HashMap[Node, Node]() - val rnd = new Random() - val maxInt = 1 << 16 - for (i <- 0 until 10) { - vars.clear() - val x = rnd.nextInt(maxInt) - val y = rnd.nextInt(maxInt) - vars(c.io.x) = UFix(x) - vars(c.io.y) = UFix(y) - vars(c.io.z) = UFix((x + y)&(maxInt-1)) - allGood = step(vars) && allGood - } - allGood - } } } -\end{scala} -} -\column{0.45\textwidth} -{\lstset{basicstyle={\tiny\ttfamily}} -\begin{scala} -class Tester[T <: Component] - (val c: T, val testNodes: Array[Node]) - -def defTests(body: => Boolean) - -def step(vars: HashMap[Node, Node]): Boolean -\end{scala} -} -\begin{tiny} -\begin{itemize} -\item user subclasses \code{Tester} defining DUT and -\code{testNodes} and tests in \code{defTests} body -\item \code{vars} is mapping from \code{testNodes} to literals, called bindings -\item \code{step} runs test with given bindings, where -var values for input ports are sent to DUT, -DUT computes next outputs, and -DUT sends next outputs to Chisel -\item finally \code{step} compares received values against var values - for output ports and returns false if any comparisons fail -\end{itemize} -\end{tiny} - -\begin{center} -\includegraphics[width=0.9\textwidth]{../../tutorial/figs/DUT.pdf} -\end{center} - -\end{columns} -\end{frame} - -\begin{frame}[fragile] -\frametitle{Chisel Line Count Breakdown} - -\begin{columns} - -\column{0.3\textwidth} - -\begin{itemize} -\item \verb+~+5200 lines total -\item Embeds into Scala well -\end{itemize} - -\column{0.7\textwidth} - -\begin{center} -\includegraphics[width=0.9\textwidth]{figs/linecount.png} -\end{center} - -\end{columns} - -\end{frame} - -\begin{frame} -\frametitle {Chisel versus Hand-Coded Verilog} - -\begin{itemize} -\item 3-stage RISCV CPU hand-coded in Verilog -\item Translated to Chisel -\item Resulted in 3x reduction in lines of code -\item Most savings in wiring -\item Lots more savings to go ... -% \item Chisel-generated Verilog gives comparable synthesis quality of results -\end{itemize} - -\end{frame} - -\begin{frame}{Related Work} - -\begin{itemize} -\item SystemVerilog -\begin{itemize} -\item Lacks general purpose programming and extensibility -\end{itemize} -\item Lava -\begin{itemize} -\item Elegant but focus on spatial layout -\end{itemize} -\item Domain-specific (Bluespec + Esterel + AutoESL) -\begin{itemize} -\item Powerful but needs to match task at hand -\end{itemize} -\item Generator language (Genesis2 + SpiralFFT) -\begin{itemize} -\item Either inherit poor abstraction qualities of underlying HDL or -\item Do not provide complete solution -\end{itemize} -\end{itemize} - -\end{frame} - -\begin{frame}[fragile] -\frametitle{Rocket Microarchitecture} -\begin{itemize} -\item 6-stage RISC decoupled integer datapath + 5-stage IEEE FPU + MMU - and non-blocking caches -\item Completely written in Chisel -\end{itemize} -\includegraphics[width=\textwidth]{figs/rocket-microarchitecture.pdf} - -\end{frame} - -\ifx\poster\undefined -\begin{frame}[fragile] -\frametitle{Single Source / Multiple Targets} - -\begin{center} -single source \\ -\includegraphics[width=0.95\textwidth]{./figs/targets.pdf} \\ -multiple targets \ -\end{center} - -\end{frame} -\fi - -\begin{frame}[fragile] -\frametitle{Fast Cycle-Accurate Simulation in C++} - -\begin{itemize} -\item Compiles to single class -\begin{itemize} -\item Keep state and top level io in class fields -\item \verb+clock_lo+ and \verb+clock_hi+ methods -\end{itemize} -\item Generates calls to fast multiword library using C++ templates -\begin{itemize} -\item specializing for small word cases -\item remove branching as much as possible to utilize maximum ILP in processor -\end{itemize} -\end{itemize} - -\end{frame} - -\begin{frame}[fragile] -\frametitle{Simulator Comparison} - -\textbf{Comparison of simulation time when booting Tessellation OS} -\vskip0.5cm - -\begin{footnotesize} -\begin{tabular}{lrrrrrr} -\textbf{Simulator} & \textbf{Compile} & \textbf{Compile} & \textbf{Run} & \textbf{Run} & \textbf{Total} & \textbf{Total} \\ -& \textbf{Time (s)} & \textbf{Speedup} & \textbf{Time (s)} & \textbf{Speedup} & \textbf{Time (s)} & \textbf{Speedup} \\ -\hline -VCS & 22 & 1.000 & 5368 & 1.00 & 5390 & 1.00 \\ -Chisel C++ & 119 & 0.184 & 575 & 9.33 & 694 & 7.77\\ -Virtex-6 & 3660 & 0.006 & 76 & 70.60 & 3736 & 1.44\\ -\end{tabular} -\end{footnotesize} - - -\end{frame} - -\ifx\poster\undefined -\begin{frame} -\frametitle{Simulation Crossover Points} - -% \begin{columns} -% \begin{tabular}{ll} -% \textbf{Simulation} & \textbf{Worth it if ...} \\ -% \hline -% Chisel C++ & millions of cycles \\ -% FPGA & billions of cycles \\ -% \end{tabular} -% -% \column{0.55\textwidth} - -\begin{center} -\includegraphics[height=0.8\textheight]{figs/perf.pdf} -\end{center} - -% \end{columns} - -\end{frame} -\fi - -\begin{frame}[fragile] -\frametitle{Data Parallel Processor Tape Out Results} - -\begin{center} -Completely written in Chisel -\includegraphics[height=0.7\textheight]{figs/ibm45.png} - -\begin{footnotesize} -The data-parallel processor layout results using IBM 45nm SOI 10-metal layer process using memory compiler generated 6T and 8T SRAM blocks. -\end{footnotesize} -\end{center} - -\end{frame} - -\begin{frame}[fragile]{Products} - -\begin{itemize} -\item Open source with BSD license -\begin{itemize} -\item \verb+chisel.eecs.berkeley.edu+ -\item complete set of documentation -\item public alpha now -\end{itemize} -\item Library of components -\begin{itemize} -\item queues, decoders, encoders, popcount, scoreboards, integer ALUs, LFSR, Booth multiplier, iterative divider, ROMs, RAMs, CAMs, TLB, caches, prefetcher, fixed-priority arbiters, round-robin arbiters, IEEE-754/2008 floating-point units -\end{itemize} -\item Set of educational processors including: -\begin{itemize} -\item microcoded processor, one-stage, two-stage, and five-stage pipelines, and an out-of-order processor, all with accompanying visualizations. -\end{itemize} -\end{itemize} - -\end{frame} - -\ifx\poster\undefined -\begin{frame}[fragile] -\frametitle{Future} - -\begin{itemize} -\item Automated design space exploration -\item Insertion of activity counters for power monitors -\item Automatic fault insertion -\item Faster and more scalable simulation -\item More generators -\item More little languages -\item Compilation to UCLID -\end{itemize} - -\end{frame} -\fi - -\ifx\poster\undefined -\begin{frame}[fragile]{Come to Poster} - -\begin{itemize} -\item Open source plans -\item Manual, tutorial, and bootcamp -\item Chisel workflow -\item More on testing -\item Educational processors -\end{itemize} - -\end{frame} -\fi - - - -\end{document} diff --git a/doc/talks/dac12/figs/ibm45.png b/doc/talks/dac12/figs/ibm45.png deleted file mode 100644 index 2fb10d7c..00000000 Binary files a/doc/talks/dac12/figs/ibm45.png and /dev/null differ diff --git a/doc/talks/dac12/figs/linecount.png b/doc/talks/dac12/figs/linecount.png deleted file mode 100644 index 7b2e0eeb..00000000 Binary files a/doc/talks/dac12/figs/linecount.png and /dev/null differ diff --git a/doc/talks/dac12/figs/perf.pdf b/doc/talks/dac12/figs/perf.pdf deleted file mode 100644 index 6b8066ac..00000000 Binary files a/doc/talks/dac12/figs/perf.pdf and /dev/null differ diff --git a/doc/talks/dac12/figs/rocket-microarchitecture.pdf b/doc/talks/dac12/figs/rocket-microarchitecture.pdf deleted file mode 100644 index bf7afff4..00000000 Binary files a/doc/talks/dac12/figs/rocket-microarchitecture.pdf and /dev/null differ diff --git a/doc/talks/dac12/figs/targets.pdf b/doc/talks/dac12/figs/targets.pdf deleted file mode 100644 index 4d9c787c..00000000 Binary files a/doc/talks/dac12/figs/targets.pdf and /dev/null differ diff --git a/doc/talks/microsoft/libs-to-langs-guts-in-scala.tex b/doc/talks/microsoft/libs-to-langs-guts-in-scala.tex deleted file mode 100644 index 2277dc66..00000000 --- a/doc/talks/microsoft/libs-to-langs-guts-in-scala.tex +++ /dev/null @@ -1,769 +0,0 @@ -% \begin{frame}[fragile]{Chisel Today} -% \begin{itemize} -% \item whirlwind tour of chisel -% \item recents results and products -% \item update on upcoming release -% \item future research work -% \end{itemize} -% \end{frame} - -\begin{frame}[fragile] -\frametitle{What is Chisel?} -\vfill -\begin{itemize} -\item {\bf Abstractly}: Chisel is a framework for {\it programmatically} generating circuitry. -\item {\bf Less Abstractly}: Chisel is a software library for creating and connecting circuit components to form a circuit graph. -\item {\bf Concretely}: Chisel is a DSL embedded in Scala for creating and connecting circuit components, with tools for simulation and translation to Verilog. -\end{itemize} -\vspace{3.5cm} -{\it\small * based on slides by my PhD student Patrick Li} -\end{frame} - -\begin{frame}[fragile] -\frametitle{Chisel is a {\it Library}} -\begin{itemize} -\item Classes are provided for circuit components: -\begin{itemize} -\item \verb+Register()+ -\item \verb+Adder()+ -\item \verb+Multiplexor()+ -\item \verb+Wire(name)+ -\item \verb+Constant(name)+ -\end{itemize} - -\noindent -and \verb+new+ used to construct components and \verb+connect+ used to wire them together: -\begin{itemize} -\item \verb+new Register()+ -\item ... -\item \verb+connect(input, output)+ -\end{itemize} -\end{itemize} -\end{frame} - -\begin{frame}[fragile] -\frametitle{What if Chisel was a Scala Library?} -\begin{columns} -\column{0.50\textwidth} -{\lstset{basicstyle={\tiny\ttfamily}} -\begin{scala} -def main(args: Array[String]) = { - // Create Components - val reset = new Wire("reset"); - val counter = new Register("counter"); - val adder = new Adder(); - val multiplexor = new Multiplexor(); - val one = new UInt(1); - val zero = new UInt(0); - - // Connect Components - connect(multiplexor.choice, reset); - connect(multiplexor.in_a, zero.out); - connect(multiplexor.in_b, adder.out); - connect(counter.in, multiplexor.out); - connect(adder.in_a, counter.out); - connect(adder.in_b, one.out); - - // Produce Verilog - generate_verilog(counter); -} -\end{scala} -} -\column{0.40\textwidth} -\begin{center} -\includegraphics[width=0.9\textwidth]{figs/simple-counter.pdf} -\end{center} -\end{columns} -\end{frame} - -\begin{frame}[fragile] -\frametitle{What if Chisel was a Scala Library?} -\begin{columns} -\column{0.50\textwidth} -{\lstset{basicstyle={\tiny\ttfamily}} -\begin{scala} -def main(args: Array[String]) = { - // Create Components - val reset = new Wire("reset"); - val counter = new Register("counter"); - val adder = new Adder(); - val multiplexor = new Multiplexor(); - val one = new UInt(1); - val zero = new UInt(0); - - // Connect Components - connect(multiplexor.choice, reset); - connect(multiplexor.in_a, zero.out); - connect(multiplexor.in_b, adder.out); - connect(counter.in, multiplexor.out); - connect(adder.in_a, counter.out); - connect(adder.in_b, one.out); - - // Produce Verilog - generate_verilog(counter); -} -\end{scala} -} -\column{0.40\textwidth} -\begin{center} -\includegraphics[width=0.9\textwidth]{figs/simple-counter.pdf} -\end{center} -\end{columns} -\begin{itemize} -\item using Scala to programmatically generate hardware -\item can use full power of Scala (loops, arrays, conditionals, ...) -\end{itemize} -\end{frame} - -\begin{frame}[fragile] -\frametitle{What if Chisel was a Scala Library?} -\begin{columns} -\column{0.50\textwidth} -{\lstset{basicstyle={\tiny\ttfamily}} -\begin{scala} -def main(args: Array[String]) = { - // Create Components - val reset = new Wire("reset"); - val counter = new Register("counter"); - val adder = new Adder(); - val multiplexor = new Multiplexor(); - val one = new UInt(1); - val zero = new UInt(0); - - // Connect Components - connect(multiplexor.choice, reset); - connect(multiplexor.in_a, zero.out); - connect(multiplexor.in_b, adder.out); - connect(counter.in, multiplexor.out); - connect(adder.in_a, counter.out); - connect(adder.in_b, one.out); - - // Produce Verilog - generate_verilog(counter); -} -\end{scala} -} -\column{0.40\textwidth} -\begin{center} -\includegraphics[width=0.9\textwidth]{figs/simple-counter.pdf} -\end{center} -\end{columns} -\begin{itemize} -\item but Scala is pretty Verbose, how can we do better? -\end{itemize} -\end{frame} - -\begin{frame}[fragile] -\frametitle{Functional Composition of Adder} -\begin{columns} -\column{0.4\textwidth} -{\lstset{basicstyle={\tiny\ttfamily}} -\begin{scala} -def main(args: Array[String]) = { - // Create Components - val reset = new Wire("reset"); - val counter = new Register("counter"); - val adder = new Adder(); - val multiplexor = new Multiplexor(); - val one = new UInt(1); - val zero = new UInt(0); - - // Connect Components - connect(multiplexor.choice, reset); - connect(multiplexor.in_a, zero.out); - connect(multiplexor.in_b, adder.out); - connect(counter.in, multiplexor.out); - connect(adder.in_a, counter.out); - connect(adder.in_b, one.out); - - // Produce Verilog - generate_verilog(counter); -} -\end{scala} -} - -\column{0.05\textwidth} -\begin{center} -$\Rightarrow$ -\end{center} -\column{0.4\textwidth} - -{\lstset{basicstyle={\tiny\ttfamily}} -\begin{scala} -def main(args: Array[String]) = { - // Create Components - val reset = new Wire("reset"); - val counter = new Register("counter"); - val multiplexor = new Multiplexor(); - val one = new UInt(1); - val zero = new UInt(0); - - // Connect Components - connect(multiplexor.choice, reset); - connect(multiplexor.in_a, zero.out); - connect(multiplexor.in_b, - make_adder(one.out, counter.out)); - connect(counter.in, multiplexor.out); - - // Produce Verilog - generate_verilog(counter); -} -\end{scala} -} -\end{columns} -\end{frame} - -\begin{frame}[fragile] -\frametitle{Functional Composition of Multiplexor} -\begin{columns} -\column{0.4\textwidth} -{\lstset{basicstyle={\tiny\ttfamily}} -\begin{scala} -def main(args: Array[String]) = { - // Create Components - val reset = new Wire("reset"); - val counter = new Register("counter"); - val multiplexor = new Multiplexor(); - val one = new UInt(1); - val zero = new UInt(0); - - // Connect Components - connect(multiplexor.choice, reset); - connect(multiplexor.in_a, zero.out); - connect(multiplexor.in_b, - make_adder(one.out, counter.out)); - connect(counter.in, multiplexor.out); - - // Produce Verilog - generate_verilog(counter); -} -\end{scala} -} -\column{0.05\textwidth} -\begin{center} -$\Rightarrow$ -\end{center} -\column{0.4\textwidth} -{\lstset{basicstyle={\tiny\ttfamily}} -\begin{scala} -def main(args: Array[String]) = { - // Create Components - val reset = new Wire("reset"); - val counter = new Register("counter"); - val one = new UInt(1); - val zero = new UInt(0); - - // Connect Components - connect(counter.in, - make_multiplexor(reset, - zero.out - make_adder(one.out, counter.out))); - - // Produce Verilog - generate_verilog(counter); -} -\end{scala} -} -\end{columns} -\end{frame} - -\begin{frame}[fragile] -\frametitle{Functional Composition of UInt Creation} -\begin{columns} -\column{0.4\textwidth} -{\lstset{basicstyle={\tiny\ttfamily}} -\begin{scala} -def main(args: Array[String]) = { - // Create Components - val reset = new Wire("reset"); - val counter = new Register("counter"); - val one = new UInt(1); - val zero = new UInt(0); - - // Connect Components - connect(counter.in, - make_multiplexor(reset, - zero.out - make_adder(one.out, counter.out))); - - // Produce Verilog - generate_verilog(counter); -} -\end{scala} -} -\column{0.05\textwidth} -\begin{center} -$\Rightarrow$ -\end{center} -\column{0.4\textwidth} -{\lstset{basicstyle={\tiny\ttfamily}} -\begin{scala} -def main(args: Array[String]) = { - // Create Components - val reset = new Wire("reset"); - val counter = new Register("counter"); - - // Connect Components - connect(counter.in, - make_multiplexor(reset, - UInt(0), - make_adder(UInt(1), counter.out))); - - // Produce Verilog - generate_verilog(counter); -} -\end{scala} -} -\end{columns} -\end{frame} - -\begin{frame}[fragile] -\frametitle{Overload Addition Operator} -\begin{columns} -\column{0.4\textwidth} -{\lstset{basicstyle={\tiny\ttfamily}} -\begin{scala} -def main(args: Array[String]) = { - // Create Components - val reset = new Wire("reset"); - val counter = new Register("counter"); - - // Connect Components - connect(counter.in, - make_multiplexor(reset, - UInt(0), - make_adder(UInt(1), counter.out))); - - // Produce Verilog - generate_verilog(counter); -} -\end{scala} -} -\column{0.05\textwidth} -\begin{center} -$\Rightarrow$ -\end{center} -\column{0.4\textwidth} -{\lstset{basicstyle={\tiny\ttfamily}} -\begin{scala} -def main(args: Array[String]) = { - // Create Components - val reset = new Wire("reset"); - val counter = new Register("counter"); - - // Connect Components - connect(counter.in, - make_multiplexor(reset, - UInt(0), - UInt(1) + counter.out)); - - // Produce Verilog - generate_verilog(counter); -} -\end{scala} -} -\end{columns} -\end{frame} - -\begin{frame}[fragile] -\frametitle{Introduce Connect Infix Operator} -\begin{columns} -\column{0.4\textwidth} -{\lstset{basicstyle={\tiny\ttfamily}} -\begin{scala} -def main(args: Array[String]) = { - // Create Components - val reset = new Wire("reset"); - val counter = new Register("counter"); - - // Connect Components - connect(counter.in, - make_multiplexor(reset, - UInt(0), - UInt(1) + counter.out)); - - // Produce Verilog - generate_verilog(counter); -} -\end{scala} -} -\column{0.05\textwidth} -\begin{center} -$\Rightarrow$ -\end{center} -\column{0.4\textwidth} -{\lstset{basicstyle={\tiny\ttfamily}} -\begin{scala} -def main(args: Array[String]) = { - // Create Components - val reset = new Wire("reset"); - val counter = new Register("counter"); - - // Connect Components - counter.in := - make_multiplexor(reset, - UInt(0), - UInt(1) + counter.out); - - // Produce Verilog - generate_verilog(counter); -} -\end{scala} -} -\end{columns} -\end{frame} - -\begin{frame}[fragile] -\frametitle{Automatically Create Multiplexors} -\begin{columns} -\column{0.4\textwidth} -{\lstset{basicstyle={\tiny\ttfamily}} -\begin{scala} -def main(args: Array[String]) = { - // Create Components - val reset = new Wire("reset"); - val counter = new Register("counter"); - - // Connect Components - counter.in := - make_multiplexor(reset, - UInt(0), - UInt(1) + counter.out); - - // Produce Verilog - generate_verilog(counter); -} -\end{scala} -} -\column{0.05\textwidth} -\begin{center} -$\Rightarrow$ -\end{center} -\column{0.4\textwidth} -{\lstset{basicstyle={\tiny\ttfamily}} -\begin{scala} -def main(args: Array[String]) = { - // Create Components - val reset = new Wire("reset"); - val counter = new Register("counter"); - - // Connect Components - when (reset) { - counter.in := UInt(0); - } .otherwise { - counter.in := UInt(1) + counter.out; - } - - // Produce Verilog - generate_verilog(counter); -} -\end{scala} -} -\end{columns} -\end{frame} - -\begin{frame}[fragile] -\frametitle{Grab Names of Wires Directly} -\begin{columns} -\column{0.4\textwidth} -{\lstset{basicstyle={\tiny\ttfamily}} -\begin{scala} -def main(args: Array[String]) = { - // Create Components - val reset = new Wire("reset"); - val counter = new Register("counter"); - - // Connect Components - when (reset) { - counter.in := UInt(0); - } .otherwise { - counter.in := UInt(1) + counter.out; - } - - // Produce Verilog - generate_verilog(counter); -} -\end{scala} -} -\column{0.05\textwidth} -\begin{center} -$\Rightarrow$ -\end{center} -\column{0.4\textwidth} -{\lstset{basicstyle={\tiny\ttfamily}} -\begin{scala} -def main(args: Array[String]) = { - // Create Components - val reset = new Wire(); - val counter = new Register(); - - // Connect Components - when (reset) { - counter.in := UInt(0); - } .otherwise { - counter.in := UInt(1) + counter.out; - } - - // Produce Verilog - generate_verilog(counter); -} -\end{scala} -} -\end{columns} -\end{frame} - -\begin{frame}[fragile] -\frametitle{Abstract Counter} -\begin{columns} -\column{0.4\textwidth} -{\lstset{basicstyle={\tiny\ttfamily}} -\begin{scala} -def main(args: Array[String]) = { - // Create Components - val reset = new Wire(); - val counter = new Register(); - - // Connect Components - when (reset) { - counter.in := UInt(0); - } .otherwise { - counter.in := UInt(1) + counter.out; - } - - // Produce Verilog - generate_verilog(counter); -} -\end{scala} -} -\column{0.05\textwidth} -\begin{center} -$\Rightarrow$ -\end{center} -\column{0.4\textwidth} -{\lstset{basicstyle={\tiny\ttfamily}} -\begin{scala} -def make_counter(reset: Boolean) = { - val counter = new Register(); - when (reset) { - counter.in := UInt(0); - } .otherwise { - counter.in := UInt(1) + counter.out; - } - counter -} - -def main(args: Array[String]) = { - // Create Components - val reset = new Wire(); - val counter = make_counter(reset); - - // Produce Verilog - generate_verilog(counter); -} -\end{scala} -} -\end{columns} -\end{frame} - -\begin{frame}[fragile] -\frametitle{Make Reset Implicit} -\begin{columns} -\column{0.4\textwidth} -{\lstset{basicstyle={\tiny\ttfamily}} -\begin{scala} -def make_counter(reset: Boolean) = { - val counter = new Register(); - when (reset) { - counter.in := UInt(0); - } .otherwise { - counter.in := UInt(1) + counter.out; - } - counter -} - -def main(args: Array[String]) = { - // Create Components - val reset = new Wire(); - val counter = make_counter(reset); - - // Produce Verilog - generate_verilog(counter); -} -\end{scala} -} -\column{0.05\textwidth} -\begin{center} -$\Rightarrow$ -\end{center} -\column{0.4\textwidth} -{\lstset{basicstyle={\tiny\ttfamily}} -\begin{scala} -def make_counter() = { - val counter = new Register(); - when (reset) { - counter.in := UInt(0); - } .otherwise { - counter.in := UInt(1) + counter.out; - } - counter -} - -def main(args: Array[String]) = { - // Create Components - val reset = new Wire(); - val counter = - withReset(reset) { - make_counter(reset); - } - // Produce Verilog - generate_verilog(counter); -} -\end{scala} -} -\end{columns} -\end{frame} - -\begin{frame}[fragile] -\frametitle{Looks ``Behavioral'' but ...} -\begin{columns} -\column{0.50\textwidth} -{\lstset{basicstyle={\tiny\ttfamily}} -\begin{scala} -def make_counter() = { - val counter = new Register(); - when (reset) { - counter.in := UInt(0); - } .otherwise { - counter.in := UInt(1) + counter.out; - } - counter -} - -def main(args: Array[String]) = { - // Create Components - val reset = new Wire(); - val counter = - withReset(reset) { - make_counter(reset); - } - // Produce Verilog - generate_verilog(counter); -} -\end{scala} -} -\column{0.40\textwidth} -\begin{center} -\includegraphics[width=0.9\textwidth]{figs/simple-counter.pdf} -\end{center} -\end{columns} -\begin{itemize} -\item every construct actually creates a concrete circuit -\item know cost of everything -\item layered and can choose level of abstraction -\end{itemize} -\end{frame} - -\begin{frame}[fragile]{Hosting Language Ingredients} -Crucial -\begin{itemize} -\item Type Inference -\item Infix Operator Overloading -\item Lightweight Closures -\item Dynamic Scoping -\item Introspection or Simple Macros -\item Functional Programming -\end{itemize} -\vspace{0.5cm} -Even Better with -\begin{itemize} -\item Object Orientation -\item Powerful Macros -\end{itemize} -\end{frame} - -\begin{frame}[fragile]{Synthesizable By Construction} -Well formed Chisel graphs are synthesizable. -\begin{columns} -\column{0.6\textwidth} -\begin{itemize} -\item Use small number of basic nodes -\begin{itemize} -\item simple semantics -\item easy to synthesize -\end{itemize} -\item During construction check that -\begin{itemize} -\item types, directions and widths match -\item there are no combinational loops -\end{itemize} -\end{itemize} -\column{0.3\textwidth} -\begin{center} -\includegraphics[width=0.9\textwidth]{figs/synthesizable.pdf} -\end{center} -\end{columns} -\vspace{1cm} -\begin{itemize} -\item {\color{red}If it passes these checks then it's synthesizable} -\end{itemize} -\end{frame} - -\begin{frame}[fragile]{Hardware Language Approaches} -% \begin{columns} -% \column{0.45\textwidth} -\begin{itemize} -\item {\color{magenta}behavioral} -- high level language compiled to verilog -\begin{itemize} -\item examples: C, Lime, CHP, Esterel, BlueSpec -\end{itemize} -\item {\color{orange}simulation} -- simulation language with synthesizable subset -\begin{itemize} -\item examples: Verilog, System Verilog, SystemC, myHDL -\end{itemize} -\item {\color{green}construction} -- programmatically construct circuits -\begin{itemize} -\item examples: Chisel, Lava -\end{itemize} -\end{itemize} -% \column{0.45\textwidth} -% \begin{center} -% \includegraphics[width=1.0\textwidth]{figs/hdls.pdf} -% \end{center} -% \end{columns} -\end{frame} - -\begin{frame}[fragile]{Hardware Language Comparisons} -\begin{small} -\begin{center} -\begin{tabular}{|r|c|c|c|} -\hline -{\bf name} & {\bf example} & {\bf pros} & {\bf cons} \\ -\hline -{\color{magenta}behavioral} & C-to-gates & high level & unpredictable \\ - & & & QoR \\ -\hline -{\color{orange}simulation} & Verilog & flexible & synthesizable? + \\ - & & & low abstraction \\ -\hline -{\color{green}construction} & Chisel & metaprogramming + & two levels + \\ - & & predictable QoR + & blemishes \\ - & & synthesizable QoR & \\ -\hline -\end{tabular} -\end{center} -\end{small} - -\begin{columns} -\column{0.4\textwidth} -\begin{center} -\includegraphics[width=0.8\textwidth]{figs/hdls.pdf} -\end{center} -\column{0.5\textwidth} -Chisel -\begin{itemize} -\item is {\bf not} Scala to Verilog -\item produces circuits that are synthesizable by construction -\item permits simulation by driving synthesized design -\end{itemize} -\end{columns} -\end{frame} diff --git a/doc/talks/microsoft/libs-to-langs.tex b/doc/talks/microsoft/libs-to-langs.tex deleted file mode 100644 index d60f462f..00000000 --- a/doc/talks/microsoft/libs-to-langs.tex +++ /dev/null @@ -1,31 +0,0 @@ -\documentclass[xcolor=pdflatex,dvipsnames,table]{beamer} -% \usepackage{pgfpages} -% \setbeamertemplate{note page}[plain] -% \setbeameroption{show notes on second screen=right} -\usepackage{epsfig,graphicx} -\usepackage{palatino} -\usepackage{fancybox} -\usepackage{relsize} -\usepackage[procnames]{listings} - -\input{../../style/scala.tex} -\input{../../style/talk.tex} - -\title{Chisel @ Microsoft} -\author{{\Large Jonathan Bachrach} + Huy Vo + Andrew Waterman + \\ -Sebastian Mirolo + John Wawrzynek + Krste Asanovi\'{c} + \\ -many more} -\date{\today} -\institute[UC Berkeley]{EECS UC Berkeley} - -\begin{document} - -\begin{frame} -\titlepage -\end{frame} -\addtocounter{framenumber}{-1} - -\input{libs-to-langs-guts.tex} - -\end{document} - diff --git a/doc/templates/base.html b/doc/templates/base.html deleted file mode 100644 index da2aeaeb..00000000 --- a/doc/templates/base.html +++ /dev/null @@ -1,99 +0,0 @@ - - - - - Chisel: Constructing Hardware in an Scala Embedded Language - - - - - - - - - - - - - - - - - - - - - - {% block localheader %}{% endblock %} - - - - - - -
- {% block content %}{% endblock %} -
-
-

Copyright © 2012-2014 The Regents of the University of - California ‐ All Rights Reserved

-
-
- - - - - - - - - - - - - - - - - {% block bodyscripts %} - {% endblock %} - - diff --git a/doc/templates/changelog_v2.2.19.html b/doc/templates/changelog_v2.2.19.html deleted file mode 100644 index 9a42afac..00000000 --- a/doc/templates/changelog_v2.2.19.html +++ /dev/null @@ -1,58 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
#263No Explicit Error When Writing To Your Inputs
#259C++ compilation speedups
#257initialize register that guards reset for assert checking
#251make assertions an option in driver
#248,249Update ShiftRegister to support a parameterized delay of 0.
#247Vec getWidth return zero
#176Re-enable testEqlBundle() and testEqlVec() after inserting explicit toBits comversion.
#124Zero width wire support
#86Queue is generating incorrect code; io.deq signals don't match io.enq signals.
#83log2Up(1) returns 1, instead of the correct answer of 0
#76Width inference takes hours, needs to quickly detect and throw error on un-inferable code
diff --git a/doc/templates/changelog_v2.2.20.html b/doc/templates/changelog_v2.2.20.html deleted file mode 100644 index 95b3e0c4..00000000 --- a/doc/templates/changelog_v2.2.20.html +++ /dev/null @@ -1,138 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
#331Fill(0, ...) fails with a java exception
#321Support poking large numbers - extension of #318
#319--parallelMakeJobs doesn't understand --targetDir
#300Generated cpp files lack Config substring (C++ backend)
#298Printf() doesn't since the switch to the new Tester
#295Bundle.calcElements calculates too many
#292Vcd varName,stripComponent code emits invalid variable IDs
#290Register with custom clock for a bundle generate wrong verilog
#286Width Inference Issue (width of operations on literals)
#209enerated Verilog repeated wire names (Verilog backend)
#196README Instructions don't let to a working HelloWorld
#168lit as port breaks chisel - flag it as a ChiselError
#153nameIt is way too eager, needs to chill out
#94printf being discarded during elaboration
Vtests: fix step
Deleted unused ModularCpp backend before more bitrot sets in.
Cosmetic/scalastyle fixes - no functional changes.
Add support for a constant pool (C++ backend)
Add hasSRAM & sramMaxSize for custom transforms
Fix naming problems when adding modules in custom transforms
Parametrization in custom transforms
Fix a binding problem
Fixes to --partitionIslands
Small changes in parameterization
Added "in" operator that can be used when defining constraints. Currently only works for List[Int], Range, and List[Chisel.IntEx]
Significant rewrite of the Bundle and Vec code
Significant changes to Verilog test code
diff --git a/doc/templates/changelog_v2.2.21.html b/doc/templates/changelog_v2.2.21.html deleted file mode 100644 index ce674823..00000000 --- a/doc/templates/changelog_v2.2.21.html +++ /dev/null @@ -1,57 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
#347Mishandling of UInts with MSB == 1
#346Signals only used as resets are trimmed
#335Null Pointer Exception on Floating Output.
#334Fix poking Negative Values Fails
#325ChiselUtil Reverse: Cpp optimization floods console with warnings
Eliminate NullPointerException if computeMemPorts is called before forceMatchingWidth.
Reorder Chisel standard passes for performance and flexibility.
Simplify and speed up width inference.
Placate various C++ compilers (C++ backend).
Minor changes to the dot backend for literal node names in debugging support (Dot backend).
Fixes to binding and register naming.
diff --git a/doc/templates/changelog_v2.2.22.html b/doc/templates/changelog_v2.2.22.html deleted file mode 100644 index 25e36247..00000000 --- a/doc/templates/changelog_v2.2.22.html +++ /dev/null @@ -1,77 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
#363Convert to C++ getline() semantics
#363Break out of read_eval_print_loop() if getline() returns an error.
#363Check File pointers are non-NULL before trying to fclose() them.
#359Weird compiler error for write-masked Mems in Verilog backend.
#358Muxes of type Bits now use SInt (previously, UInt).
#356: Tester.expect always results a PASS on data wider than 32 bits, even when signal value does not much the expected value.
#265Wrong verilog generated from When X{ when Y{ reg := }} otherwise { reg := }.
#191Randomize unconnected Verilog wires (as we do for the C++ backend).
Fix fromNode involving zero-width wires.
Fixes from HPCA workshop.
Minor fixes to the tutorial.
Use signal names from parent objects (implicit reset may have a different name).
Support Quartus' variant of `ifndef SYNTHESIS.
Work around bug causing illegal assignment of static const variable.
Don't accept negative UInt literals.
diff --git a/doc/templates/changelog_v2.2.24.html b/doc/templates/changelog_v2.2.24.html deleted file mode 100644 index 186c8c65..00000000 --- a/doc/templates/changelog_v2.2.24.html +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - -
Convert from unsupported sbt-scct to scoverage.
Fix bug in applying new parameters via bundle factory
Initial support for Scala 2.11
diff --git a/doc/templates/changelog_v2.2.25.html b/doc/templates/changelog_v2.2.25.html deleted file mode 100644 index 85f8385b..00000000 --- a/doc/templates/changelog_v2.2.25.html +++ /dev/null @@ -1,67 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Detect and issue an error for double Module() wrapping - #385
Fix Data width lost in Vec #384.
For test, use JUnitSuite over AssertionsForJUnit
In Verilog, fix bug for similar modules, some not emitted
Better Namespace conflict resolution for Verilog
Fix for multiply instantiated modules in Chisel result in redundant (functionally equivalent) module definitions in generated Verilog #374
In CPP, better detection of signals to randomize
Disallow comparisons between Nodes and non-Nodes
Include type of missing Parameter in error message
Address issue with width-inference of right-shift
Update emulator_{api,mod}.h to eliminate C++ compiler warnings.
Update README to reflect current build procedure.
diff --git a/doc/templates/documentation.html b/doc/templates/documentation.html deleted file mode 100644 index faf78517..00000000 --- a/doc/templates/documentation.html +++ /dev/null @@ -1,26 +0,0 @@ -{% extends "base.html" %} - -{% block content %} -
- -

- The rationale for Chisel and a gentle introduction can be found - in the DAC 2012 paper. -

- -

Chisel 2.2.x

-

- This is the accompanying documentation for the chisel 2.2.x jar files. -

-

- -
-{% endblock %} diff --git a/doc/templates/download.html b/doc/templates/download.html deleted file mode 100644 index 53d114d0..00000000 --- a/doc/templates/download.html +++ /dev/null @@ -1,95 +0,0 @@ -{% extends "base.html" %} - -{% block content %} -
- -

Chisel

-

-Chisel is made available under a modified BSD Licence. -The public repository is hosted on github. -

-

-See instructions for downloading and -installing the distribution on either Linux/x86 or Mac OS X. -

- -
-

-There is a VirtualBox Image with chisel, chisel-tutorial, riscv-sodor -and the riscv tools (isa sim, gcc, etc.) -

-

-First, install VirtualBox -and Vagrant. Then from a terminal: -

-
-$ vagrant box add chisel-riscv https://chisel.eecs.berkeley.edu/chisel-riscv.box
-$ vagrant init chisel-riscv
-$ diff -u prev Vagrantfile
-- # config.vm.network :forwarded_port, guest: 80, host: 8080
-+  config.vm.network :forwarded_port, guest: 8080, host: 8888
-$ vagrant up
-
-

-You can then browse, pull latest changes and re-build the projects through -the jenkins interface at http://localhost:8888/ -

-

-If you want to do work on the command line (run the chisel tutorial for example) -

-
-host$ vagrant ssh
-guest$ export PATH=${PATH}:/var/lib/jenkins/local/bin
-guest$ cd /var/lib/jenkins/jobs/chisel-tutorial/workspace
-# follow instructions on https://github.com/ucb-bar/chisel-tutorial
-guest$ cd examples
-guest$ make
-
- -
-

-There is a public Amazon EC2 AMI with chisel, chisel-tutorial and riscv-sodor -installed and ready to go. -

-
-id:    ami-345ec104
-login: ubuntu
-
- -

Third-party Chisel Integrated Circuits

- - - - - - - - - - - - - - - - - - - - - - - - - - -
tutorialsExamples of Basic Logic Circuits(Jonathan Bachrach)
riscv-sodorEducational microarchitectures for risc-v isa(Christopher Celio)
PatmosTime-predictable VLIW processor(T-CREST)
comphdlChisel Blink, Counter and FSM Examples(Martin Schoeberl)
OpenSoC FabricA Parameterizable NoC(LBL Computer Architecture Lab)
-

-

-To Add your project to the list, just advertise about it on the -Chisel mailing list! -

-
-{% endblock %} diff --git a/doc/templates/faq.html b/doc/templates/faq.html deleted file mode 100644 index 890ac06b..00000000 --- a/doc/templates/faq.html +++ /dev/null @@ -1,78 +0,0 @@ -{% extends "base.html" %} - -{% block content %} -
- - -

Does Chisel convert Scala to Verilog?

-

No Chisel is a hardware construction language for writing Scala programs - that generate hardware

- -

What's the overhead for Chisel?

-

None. Chisel allows designers to write circuits structurally as they do - in Verilog with no extra overhead.

- -

Why do I need SBT to compile and execute my Chisel code?

-

- Technically you don't. -

-

- SBT is - a builder for scala which is a cross between apt-get and make. - It downloads all the prerequisites (as apt-get would do) then - builds your chisel code (as make would do). The downloaded files - will be cached in ~/.sbt and ~/.ivy2. -

-

- Chisel is packaged as a regular JAR file published on the sonatype - repo. If you have your own build system, the bare minimum you need - is to download the latest chisel jar file - and execute the following commands (based on the example in the - README file). -

-
-# Compile and execute your Chisel code
-$ scalac-2.10 -cp chisel_2.10-2.2.25.jar Hello.scala
-$ scala-2.10 -cp chisel_2.10-2.2.25.jar:. hello
-
-# Compile and run the generated simulation
-$ g++ -std=c++11 -o HelloModule HelloModule.cpp HelloModule-emulator.cpp
-$ ./HelloModule 1
-  
- -

How can I make a vector of modules?

-
-Vec.fill{ Module(new CPU()).io }
-  
- -

How do I get in touch with the Chisel community?

-

-There is a Chisel users Google group. -You can also search for Chisel on Stack Overflow. -To report bugs on the Chisel code itself, -please open an issue on github. -

- -

How stable is Chisel?

-

- Every night, we build all of Chisel and the projects listed - in download with the help of - a jenkins buildbot. - Follow the unit tests trends here. -

- -

How did you get to work on such a cool project?

-

Chisel has been partially funded by

-
    -
  • Project Isis: DoE Award DE-SC0003624.
  • -
  • Par Lab: Microsoft (Award #024263) and Intel (Award #024894) funding - and by matching funding by U.C. Discovery (Award #DIG07-10227). - Additional support came from Par Lab affiliates Nokia, NVIDIA, Oracle, - and Samsung.
  • -
  • ASPIRE: DARPA PERFECT program, Award HR0011-12-2-0016.
  • -
-

Thank you for your support!

-
-{% endblock %} diff --git a/doc/templates/index.html b/doc/templates/index.html deleted file mode 100644 index ce2ec2c5..00000000 --- a/doc/templates/index.html +++ /dev/null @@ -1,252 +0,0 @@ -{% extends "base.html" %} - -{% block content %} - -
-

Chisel

-

Constructing Hardware in a Scala Embedded Language

- Get Started - View on GitHub -
- -
-
-
- -

-Chisel is an open-source hardware construction language -developed at UC Berkeley that supports -advanced hardware design using highly parameterized generators -and layered domain-specific hardware languages. -

-
-
-
    -
  • Hardware construction language (not C to Gates)
  • -
  • Embedded in the Scala programming language
  • -
  • Algebraic construction and wiring
  • -
  • Abstract data types and interfaces
  • -
  • Bulk connections
  • -
  • Hierarchical + object oriented + functional construction
  • -
  • Highly parameterizable using metaprogramming in Scala
  • -
  • Supports layering of domain specific languages
  • -
-
-
-
    -
  • Sizeable standard library including floating-point units
  • -
  • Multiple clock domains
  • -
  • Generates high-speed C++-based cycle-accurate software simulator
  • -
  • Generates low-level Verilog designed to pass on to standard ASIC or FPGA tools
  • -
  • Open source on github with modified BSD license
  • -
  • Complete set of docs
  • -
  • Growing community of adopters
  • -
-
-
-
-
-
-
- - -
-
-
- -
-
-
- -

-You can find code examples on the Berkeley EECS Berkeley Architecture Research -(BAR) github page. -Chisel-tutorial is -a set of sample circuits with supporting -documentation. -Sodor is a set of -educational processors written in Chisel by Christopher -Celio, a PhD student at UC Berkeley. Sodor implements the RISC-V -Instruction Set Architecture designed in the BAR group and described on -riscv.org. -

-
- -
-
-
-import Chisel._
-
-class GCD extends Module {
-  val io = new Bundle {
-    val a  = UInt(INPUT,  16)
-    val b  = UInt(INPUT,  16)
-    val e  = Bool(INPUT)
-    val z  = UInt(OUTPUT, 16)
-    val v  = Bool(OUTPUT)
-  }
-  val x  = Reg(UInt())
-  val y  = Reg(UInt())
-  when   (x > y) { x := x - y }
-  unless (x > y) { y := y - x }
-  when (io.e) { x := io.a; y := io.b }
-  io.z := x
-  io.v := y === UInt(0)
-}
-
-object Example {
-  def main(args: Array[String]): Unit = {
-    chiselMain(args, () => Module(new GCD()))
-  }
-}
-
-                              
-
-
-
import Chisel._  // importing the Chisel library.
-
-/// Creating a Module that computes the maximum of N values
-//
-//  This generator shows how it is possible to do functional construction
-//  of circuits.
-
-class MaxN(n: Int, w: Int /* parameterized input */) extends Module {
-
- private def Max2(x: UInt, y: UInt) = Mux(x > y, x, y)
-
- val io = new Bundle {
-   val in  = Vec.fill(n){ UInt(INPUT, w) }
-   val out = UInt(OUTPUT, w)
- }
- io.out := io.in.reduceLeft(Max2)
-}
-
-object MaxNExample {
- // Main Entry Point of the circuit generator
- def main(args: Array[String]): Unit = {
-   // instantiate with 4 ports. Each port is 8 bits wide.
-   chiselMain(args, () => Module(new MaxN(4, 8)))
- }
-}
-
-
-
-
/** Four-by-four multiply using a look-up table.
-*/
-class Mul extends Module {
-  val io = new Bundle {
-    val x   = UInt(INPUT,  4)
-    val y   = UInt(INPUT,  4)
-    val z   = UInt(OUTPUT, 8)
-  }
-  val muls = new ArrayBuffer[UInt]()
-
-  for (i <- 0 until 16)
-    for (j <- 0 until 16)
-      muls += UInt(i * j, width = 8)
-  val tbl = Vec(muls)
-  io.z := tbl((io.x << UInt(4)) | io.y)
-}
-
-
-
-
/** A n-bit adder with carry in and carry out
-  */
-class Adder(val n:Int) extends Module {
-  val io = new Bundle {
-    val A    = UInt(INPUT, n)
-    val B    = UInt(INPUT, n)
-    val Cin  = UInt(INPUT, 1)
-    val Sum  = UInt(OUTPUT, n)
-    val Cout = UInt(OUTPUT, 1)
-  }
-  //create a vector of FullAdders
-  val FAs   = Vec.fill(n){ Module(new FullAdder()).io }
-  val carry = Vec.fill(n+1){ UInt(width = 1) }
-  val sum   = Vec.fill(n){ Bool() }
-
-  //first carry is the top level carry in
-  carry(0) := io.Cin
-
-  //wire up the ports of the full adders
-  for (i <- 0 until n) {
-    FAs(i).a := io.A(i)
-    FAs(i).b := io.B(i)
-    FAs(i).cin := carry(i)
-    carry(i+1) := FAs(i).cout
-    sum(i) := FAs(i).sum.toBool()
-  }
-  io.Sum := sum.toBits().toUInt()
-  io.Cout := carry(n)
-}
-
-
-
-
-
-
-
-
-
-
- -

-Getting started with Chisel is easy. Boilerplate verilog often directly maps -to Chisel one-liners. Everything you learn to write Scala code is directly -applicable. Follow the Chisel Tutorial. -When you have a question that the documentation doesn't answer, check -Stack Overflow -or ask on the Chisel users mailing list. -

-
-
- -

-Chisel is released as a JAR file through the official Maven repo. -Just add this line to your build.sbt -

-
-libraryDependencies += "edu.berkeley.cs" %% "chisel" % "latest.release"
-            
-

-If you are new to Scala -and have no idea what that means, follow the step-by-step -in Chisel's README.md. -

-
-
- - -

-Also see: slides from the second Chisel -bootcamp. -

-
- -
-
-{% endblock %} diff --git a/doc/templates/releasenotes_v2.2.19.html b/doc/templates/releasenotes_v2.2.19.html deleted file mode 100644 index 659dd069..00000000 --- a/doc/templates/releasenotes_v2.2.19.html +++ /dev/null @@ -1,97 +0,0 @@ -

This release of Chisel adds support for: -

    -
  • design parameters
  • -
  • 0-width wires
  • -
  • C++ backend compilation performance
  • -
-

-

-We are introducing experimental support to Chisel to allow module -designers to specify design parameters that should be configured on -the fly as the design is elaborated. We provide support for looking up -parameter values within Chisel Modules and Bundles, as well as scoping -where certain parameter values are defined and customizing how -dependent parameters are calculated. Users can define custom -ChiselConfiguration classes which override default parameter values, -and they can select which configuration to use at runtime via the -Chisel command line. We allow constraints to be placed on parameter -values and provide hooks for automated design space exploration of -parameter spaces. A detailed guide to these experimental features is -available at in the Chisel repo at chisel/doc/parameters/parameters.pdf -

-

-0-width wire support attempts to eliminate 0-width wires from the -design by either replacing them with the appropriate identity element, -or by removing them entirely. This feature is highly experimental and -is controlled by the --W0W command line option to Chisel. -

-

-The C++ backend changes attempt to improve compilation performance by -reducing the size of the functions generated by the C++ backend. This -feature is highly experimental and is controlled by a number of Chisel -command line options. The following options are either treated as -simple binary feature enablers, or take an argument -specifying the value of some optional feature. -

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
--allocateOnlyNeededShadowRegisters(C++ backend) Attempt to allocate only those shadow registers - actually required. This reduces the size of the main C++ design - object (especially when --shadowRegisterInObject is enabled), which - in turn reduces compilation time. It should have no execution-time - performance impact.
--compileInitializationUnoptimized(C++ backend) Compile initialization code at -O0, rarely used code - at -O1.
--isVCDinline(C++ backend) Generate VCD dump code without goto branches. Allows - compiling smaller VCD dump functions, reducing C++ compile - times. This will have some impact on execution-time performance.
--lineLimitFunctions (Integer)(C++ backend) Limit the number of lines in a C++ function/method - before splitting it up into multiple functions to reduce C++ compile - times. The value specifies a loose upper limit on the - number of lines output to a single function before that function is - split up into smaller functions. This involves a trade-off between - compile-time performance and execution-time performance. Smaller - functions yield faster compile times, but result in slower execution - since instead of calling a single function, calls to multiple - functions are generated. Reasonable values for this argument would - be in the range from 256 to 2048.
--minimumLinesPerFile (Integer)(C++ backend) Limit the minimum number of lines per file so as not - to produce trivial files. This works in conjunction with - --lineLimitFunctions to break up a massive single file into - multiple smaller (but not too small) files. Reasonable values for - this argument would be in the range of 1024 to 32768.
--parallelMakeJobs (Integer)(C++ backend) Generate a Makefile to compile multiple C++ files in - parallel. The argument specifies the amount of parallelism - (the argument to the -j option to make). A value of -1 indicates - that no value will be passed with the -j argument to make, which in - turn should inform make not to limit the number of jobs that can run - simultaneously.
--partitionIslands(C++, dot backends) Partition the graph into islands of - combinatorial logic that may be compiled and executed in parallel.
--shadowRegisterInObject(C++ backend) Allocate shadow registers in the global emulation - object (as opposed to the local clock procedures). This is - automatically enabled when --lineLimitFunctions is in effect.
diff --git a/doc/templates/releasenotes_v2.2.20.html b/doc/templates/releasenotes_v2.2.20.html deleted file mode 100644 index 4e7e99b5..00000000 --- a/doc/templates/releasenotes_v2.2.20.html +++ /dev/null @@ -1,24 +0,0 @@ -

This release of Chisel is largely a maintenance release. -See the associated Changelog for issues resolved with this release. -

-

-There were significant changes to the Bundle and Vec code: -

    -
  1. Make the flatten methods generate correct element names
  2. -
  3. Internal data structures -
      -
    1. Bundle: LinkedHashMap(name & io pairs)
    2. -
    3. Vec: Vector(now Vec is immutable)
    4. -
    -
  4. -
  5. Remove legacy code
  6. -
-

-

-There were significant changes to Verilog testing: -

    -
  1. Use vpi routines for verilog tests
  2. -
  3. Fix timing and compile errors of verilog tests
  4. -
  5. Generate the same harness regardless of the --test option
  6. -
- diff --git a/doc/templates/releasenotes_v2.2.21.html b/doc/templates/releasenotes_v2.2.21.html deleted file mode 100644 index 80832c85..00000000 --- a/doc/templates/releasenotes_v2.2.21.html +++ /dev/null @@ -1,3 +0,0 @@ -

This release of Chisel is largely a maintenance release. -See the associated Changelog for issues resolved with this release. -

diff --git a/doc/templates/releasenotes_v2.2.22.html b/doc/templates/releasenotes_v2.2.22.html deleted file mode 100644 index aaea69da..00000000 --- a/doc/templates/releasenotes_v2.2.22.html +++ /dev/null @@ -1,10 +0,0 @@ -

This release of Chisel is largely a maintenance release. -See the associated Changelog for issues resolved with this release. -

-

Muxes of type Bits now use SInt (previously, UInt) This fixes issue -#358 and constitutes behavioral change. To facilitate any necessary -porting, a warning is now issued when a Mux of type Bits is -created. This warning will likely be turned off or removed in future -versions. Justification behind using SInt over UInt is so that -corresponding sign extension is better aligned to C semantics. -

diff --git a/doc/templates/releasenotes_v2.2.24.html b/doc/templates/releasenotes_v2.2.24.html deleted file mode 100644 index e5cb19b1..00000000 --- a/doc/templates/releasenotes_v2.2.24.html +++ /dev/null @@ -1,33 +0,0 @@ -

-This release of Chisel is largely a maintenance release. -See the associated Changelog for issues resolved with this release. -

-

-This release provides initial support for Scala 2.11. - -In order to use the 2.11 version of the code, change the scalaVersion -definition in your build.sbt (or build.scala) file from -


-scalaVersion := "2.10.x"
-
-to: -

-scalaVersion := "2.11.4"
-
-

-

-NOTE: Expect three warnings when compiling under Scala 2.11: -

-

-[warn] src/main/scala/Parameters.scala:272: abstract type T in type pattern Chisel.Ex[T] is unchecked since it is eliminated by erasure
-[warn]           case ex:Ex[T] => _bindLet[T](pname,ex)
-[warn]                   ^
-[warn] src/main/scala/Parameters.scala:271: abstract type T in type pattern Chisel.Knob[T] is unchecked since it is eliminated by erasure
-[warn]           case k:Knob[T] => ExVar[T](_VarKnob[T](k.name))
-[warn]                  ^
-[warn] src/main/scala/Parameters.scala:272: abstract type T in type pattern Chisel.Ex[T] is unchecked since it is eliminated by erasure
-[warn]           case ex:Ex[T] => _bindLet[T](pname,ex)
-[warn]                   ^
-model contains 286 documentable templates
-[warn] three warnings found
-
diff --git a/doc/templates/releasenotes_v2.2.25.html b/doc/templates/releasenotes_v2.2.25.html deleted file mode 100644 index 80832c85..00000000 --- a/doc/templates/releasenotes_v2.2.25.html +++ /dev/null @@ -1,3 +0,0 @@ -

This release of Chisel is largely a maintenance release. -See the associated Changelog for issues resolved with this release. -

diff --git a/doc/templates/releases.html b/doc/templates/releases.html deleted file mode 100644 index e8ad3373..00000000 --- a/doc/templates/releases.html +++ /dev/null @@ -1,59 +0,0 @@ -{% extends "base.html" %} - -{% block content %} -
- - -

Chisel 2.2.x

-

-

ReleaseNotes for Chisel @VERSION@ @DATE@

- {% include "releasenotes_@VERSION@.html" %} -

-

-

ChangeLog for Chisel @VERSION@ @DATE@

- {% include "changelog_@VERSION@.html" %} -

-

-

ReleaseNotes for Chisel v2.2.24 2015-03-09

- {% include "releasenotes_v2.2.24.html" %} -

-

-

ChangeLog for Chisel v2.2.24 2015-03-09

- {% include "changelog_v2.2.24.html" %} -

-

-

ReleaseNotes for Chisel v2.2.22 2015-02-26

- {% include "releasenotes_v2.2.22.html" %} -

-

-

ChangeLog for Chisel v2.2.22 2015-02-26

- {% include "changelog_v2.2.22.html" %} -

-

-

ReleaseNotes for Chisel v2.2.21 2014-12-12

- {% include "releasenotes_v2.2.21.html" %} -

-

-

ChangeLog for Chisel v2.2.21 2014-12-12

- {% include "changelog_v2.2.21.html" %} -

-

-

ReleaseNotes for Chisel v2.2.20 2014-11-20

- {% include "releasenotes_v2.2.20.html" %} -

-

-

ChangeLog for Chisel v2.2.20 2014-11-20

- {% include "changelog_v2.2.20.html" %} -

-

-

ReleaseNotes for Chisel v2.2.19 2014-10-03

- {% include "releasenotes_v2.2.19.html" %} -

-

-

ChangeLog for Chisel v2.2.19 2014-10-03

- {% include "changelog_v2.2.19.html" %} -

-
-{% endblock %} diff --git a/doc/templates/unit_tests_trends.html b/doc/templates/unit_tests_trends.html deleted file mode 100644 index 062a610b..00000000 --- a/doc/templates/unit_tests_trends.html +++ /dev/null @@ -1,118 +0,0 @@ -{% extends "base.html" %} - -{% block localheader %} - -{% endblock %} - -{% block content %} -
-

Build Metrics for Chisel

-

code repository at http://github.com/ucb-bar/chisel

-

Static Style Checker

-
-$ sbt scalastyle
-
-
-  
-  
-
-

Runtime Analysis

-
-$ sbt scct:test
-
-
-  
-  
-
-{% endblock %} - -{% block bodyscripts %} - - - -{% endblock %} - diff --git a/doc/tutorial/figs/DUT.graffle b/doc/tutorial/figs/DUT.graffle deleted file mode 100644 index 920a7d0b..00000000 --- a/doc/tutorial/figs/DUT.graffle +++ /dev/null @@ -1,469 +0,0 @@ - - - - - ActiveLayerIndex - 0 - ApplicationVersion - - com.omnigroup.OmniGrafflePro - 139.7.0.167456 - - AutoAdjust - - BackgroundGraphic - - Bounds - {{0, 0}, {756, 553}} - Class - SolidGraphic - ID - 2 - Style - - shadow - - Draws - NO - - stroke - - Draws - NO - - - - BaseZoom - 0 - CanvasOrigin - {0, 0} - ColumnAlign - 1 - ColumnSpacing - 36 - CreationDate - 2012-06-05 23:04:25 -0700 - Creator - Jonathan Bachrach - DisplayScale - 1 0/72 in = 1.0000 in - FileType - auto - GraphDocumentVersion - 8 - GraphicsList - - - Bounds - {{240, 231.5}, {96, 41}} - Class - ShapedGraphic - FitText - YES - Flow - Resize - FontInfo - - Color - - w - 0 - - Font - Helvetica - Size - 26 - - ID - 10 - Line - - ID - 6 - Position - 0.5 - RotationType - 0 - - Shape - Rectangle - Style - - shadow - - Draws - NO - - stroke - - Draws - NO - - - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1038\cocoasubrtf360 -{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural - -\f0\fs52 \cf0 outputs} - - Wrap - NO - - - Bounds - {{248, 159.5}, {80, 41}} - Class - ShapedGraphic - FitText - YES - Flow - Resize - FontInfo - - Color - - w - 0 - - Font - Helvetica - Size - 26 - - ID - 9 - Line - - ID - 5 - Position - 0.5 - RotationType - 0 - - Shape - Rectangle - Style - - shadow - - Draws - NO - - stroke - - Draws - NO - - - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1038\cocoasubrtf360 -{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural - -\f0\fs52 \cf0 inputs} - - Wrap - NO - - - Class - LineGraphic - FontInfo - - Font - Helvetica - Size - 25 - - ID - 6 - Points - - {216, 252} - {360, 252} - - Style - - stroke - - HeadArrow - 0 - Legacy - - TailArrow - StickArrow - Width - 2 - - - - - Class - LineGraphic - FontInfo - - Font - Helvetica - Size - 25 - - ID - 5 - Points - - {216, 180} - {360, 180} - - Style - - stroke - - HeadArrow - StickArrow - Legacy - - TailArrow - 0 - Width - 2 - - - - - Bounds - {{360, 144}, {144, 144}} - Class - ShapedGraphic - FontInfo - - Font - Helvetica - Size - 25 - - ID - 4 - Shape - Rectangle - Style - - stroke - - Width - 2 - - - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1038\cocoasubrtf360 -{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural - -\f0\fs52 \cf0 DUT} - - - - Bounds - {{72, 144}, {144, 144}} - Class - ShapedGraphic - FontInfo - - Font - Helvetica - Size - 25 - - ID - 3 - Shape - Rectangle - Style - - stroke - - Width - 2 - - - Text - - Text - {\rtf1\ansi\ansicpg1252\cocoartf1038\cocoasubrtf360 -{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural - -\f0\fs52 \cf0 Chisel} - - - - GridInfo - - ShowsGrid - YES - SnapsToGrid - YES - - GuidesLocked - NO - GuidesVisible - YES - HPages - 1 - ImageCounter - 1 - KeepToScale - - Layers - - - Lock - NO - Name - Layer 1 - Print - YES - View - YES - - - LayoutInfo - - Animate - NO - circoMinDist - 18 - circoSeparation - 0.0 - layoutEngine - dot - neatoSeparation - 0.0 - twopiSeparation - 0.0 - - LinksVisible - NO - MagnetsVisible - NO - MasterSheets - - ModificationDate - 2012-06-07 22:13:36 -0700 - Modifier - Jonathan Bachrach - NotesVisible - NO - Orientation - 2 - OriginVisible - NO - PageBreaks - YES - PrintInfo - - NSBottomMargin - - float - 41 - - NSLeftMargin - - float - 18 - - NSOrientation - - int - 1 - - NSPaperName - - string - US Letter - - NSPaperSize - - size - {792, 612} - - NSRightMargin - - float - 18 - - NSTopMargin - - float - 18 - - - PrintOnePage - - ReadOnly - NO - RowAlign - 1 - RowSpacing - 36 - SheetTitle - Canvas 1 - SmartAlignmentGuidesActive - YES - SmartDistanceGuidesActive - YES - UniqueID - 1 - UseEntirePage - - VPages - 1 - WindowInfo - - CurrentSheet - 0 - ExpandedCanvases - - - name - Canvas 1 - - - ListView - - OutlineWidth - 142 - RightSidebar - - ShowRuler - - Sidebar - - SidebarWidth - 120 - VisibleRegion - {{0, -82}, {575, 718}} - Zoom - 1 - ZoomValues - - - Canvas 1 - 1 - 1 - - - - - diff --git a/doc/tutorial/figs/DUT.pdf b/doc/tutorial/figs/DUT.pdf deleted file mode 100644 index d61de1d8..00000000 Binary files a/doc/tutorial/figs/DUT.pdf and /dev/null differ diff --git a/doc/tutorial/figs/condupdates.graffle b/doc/tutorial/figs/condupdates.graffle deleted file mode 100644 index 71d93992..00000000 --- a/doc/tutorial/figs/condupdates.graffle +++ /dev/null @@ -1,2822 +0,0 @@ - - - - - ActiveLayerIndex - 0 - ApplicationVersion - - com.omnigroup.OmniGrafflePro - 138.33.0.157554 - - AutoAdjust - - BackgroundGraphic - - Bounds - {{0, 0}, {576, 733}} - Class - SolidGraphic - ID - 2 - Style - - shadow - - Draws - NO - - stroke - - Draws - NO - - - - CanvasOrigin - {0, 0} - ColumnAlign - 1 - ColumnSpacing - 36 - CreationDate - 2011-09-12 23:56:23 -0700 - Creator - Krste Asanovic - DisplayScale - 1 0/72 in = 1.0000 in - GraphDocumentVersion - 8 - GraphicsList - - - Bounds - {{302, 209}, {100, 22}} - Class - ShapedGraphic - FitText - YES - Flow - Resize - FontInfo - - Font - CourierNewPS-BoldMT - Size - 18 - - ID - 155 - Shape - Rectangle - Style - - fill - - Draws - NO - - shadow - - Draws - NO - - stroke - - Draws - NO - - - Text - - Pad - 0 - Text - {\rtf1\ansi\ansicpg1252\cocoartf1038\cocoasubrtf360 -{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural - -\f0\fs36 \cf0 Initial values} - VerticalPad - 0 - - Wrap - NO - - - Bounds - {{394, 237}, {11, 21}} - Class - ShapedGraphic - FitText - YES - Flow - Resize - FontInfo - - Font - CourierNewPS-BoldMT - Size - 18 - - ID - 296 - Shape - Rectangle - Style - - fill - - Draws - NO - - shadow - - Draws - NO - - stroke - - Draws - NO - - - Text - - Pad - 0 - Text - {\rtf1\ansi\ansicpg1252\cocoartf1038\cocoasubrtf360 -{\fonttbl\f0\fmodern\fcharset0 CourierNewPS-BoldMT;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural - -\f0\b\fs36 \cf0 0} - VerticalPad - 0 - - VFlip - YES - Wrap - NO - - - Bounds - {{313, 237}, {11, 21}} - Class - ShapedGraphic - FitText - YES - Flow - Resize - FontInfo - - Font - CourierNewPS-BoldMT - Size - 18 - - ID - 295 - Shape - Rectangle - Style - - fill - - Draws - NO - - shadow - - Draws - NO - - stroke - - Draws - NO - - - Text - - Pad - 0 - Text - {\rtf1\ansi\ansicpg1252\cocoartf1038\cocoasubrtf360 -{\fonttbl\f0\fmodern\fcharset0 CourierNewPS-BoldMT;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural - -\f0\b\fs36 \cf0 0} - VerticalPad - 0 - - VFlip - YES - Wrap - NO - - - Class - LineGraphic - FontInfo - - Font - CourierNewPS-BoldMT - Size - 18 - - ID - 294 - Points - - {432, 318} - {432, 369} - {396, 369} - - Style - - stroke - - HeadArrow - 0 - TailArrow - 0 - Width - 2 - - - Tail - - ID - 290 - Info - 1 - - - - Class - LineGraphic - FontInfo - - Font - CourierNewPS-BoldMT - Size - 18 - - Head - - ID - 274 - Info - 1 - - ID - 293 - Points - - {324, 381} - {324, 387} - {315, 387} - - Style - - stroke - - HeadArrow - 0 - TailArrow - 0 - Width - 2 - - - Tail - - ID - 288 - Info - 1 - - - - Class - Group - Graphics - - - Bounds - {{387, 286}, {11, 21}} - Class - ShapedGraphic - FitText - YES - Flow - Resize - FontInfo - - Font - CourierNewPS-BoldMT - Size - 18 - - ID - 278 - Shape - Rectangle - Style - - fill - - Draws - NO - - shadow - - Draws - NO - - stroke - - Draws - NO - - - Text - - Pad - 0 - Text - {\rtf1\ansi\ansicpg1252\cocoartf1038\cocoasubrtf360 -{\fonttbl\f0\fmodern\fcharset0 CourierNewPS-BoldMT;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural - -\f0\b\fs36 \cf0 f} - VerticalPad - 0 - - VFlip - YES - Wrap - NO - - - Bounds - {{459, 286}, {11, 21}} - Class - ShapedGraphic - FitText - YES - Flow - Resize - FontInfo - - Font - CourierNewPS-BoldMT - Size - 18 - - ID - 279 - Shape - Rectangle - Style - - fill - - Draws - NO - - shadow - - Draws - NO - - stroke - - Draws - NO - - - Text - - Pad - 0 - Text - {\rtf1\ansi\ansicpg1252\cocoartf1038\cocoasubrtf360 -{\fonttbl\f0\fmodern\fcharset0 CourierNewPS-BoldMT;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural - -\f0\b\fs36 \cf0 t} - VerticalPad - 0 - - VFlip - YES - Wrap - NO - - - Class - LineGraphic - FontInfo - - Font - CourierNewPS-BoldMT - Size - 18 - - ID - 280 - Points - - {468, 282} - {468, 255} - - Style - - stroke - - HeadArrow - 0 - TailArrow - 0 - Width - 2 - - - - - Class - LineGraphic - FontInfo - - Font - CourierNewPS-BoldMT - Size - 18 - - ID - 281 - Points - - {396, 282} - {396, 261} - - Style - - stroke - - HeadArrow - 0 - TailArrow - 0 - Width - 2 - - - - - Bounds - {{462, 234}, {22, 21}} - Class - ShapedGraphic - FitText - YES - Flow - Resize - FontInfo - - Font - CourierNewPS-BoldMT - Size - 18 - - ID - 282 - Shape - Rectangle - Style - - fill - - Draws - NO - - shadow - - Draws - NO - - stroke - - Draws - NO - - - Text - - Pad - 0 - Text - {\rtf1\ansi\ansicpg1252\cocoartf1038\cocoasubrtf360 -{\fonttbl\f0\fmodern\fcharset0 CourierNewPS-BoldMT;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural - -\f0\b\fs36 \cf0 e1} - VerticalPad - 0 - - VFlip - YES - Wrap - NO - - - Bounds - {{257, 286}, {22, 21}} - Class - ShapedGraphic - FitText - YES - Flow - Resize - FontInfo - - Font - CourierNewPS-BoldMT - Size - 18 - - ID - 283 - Shape - Rectangle - Style - - fill - - Draws - NO - - shadow - - Draws - NO - - stroke - - Draws - NO - - - Text - - Pad - 0 - Text - {\rtf1\ansi\ansicpg1252\cocoartf1038\cocoasubrtf360 -{\fonttbl\f0\fmodern\fcharset0 CourierNewPS-BoldMT;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural - -\f0\b\fs36 \cf0 c1} - VerticalPad - 0 - - VFlip - YES - Wrap - NO - - - Bounds - {{330.639, 295.502}, {8.99658, 8.99658}} - Class - ShapedGraphic - FontInfo - - Font - CourierNewPS-BoldMT - Size - 18 - - ID - 284 - Line - - ID - 292 - Position - 0.4762515127658844 - RotationType - 0 - - Shape - Circle - Style - - fill - - Color - - b - 0 - g - 0 - r - 0 - - - shadow - - Draws - NO - - stroke - - Width - 2 - - - - - Class - LineGraphic - FontInfo - - Font - CourierNewPS-BoldMT - Size - 18 - - ID - 285 - Points - - {432, 380} - {432, 381} - - Style - - stroke - - HeadArrow - 0 - HeadScale - 1.5000001192092896 - LineType - 1 - TailArrow - 0 - Width - 2 - - - - - Class - Group - Graphics - - - AllowLabelDrop - - Class - LineGraphic - FontInfo - - Font - CourierNewPS-BoldMT - Size - 18 - - Head - - ID - 289 - - ID - 287 - Points - - {333, 300} - {333.154, 320.917} - - Style - - stroke - - Cap - 0 - HeadArrow - 0 - Join - 0 - LineType - 1 - TailArrow - 0 - Width - 2 - - - - - AllowLabelDrop - - Class - LineGraphic - FontInfo - - Font - CourierNewPS-BoldMT - Size - 18 - - ID - 288 - Points - - {324, 363} - {324, 381} - - Style - - stroke - - Cap - 0 - HeadArrow - 0 - Join - 0 - LineType - 1 - TailArrow - 0 - TailScale - 1.8571430444717407 - Width - 2 - - - Tail - - ID - 289 - - - - AllowConnections - NO - Bounds - {{301.5, 322.5}, {45, 36}} - Class - ShapedGraphic - FontInfo - - Font - CourierNewPS-BoldMT - Size - 18 - - ID - 289 - Magnets - - {1, 0} - {-0.460092, -0.26062} - {-0.475541, 0.277852} - - Rotation - 90 - Shape - OrGate - Style - - shadow - - Draws - NO - - stroke - - Width - 2 - - - Text - - VerticalPad - 0 - - VFlip - YES - - - ID - 286 - Rotation - 90 - VFlip - YES - - - Bounds - {{360, 282}, {144, 36}} - Class - ShapedGraphic - FontInfo - - Font - CourierNewPS-BoldMT - Size - 18 - - ID - 290 - Magnets - - {0, 1} - {0, -1} - - Shape - Trapazoid - Style - - shadow - - Draws - NO - - stroke - - Width - 2 - - - - - Class - LineGraphic - FontInfo - - Font - CourierNewPS-BoldMT - Size - 18 - - ID - 291 - Points - - {315, 327.101} - {315, 261} - - Style - - stroke - - HeadArrow - 0 - TailArrow - 0 - Width - 2 - - - - - AllowConnections - NO - AllowLabelDrop - - AllowToConnect - - Class - LineGraphic - FontInfo - - Font - CourierNewPS-BoldMT - Size - 18 - - ID - 292 - Points - - {378, 300} - {333, 300} - {288, 300} - - Style - - stroke - - HeadArrow - 0 - TailArrow - 0 - Width - 2 - - - - - ID - 277 - VFlip - YES - - - Bounds - {{389, 507}, {11, 21}} - Class - ShapedGraphic - FitText - YES - Flow - Resize - FontInfo - - Font - CourierNewPS-BoldMT - Size - 18 - - ID - 276 - Shape - Rectangle - Style - - fill - - Draws - NO - - shadow - - Draws - NO - - stroke - - Draws - NO - - - Text - - Pad - 0 - Text - {\rtf1\ansi\ansicpg1252\cocoartf1038\cocoasubrtf360 -{\fonttbl\f0\fmodern\fcharset0 CourierNewPS-BoldMT;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural - -\f0\b\fs36 \cf0 r} - VerticalPad - 0 - - VFlip - YES - Wrap - NO - - - Bounds - {{401, 471}, {22, 21}} - Class - ShapedGraphic - FitText - YES - Flow - Resize - FontInfo - - Font - CourierNewPS-BoldMT - Size - 18 - - ID - 259 - Shape - Rectangle - Style - - fill - - Draws - NO - - shadow - - Draws - NO - - stroke - - Draws - NO - - - Text - - Pad - 0 - Text - {\rtf1\ansi\ansicpg1252\cocoartf1038\cocoasubrtf360 -{\fonttbl\f0\fmodern\fcharset0 CourierNewPS-BoldMT;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural - -\f0\b\fs36 \cf0 in} - VerticalPad - 0 - - VFlip - YES - Wrap - NO - - - Bounds - {{252, 471}, {65, 21}} - Class - ShapedGraphic - FitText - YES - Flow - Resize - FontInfo - - Font - CourierNewPS-BoldMT - Size - 18 - - ID - 260 - Shape - Rectangle - Style - - fill - - Draws - NO - - shadow - - Draws - NO - - stroke - - Draws - NO - - - Text - - Pad - 0 - Text - {\rtf1\ansi\ansicpg1252\cocoartf1038\cocoasubrtf360 -{\fonttbl\f0\fmodern\fcharset0 CourierNewPS-BoldMT;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural - -\f0\b\fs36 \cf0 enable} - VerticalPad - 0 - - VFlip - YES - Wrap - NO - - - Bounds - {{387, 400}, {11, 21}} - Class - ShapedGraphic - FitText - YES - Flow - Resize - FontInfo - - Font - CourierNewPS-BoldMT - Size - 18 - - ID - 261 - Shape - Rectangle - Style - - fill - - Draws - NO - - shadow - - Draws - NO - - stroke - - Draws - NO - - - Text - - Pad - 0 - Text - {\rtf1\ansi\ansicpg1252\cocoartf1038\cocoasubrtf360 -{\fonttbl\f0\fmodern\fcharset0 CourierNewPS-BoldMT;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural - -\f0\b\fs36 \cf0 f} - VerticalPad - 0 - - VFlip - YES - Wrap - NO - - - Bounds - {{459, 400}, {11, 21}} - Class - ShapedGraphic - FitText - YES - Flow - Resize - FontInfo - - Font - CourierNewPS-BoldMT - Size - 18 - - ID - 262 - Shape - Rectangle - Style - - fill - - Draws - NO - - shadow - - Draws - NO - - stroke - - Draws - NO - - - Text - - Pad - 0 - Text - {\rtf1\ansi\ansicpg1252\cocoartf1038\cocoasubrtf360 -{\fonttbl\f0\fmodern\fcharset0 CourierNewPS-BoldMT;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural - -\f0\b\fs36 \cf0 t} - VerticalPad - 0 - - VFlip - YES - Wrap - NO - - - Class - LineGraphic - FontInfo - - Font - CourierNewPS-BoldMT - Size - 18 - - ID - 263 - Points - - {468, 396} - {468, 369} - - Style - - stroke - - HeadArrow - 0 - TailArrow - 0 - Width - 2 - - - - - Class - LineGraphic - FontInfo - - Font - CourierNewPS-BoldMT - Size - 18 - - ID - 264 - Points - - {396, 396} - {396, 369} - - Style - - stroke - - HeadArrow - 0 - TailArrow - 0 - Width - 2 - - - - - Bounds - {{462, 348}, {22, 21}} - Class - ShapedGraphic - FitText - YES - Flow - Resize - FontInfo - - Font - CourierNewPS-BoldMT - Size - 18 - - ID - 265 - Shape - Rectangle - Style - - fill - - Draws - NO - - shadow - - Draws - NO - - stroke - - Draws - NO - - - Text - - Pad - 0 - Text - {\rtf1\ansi\ansicpg1252\cocoartf1038\cocoasubrtf360 -{\fonttbl\f0\fmodern\fcharset0 CourierNewPS-BoldMT;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural - -\f0\b\fs36 \cf0 e2} - VerticalPad - 0 - - VFlip - YES - Wrap - NO - - - Bounds - {{257, 400}, {22, 21}} - Class - ShapedGraphic - FitText - YES - Flow - Resize - FontInfo - - Font - CourierNewPS-BoldMT - Size - 18 - - ID - 266 - Shape - Rectangle - Style - - fill - - Draws - NO - - shadow - - Draws - NO - - stroke - - Draws - NO - - - Text - - Pad - 0 - Text - {\rtf1\ansi\ansicpg1252\cocoartf1038\cocoasubrtf360 -{\fonttbl\f0\fmodern\fcharset0 CourierNewPS-BoldMT;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural - -\f0\b\fs36 \cf0 c2} - VerticalPad - 0 - - VFlip - YES - Wrap - NO - - - Bounds - {{330.639, 409.502}, {8.99658, 8.99658}} - Class - ShapedGraphic - FontInfo - - Font - CourierNewPS-BoldMT - Size - 18 - - ID - 267 - Line - - ID - 275 - Position - 0.4762515127658844 - RotationType - 0 - - Shape - Circle - Style - - fill - - Color - - b - 0 - g - 0 - r - 0 - - - shadow - - Draws - NO - - stroke - - Width - 2 - - - - - Class - LineGraphic - FontInfo - - Font - CourierNewPS-BoldMT - Size - 18 - - ID - 268 - Points - - {432, 433} - {432, 495} - - Style - - stroke - - HeadArrow - FilledArrow - HeadScale - 1.5000001192092896 - LineType - 1 - TailArrow - 0 - Width - 2 - - - Tail - - ID - 273 - Info - 1 - - - - Class - Group - Graphics - - - AllowLabelDrop - - Class - LineGraphic - FontInfo - - Font - CourierNewPS-BoldMT - Size - 18 - - Head - - ID - 272 - - ID - 270 - Points - - {333, 414} - {333.154, 434.917} - - Style - - stroke - - Cap - 0 - HeadArrow - 0 - Join - 0 - LineType - 1 - TailArrow - 0 - Width - 2 - - - - - AllowLabelDrop - - Class - LineGraphic - FontInfo - - Font - CourierNewPS-BoldMT - Size - 18 - - ID - 271 - Points - - {324, 477} - {324, 495} - - Style - - stroke - - Cap - 0 - HeadArrow - FilledArrow - Join - 0 - LineType - 1 - TailArrow - 0 - TailScale - 1.8571430444717407 - Width - 2 - - - Tail - - ID - 272 - - - - AllowConnections - NO - Bounds - {{301.5, 436.5}, {45, 36}} - Class - ShapedGraphic - FontInfo - - Font - CourierNewPS-BoldMT - Size - 18 - - ID - 272 - Magnets - - {1, 0} - {-0.460092, -0.26062} - {-0.475541, 0.277852} - - Rotation - 90 - Shape - OrGate - Style - - shadow - - Draws - NO - - stroke - - Width - 2 - - - Text - - VerticalPad - 0 - - VFlip - YES - - - ID - 269 - Rotation - 90 - VFlip - YES - - - Bounds - {{360, 396}, {144, 36}} - Class - ShapedGraphic - FontInfo - - Font - CourierNewPS-BoldMT - Size - 18 - - ID - 273 - Magnets - - {0, 1} - {0, -1} - - Shape - Trapazoid - Style - - shadow - - Draws - NO - - stroke - - Width - 2 - - - - - Class - LineGraphic - FontInfo - - Font - CourierNewPS-BoldMT - Size - 18 - - ID - 274 - Points - - {315, 441} - {315, 387} - - Style - - stroke - - HeadArrow - 0 - TailArrow - 0 - Width - 2 - - - - - AllowConnections - NO - AllowLabelDrop - - AllowToConnect - - Class - LineGraphic - FontInfo - - Font - CourierNewPS-BoldMT - Size - 18 - - ID - 275 - Points - - {378, 414} - {333, 414} - {288, 414} - - Style - - stroke - - HeadArrow - 0 - TailArrow - 0 - Width - 2 - - - - - Bounds - {{351, 534}, {33, 21}} - Class - ShapedGraphic - FitText - YES - Flow - Resize - FontInfo - - Font - CourierNewPS-BoldMT - Size - 18 - - ID - 257 - Shape - Rectangle - Style - - fill - - Draws - NO - - shadow - - Draws - NO - - stroke - - Draws - NO - - - Text - - Pad - 0 - Text - {\rtf1\ansi\ansicpg1252\cocoartf1038\cocoasubrtf360 -{\fonttbl\f0\fmodern\fcharset0 CourierNewPS-BoldMT;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural - -\f0\b\fs36 \cf0 out} - VerticalPad - 0 - - VFlip - YES - Wrap - NO - - - Class - LineGraphic - FontInfo - - Font - CourierNewPS-BoldMT - Size - 18 - - ID - 256 - Points - - {396, 531} - {396, 558} - - Style - - stroke - - HeadArrow - FilledArrow - HeadScale - 1.5000001192092896 - LineType - 1 - TailArrow - 0 - Width - 2 - - - - - Bounds - {{210, 507}, {55, 21}} - Class - ShapedGraphic - FitText - YES - Flow - Resize - FontInfo - - Font - CourierNewPS-BoldMT - Size - 18 - - ID - 255 - Shape - Rectangle - Style - - fill - - Draws - NO - - shadow - - Draws - NO - - stroke - - Draws - NO - - - Text - - Pad - 0 - Text - {\rtf1\ansi\ansicpg1252\cocoartf1038\cocoasubrtf360 -{\fonttbl\f0\fmodern\fcharset0 CourierNewPS-BoldMT;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural - -\f0\b\fs36 \cf0 clock} - VerticalPad - 0 - - VFlip - YES - Wrap - NO - - - Class - Group - Graphics - - - Class - LineGraphic - FontInfo - - Font - CourierNewPS-BoldMT - Size - 18 - - ID - 252 - Points - - {288, 513} - {270, 513} - - Style - - stroke - - HeadArrow - 0 - TailArrow - 0 - Width - 2 - - - - - Class - LineGraphic - FontInfo - - Font - CourierNewPS-BoldMT - Size - 18 - - ID - 253 - Points - - {288, 495} - {306, 513} - {288, 531} - - Style - - stroke - - HeadArrow - 0 - TailArrow - 0 - Width - 2 - - - - - AllowConnections - NO - Bounds - {{288, 495}, {216, 36}} - Class - ShapedGraphic - FontInfo - - Font - CourierNewPS-BoldMT - Size - 18 - - ID - 254 - Shape - Rectangle - Style - - shadow - - Draws - NO - - stroke - - Width - 2 - - - VFlip - YES - - - ID - 251 - VFlip - YES - - - Bounds - {{100.5, 423}, {141, 40}} - Class - ShapedGraphic - FitText - YES - Flow - Resize - FontInfo - - Font - CourierNewPS-BoldMT - Size - 18 - - ID - 88 - Shape - Rectangle - Style - - fill - - Draws - NO - - shadow - - Draws - NO - - stroke - - Draws - NO - - - Text - - Align - 0 - Pad - 0 - Text - {\rtf1\ansi\ansicpg1252\cocoartf1038\cocoasubrtf360 -{\fonttbl\f0\fmodern\fcharset0 CourierNewPS-BoldMT;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural\pardirnatural - -\f0\b\fs36 \cf0 when (c2)\ - \{ r := e2 \}} - VerticalPad - 0 - - Wrap - NO - - - Bounds - {{100.5, 318}, {141, 40}} - Class - ShapedGraphic - FitText - YES - Flow - Resize - FontInfo - - Font - CourierNewPS-BoldMT - Size - 18 - - ID - 68 - Shape - Rectangle - Style - - fill - - Draws - NO - - shadow - - Draws - NO - - stroke - - Draws - NO - - - Text - - Align - 0 - Pad - 0 - Text - {\rtf1\ansi\ansicpg1252\cocoartf1038\cocoasubrtf360 -{\fonttbl\f0\fmodern\fcharset0 CourierNewPS-BoldMT;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural\pardirnatural - -\f0\b\fs36 \cf0 when (c1)\ - \{ r := e1 \}} - VerticalPad - 0 - - Wrap - NO - - - GridInfo - - ShowsGrid - YES - SnapsToGrid - YES - - GuidesLocked - NO - GuidesVisible - YES - HPages - 1 - ImageCounter - 1 - KeepToScale - - Layers - - - Lock - NO - Name - Layer 1 - Print - YES - View - YES - - - LayoutInfo - - Animate - NO - circoMinDist - 18 - circoSeparation - 0.0 - layoutEngine - dot - neatoSeparation - 0.0 - twopiSeparation - 0.0 - - LinksVisible - NO - MagnetsVisible - NO - MasterSheets - - ModificationDate - 2012-05-30 10:27:26 -0700 - Modifier - Jonathan Bachrach - NotesVisible - NO - Orientation - 2 - OriginVisible - NO - PageBreaks - YES - PrintInfo - - NSBottomMargin - - float - 41 - - NSLeftMargin - - float - 18 - - NSPaperSize - - coded - BAtzdHJlYW10eXBlZIHoA4QBQISEhAdOU1ZhbHVlAISECE5TT2JqZWN0AIWEASqEhAx7X05TU2l6ZT1mZn2WgWQCgRgDhg== - - NSRightMargin - - float - 18 - - NSTopMargin - - float - 18 - - - PrintOnePage - - QuickLookPreview - - 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 - 4/NDyqTL1e+Uv+qLny/xZdPpC5APfB3F4n1dfLpUhxvv6pu7utDl8J+nrz5XGZAlAquL - 50v9m968zt9C3/wDhSFj7AplbmRzdHJlYW0KZW5kb2JqCjYgMCBvYmoKMTcyMwplbmRv - YmoKMyAwIG9iago8PCAvVHlwZSAvUGFnZSAvUGFyZW50IDQgMCBSIC9SZXNvdXJjZXMg - NyAwIFIgL0NvbnRlbnRzIDUgMCBSIC9NZWRpYUJveCBbMCAwIDU3NiA3MzNdCj4+CmVu - ZG9iago3IDAgb2JqCjw8IC9Qcm9jU2V0IFsgL1BERiAvVGV4dCBdIC9Db2xvclNwYWNl - IDw8IC9DczIgOSAwIFIgL0NzMSA4IDAgUiA+PiAvRm9udCA8PAovRjIuMCAxMSAwIFIg - L0YxLjAgMTAgMCBSID4+ID4+CmVuZG9iagoxMiAwIG9iago8PCAvTGVuZ3RoIDEzIDAg - UiAvTiAxIC9BbHRlcm5hdGUgL0RldmljZUdyYXkgL0ZpbHRlciAvRmxhdGVEZWNvZGUg - Pj4Kc3RyZWFtCngBhVJPSBRRHP7NNhKEiEGFeIh3CgmVKaysoNp2dVmVbVuV0qIYZ9+6 - o7Mz05vZNcWTBF2iPHUPomN07NChm5eiwKxL1yCpIAg8dej7zezqKIRveTvf+/39ft97 - RG2dpu87KUFUc0OVK6Wnbk5Ni4MfKUUd1E5YphX46WJxjLHruZK/u9fWZ9LYst7HtXb7 - 9j21lWVgIeottrcQ+iGRZgAfmZ8oZYCzwB2Wr9g+ATxYDqwa8COiAw+auTDT0Zx0pbIt - kVPmoigqr2I7Sa77+bnGvou1iYP+XI9m1o69s+qq0UzUtPdEobwPrkQZz19U9mw1FKcN - 45xIQxop8q7V3ytMxxGRKxBKBlI1ZLmfak6ddeB1GLtdupPj+PYQpT7JYKiJtemymR2F - fQB2KsvsEPAF6PGyYg/ngXth/1tRw5PAJ2E/ZId51q0f9heuU+B7hD014M4UrsXx2oof - Xi0BQ/dUI2iMc03E09c5c6SI7zHUGZj3RjmmCzF3lqoTN4A7YR9ZqmYKsV37ruol7nsC - d9PjO9GbOQtcoBxJcrEV2RTQPAlYFH2LsEkOPD7OHlXgd6iYwBy5idzNKPce1REbZ6NS - gVZ6jVfGT+O58cX4ZWwYz4B+rHbXe3z/6eMVdde2Pjz5jXrcOa69nRtVYVZxZQvd/8cy - hI/ZJzmmwdOhWVhr2HbkD5rMTLAMKMR/BT6X+pITVdzV7u24RRLMUD4sbCW6S1RuKdTq - PYNKrBwr2AB2cJLELFocuFNrujl4d9giem35TVey64b++vZ6+9ryHm3KqCkoE82zRGaU - sVuj5N142/1mkRGfODq+572KWsn+SUUQP4U5WiryFFX0VlDWxG9nDn4btn5cP6Xn9UH9 - PAk9rZ/Rr+ijEb4MdEnPwnNRH6NJ8LBpIeISoIqDM9ROVGONA+Ip8fK0W2SR/Q9AGf1m - CmVuZHN0cmVhbQplbmRvYmoKMTMgMCBvYmoKNzA0CmVuZG9iago5IDAgb2JqClsgL0lD - Q0Jhc2VkIDEyIDAgUiBdCmVuZG9iagoxNCAwIG9iago8PCAvTGVuZ3RoIDE1IDAgUiAv - TiAzIC9BbHRlcm5hdGUgL0RldmljZVJHQiAvRmlsdGVyIC9GbGF0ZURlY29kZSA+Pgpz - dHJlYW0KeAGFVM9rE0EU/jZuqdAiCFprDrJ4kCJJWatoRdQ2/RFiawzbH7ZFkGQzSdZu - NuvuJrWliOTi0SreRe2hB/+AHnrwZC9KhVpFKN6rKGKhFy3xzW5MtqXqwM5+8943731v - dt8ADXLSNPWABOQNx1KiEWlsfEJq/IgAjqIJQTQlVdvsTiQGQYNz+Xvn2HoPgVtWw3v7 - d7J3rZrStpoHhP1A4Eea2Sqw7xdxClkSAog836Epx3QI3+PY8uyPOU55eMG1Dys9xFki - fEA1Lc5/TbhTzSXTQINIOJT1cVI+nNeLlNcdB2luZsbIEL1PkKa7zO6rYqGcTvYOkL2d - 9H5Os94+wiHCCxmtP0a4jZ71jNU/4mHhpObEhj0cGDX0+GAVtxqp+DXCFF8QTSeiVHHZ - Lg3xmK79VvJKgnCQOMpkYYBzWkhP10xu+LqHBX0m1xOv4ndWUeF5jxNn3tTd70XaAq8w - Dh0MGgyaDUhQEEUEYZiwUECGPBoxNLJyPyOrBhuTezJ1JGq7dGJEsUF7Ntw9t1Gk3Tz+ - KCJxlEO1CJL8Qf4qr8lP5Xn5y1yw2Fb3lK2bmrry4DvF5Zm5Gh7X08jjc01efJXUdpNX - R5aseXq8muwaP+xXlzHmgjWPxHOw+/EtX5XMlymMFMXjVfPqS4R1WjE3359sfzs94i7P - LrXWc62JizdWm5dn/WpI++6qvJPmVflPXvXx/GfNxGPiKTEmdornIYmXxS7xkthLqwvi - YG3HCJ2VhinSbZH6JNVgYJq89S9dP1t4vUZ/DPVRlBnM0lSJ93/CKmQ0nbkOb/qP28f8 - F+T3iuefKAIvbODImbptU3HvEKFlpW5zrgIXv9F98LZua6N+OPwEWDyrFq1SNZ8gvAEc - dod6HugpmNOWls05Uocsn5O66cpiUsxQ20NSUtcl12VLFrOZVWLpdtiZ0x1uHKE5QvfE - p0plk/qv8RGw/bBS+fmsUtl+ThrWgZf6b8C8/UUKZW5kc3RyZWFtCmVuZG9iagoxNSAw - IG9iago3MzcKZW5kb2JqCjggMCBvYmoKWyAvSUNDQmFzZWQgMTQgMCBSIF0KZW5kb2Jq - CjQgMCBvYmoKPDwgL1R5cGUgL1BhZ2VzIC9NZWRpYUJveCBbMCAwIDYxMiA3OTJdIC9D - b3VudCAxIC9LaWRzIFsgMyAwIFIgXSA+PgplbmRvYmoKMTYgMCBvYmoKPDwgL1R5cGUg - L0NhdGFsb2cgL091dGxpbmVzIDIgMCBSIC9QYWdlcyA0IDAgUiA+PgplbmRvYmoKMiAw - IG9iago8PCAvTGFzdCAxNyAwIFIgL0ZpcnN0IDE4IDAgUiA+PgplbmRvYmoKMTggMCBv - YmoKPDwgL1BhcmVudCAxOSAwIFIgL0NvdW50IDAgL0Rlc3QgWyAzIDAgUiAvWFlaIDAg - NzMzIDAgXSAvVGl0bGUgKENhbnZhcyAxKQo+PgplbmRvYmoKMTkgMCBvYmoKPDwgPj4K - ZW5kb2JqCjE3IDAgb2JqCjw8IC9QYXJlbnQgMTkgMCBSIC9Db3VudCAwIC9EZXN0IFsg - MyAwIFIgL1hZWiAwIDczMyAwIF0gL1RpdGxlIChDYW52YXMgMSkKPj4KZW5kb2JqCjIw - IDAgb2JqCjw8IC9MZW5ndGggMjEgMCBSIC9MZW5ndGgxIDc3OTYgL0ZpbHRlciAvRmxh - dGVEZWNvZGUgPj4Kc3RyZWFtCngBvVkLVJNXtt7nfyaERxIS8iAhCT9JCG98IBGUiAmi - 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 - 1GaTw1zukLdmUuP++n9l4q+988y0jPl7ajYxH5rpMxzfidivuVzAuOLLKSVnCQPLoY1p - Y5cLP+Me41+G/YwCT2mZADeHf5TbxJ/jzvOK2emr00VFmCj7HcvXIbT4t0A40jmAgdjO - hckjx1i2Q8sQBv8recSXIggdWpyJFziWEJ5hBRbwzC5GQY11mDlBaLTb0E8OCyZT1VVj - 5dCnnw6ZZPsYAYOZoVjrpY9krVeszMlUV12uFKNF5tx5a31OxqNlWQ48WkHA58A44QzH - HubhO7le75DXe5NkXlRn4i8/j4b8hvsSlWQixuRPSArJPDu88vTwGi73+m627do7iNDI - O12kFc+i/9kVi40snqb78Uy7Au7AE/WF+G5ZB0G5M8GT9uh7poD/PYK/tmZRzYLM8taV - 3a1d7UubsE+USzsXYvJjmo+pBRP9bxNRgqcwvYQJ/2bCU2OA9zBdjoxcSMMYTcB+Ux0D - 4Dg+nfHG/vKabhjffhOfntPe2P+em+qrb6pTnW/sv+amejet/x9hv9JhCmVuZHN0cmVh - bQplbmRvYmoKMjEgMCBvYmoKNDc2NgplbmRvYmoKMjIgMCBvYmoKPDwgL1R5cGUgL0Zv - bnREZXNjcmlwdG9yIC9Bc2NlbnQgNzcwIC9DYXBIZWlnaHQgNjg0IC9EZXNjZW50IC0y - MzAgL0ZsYWdzIDMyCi9Gb250QkJveCBbLTk1MSAtNDgxIDE0NDUgMTEyMl0gL0ZvbnRO - YW1lIC9EU1JXUlUrSGVsdmV0aWNhIC9JdGFsaWNBbmdsZSAwCi9TdGVtViAwIC9NYXhX - aWR0aCAxNTAwIC9YSGVpZ2h0IDUxMyAvRm9udEZpbGUyIDIwIDAgUiA+PgplbmRvYmoK - MjMgMCBvYmoKWyAyNzggMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAg - MCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMAowIDAgMCAwIDAgMCAyNzggMCAw - IDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDU1NiAwIDAg - MCA1NTYKMCAwIDAgMjIyIDAgMCAyMjIgMCA1NTYgMCAwIDAgMCA1MDAgMjc4IDU1NiA1 - MDAgXQplbmRvYmoKMTEgMCBvYmoKPDwgL1R5cGUgL0ZvbnQgL1N1YnR5cGUgL1RydWVU - eXBlIC9CYXNlRm9udCAvRFNSV1JVK0hlbHZldGljYSAvRm9udERlc2NyaXB0b3IKMjIg - MCBSIC9XaWR0aHMgMjMgMCBSIC9GaXJzdENoYXIgMzIgL0xhc3RDaGFyIDExOCAvRW5j - b2RpbmcgL01hY1JvbWFuRW5jb2RpbmcKPj4KZW5kb2JqCjI0IDAgb2JqCjw8IC9MZW5n - dGggMjUgMCBSIC9MZW5ndGgxIDIwMjQwIC9GaWx0ZXIgL0ZsYXRlRGVjb2RlID4+CnN0 - cmVhbQp4Aa18C1xUx/X/zNy7Txa4+4QF2Se7PBbYRQEF0b2ISAQVfEUwEvBB1NQEXzFv - Jc3bpJUkNc/2J2nzbNJkAZOgTStt0jRJa+OvsUlM22D6S/O2mvzUNlF2/9+ZXXw0/T0+ - n/9vlzNnZu7cc2bOnDNz5ty7bN54RTcxkV4iEXXlZcvXE/EJqkAHV27Z7BFF4lhHiD7j - kvWrL0uWXdcRomtfve7qS5LlgjmEFKhrupevSpbJaeCqNahIlmkFcP6ayzZflSwH3gFe - s65nZep6gQ3lqsuWX5XiT/6Esufy5Zd1J9vP+wC4ZH3Pps2p8p3Abes3dqfa0zZC7Jbz - yxmEULTKIV+SWnIT0RBGFBIm7RjJOs2bREaZX9cQwn7y4eLOzNoTeoNekP/R4p46nvlV - 2p6V8Su/nq/5geFXaGsQ7fkF3Kd9cuwBQuT98SsTEc0PzlzhV/knZ2CJu26aTEkYEAFI - IhdFrgXQCegCvAEYBRwF6IkHKW+7A7ALwK9oiFtKkDAgApBIFGknYPRMaQdyuwD9gGMA - DVGl+FBaxkR3XaMUx61xsh6wCyDj1rOlo6JmR+paP7BEMmUNxhJGGgXsABwFyMQjnUa9 - Ip0iPYB+lA4DZFD/Gl3icIq0AHcJOAV8muxD3QHAMYAxMSL9Y2j+womkrlb6CoS+Qi+/ - Iq2A9YBeQAxwGAA5IA1LYxjxVyA8Jlp1Id8H2IfyCPABAG+dBjq8xRhYjpFnAZzOeCve - 4hjAAPZfDU69d+IekUk3i8yJoZraiQfqbNIJjK1PpJlIw4AooAWwA/AsQAs2xwcNJnHf - 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 - BPMdhGXemNLqbqy1j6MkYa4s2AGikPgczMkynKwkWoCd9mXydOJhaTFoDAiTeZy9QT3x - H5ECrDKXY39qJv9Bp5NP8d1Ndo89CG5PaB8H1z3aJ8kJ7Q/wxG8nSnewBo1ZDkPnx1gP - /U7iovhFWNOuJXvkv+JRD1HntC25cPGihQvmt7bMa5odnT6tdmpN9ZTJlRWTJpZHwmWl - JaHiosKCYCDf7/N63K68Cbk5zuwsh91mtZiVzIx0U5rRoNdpNbLEKClp8M/q8sSCXTE5 - 6L/gglJe9i9HxfJzKrpiHlTNOr9NzMPvW45L57VU0fKSf2qpJluqZ1pSxVNLaktLPA1+ - T2z/TL9nmC6d34b8d2b62z2xIyI/V+TloCiko+D14g5PQ/aamZ4Y7fI0xGZtWbO9oWtm - aQkdSDPW++u7jaUlZMCYhmwacrEs//oBmjWdigzLaqgZYESfjjHGcvwzG2JOP24FGSnQ - sHxVrHV+W8PMXK+3vbQkRutX+lfECHekQ6IJqRdsYtr6mE6w8ayNYTjkDs9Aycj2O4cV - sqIrZFrlX7V8WVtMWg4aDTFzCHxnxrKu+SD7bBHE4bLfeu7VXGl7Q/ZaD2+8ffutnlj/ - /LZz7s31cgrt7aCBe1lgVtf2WWB9J6aKZofROd59PpTkoJJHoUDXpZ6YwT/Dv2b7pV2Y - kJztMbLgau9gTo66J3GY5DR4ti9q83tj0Vx/+/KZEwZsZPuCq4ecqsd5/pXSkgHFnJTm - QEZmKmNKPzfTDUknr4mcaM5zzQvOiJPyPvpnx1To0UoPetLmx0Cm8KR7Ctm+cgqkjk87 - xV2xVZiGtTFDfdd2pYbXQ5Q0pgkofs/2EwTT7j/y+fk1y1M12oACS8ZFrhxnFCxGl4/n - YzglFBdzvdDVYyLRx+miXFlasmWY7fevVzxAOEmS1jbc1l4Thsy9Xj6rdwyrZAUKsd75 - bcmyh6zIHSRqGOct1sWvjIxfsS/mV3rHr5y5vcsP9d2NXRMvXcT0wTN/mYrD2rCmJkYd - /83l7uT15oX+ZgRhPA3bu1Kq2rzovFLyOhco5IZrqVzMWt8m5TKu2sixXElchSYuW3qm - CQptppgcwJ9WaPKqYZ0eqihqqGdWTOm6IJm2G73elKH8TzcNJ47xuwQ6e1tqGLGaUKqj - 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 - M5JUM29eDWCsIJXBSlFEPfLjUg92kFwy9Xl9KdGVEjrMjqgOe0apI7PUYU8jTurMyZMt - zglXDycXdK6+JFw7l6vwSa7IkFtKW718mdVK55Vk1+nvcY2V1vH0nDz74bjixrdOKSuD - CpdNQZ/aE+/J90uPIxI5mU5TK4s1NFJGNVWOKn9VtDgaipZMK70s47oMg8Zj99ynf0n7 - mueg9gPtySrsq2fO0uP2aoO9WiPFk32E3lJEi4onV5gsRq7FYZenQjG2Gplq7DUyo7ez - hLaU0JKSIptaCovutihel67I2FtBK7xyWjqUb8lub6eP+vjNBkta1JdTnXVrZJgtVi06 - NSsj6tZ5dBGdpHNOiT6f3IVCc8e4OoY6+A6I+doQjR7hjzQyFbV0aVRRM108sUWhpe1H - Qpbq8IaNR6CbaCIMdgiNeFeH0E5gJTeF7QIPJm/FzdWW6mpztfI5NSODP76UdGyAKnsr - U9tLPjaVlBon1WV8SxxfbKTk0itW3qrJknvu3jmP/o7qPu64pqXnoruqXEXVtvzqOf+m - 7nvTzyfx2LVrrl86JXfikqafzo4UFT176Q1/tpWX1eSnTy3LCWYpduejO+JL+eTSnuxp - BYV5Fm/NRLzz+FliVL5XY8a+Xkz71HINMxiMJul5/Sv6j/RfG2Q3U0zufCUYZh5TON8T - /Cz4WfFp7WlPIj89XzVkRoNC9sjkq8a0ClHKRiZXlX25aqExqCd8AbdYbXZH1rgC8GWc - nImrjNc6XbPTPemFmb0I2ssu4vPKukxjodeY5uYTaiM6RcymqmvVaWM6elhHdYK32RjV - 5ZSQQAbUQbVlEYfHEXG84Rh1HHUkHLpdDuoYb+ZwhlZeJ/QAizpXAO4DhTo2dMwVmyms - 11y9AfM1ZXwtei5dTVMqKO4fBMZuidWo/mo1p6jY49UYvBq3mxYZkHi0Pjct1he6Cdpg - P73hhhvI7EVXq0qwIM0UNBX65YK0gJ+Y0nHwwaY7ftWfz6R85vNr/DjeY+k5cxXaF+qg - WPWoma9sxG4jUJECe2pZmWROZShfBbV2G7bmKrqq+aGWP9DC+IcfLbi/8VhTVJ3tF3oh - LR68oXew/+67H9aY4xXl5fF3D/w6fqK4aKLYna7k6ekHt8Vi12246y6sbBth6XfA0kPk - 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 - OLJxdLYkfhOZtJHniGrIqxBKAcyVZBCYO+vcF+JLPP+I7d2RjROONTvdHMVPT1/HMzRX - 1FqFBKX31IxSXPMhcfDjBCZyZAgYE/neC5bsKMtGkiTF0/aNeDK+kZ8uz37E0449xA7t - BRuhvcCiY1i1hPYCizJ6IMrAooy4uSgDizL6JMrAKPcOoVcoCyzKODmKMrBobxXlkSFg - UUZfxf3AvDyYVs2LA2l8V/3Gp51i491I+U8tzh5F8JaF1TrJahWPXfDahfAidZKfrfnu - L56eUh1t2tcUzc9tmbft+d7WOdmRaNMvmqKTq574Ob0mfgvbJ1WHuBtY5smO/5TOjQ/R - hlQcsKhaHqvD2kLb8E7TlZpMvOd/vVocNoTzv02+IHJRBn3MdtLJdM4gkqBBJlnBJV5F - V2+y5P/Gm3CRYfrsYFYxonRLnzcbfmNKmF176RpipmtUgycrksWynGUf7cGPF5Ixu7mI - UI8hUIDANLB4UOUM82cP1QiM8GcL+OOxUZsLL0JpcQLh62lFGeO+HaK2Zv72EY+a4uUG - NNKyvvwc96KqaeH668ryJiwrL+8wmvvXRqZVXZhmyaVfFM29ML63yK+rKS6pbWytaKBr - Q560qpLSqrR0WzG98PKHa0uKavQZ9qL43oZmLoP5kMF6IYOtavixnBN2prUH7EVuyWfw - 5t+JF/+/ztDogsUGuxM+LOSgW2JSvP+TIIaycsJnRHDynyUQReSEiyD5mA5S4I86Oygm - PjVuDJgfGpISSY07eTRLSYRN8ef+V0JwciHU01lFfn1NkRDCzPiPQ15jVWmJEEL8vp4z - QqCzLpyD04H4xP34nQL3jf75g6g9osRpeKfPihCtHU/qPGQmYqSz8HuP2fgdxBz8+qSF - zMfvXhaTJfhlxFK8idgliFCsYUl6Wh77b25dMHtea6i+54qNa7s3zuu+snVh6Yyedavm - Lvp/6hp0XgplbmRzdHJlYW0KZW5kb2JqCjI1IDAgb2JqCjEzNDY2CmVuZG9iagoyNiAw - IG9iago8PCAvVHlwZSAvRm9udERlc2NyaXB0b3IgL0FzY2VudCA4MzMgL0NhcEhlaWdo - dCA2MjUgL0Rlc2NlbnQgLTMwMCAvRmxhZ3MgMzIKL0ZvbnRCQm94IFstMTkyIC03MTAg - NzAyIDEyMjJdIC9Gb250TmFtZSAvS1BSSU5QK0NvdXJpZXJOZXdQUy1Cb2xkTVQgL0l0 - YWxpY0FuZ2xlCjAgL1N0ZW1WIDAgL01heFdpZHRoIDYwMCAvWEhlaWdodCA1NDkgL0Zv - bnRGaWxlMiAyNCAwIFIgPj4KZW5kb2JqCjI3IDAgb2JqClsgNjAwIDAgMCAwIDAgMCAw - IDAgNjAwIDYwMCAwIDAgMCAwIDAgMCA2MDAgNjAwIDYwMCAwIDAgMCAwIDAgMCAwIDYw - MCAwIDAKNjAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAw - IDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMAo2MDAgNjAwIDYwMCAwIDYwMCA2MDAg - MCA2MDAgNjAwIDAgNjAwIDYwMCAwIDYwMCA2MDAgMCAwIDYwMCAwIDYwMCA2MDAgMCA2 - MDAKMCAwIDAgNjAwIDAgNjAwIF0KZW5kb2JqCjEwIDAgb2JqCjw8IC9UeXBlIC9Gb250 - IC9TdWJ0eXBlIC9UcnVlVHlwZSAvQmFzZUZvbnQgL0tQUklOUCtDb3VyaWVyTmV3UFMt - Qm9sZE1UIC9Gb250RGVzY3JpcHRvcgoyNiAwIFIgL1dpZHRocyAyNyAwIFIgL0ZpcnN0 - Q2hhciAzMiAvTGFzdENoYXIgMTI1IC9FbmNvZGluZyAvTWFjUm9tYW5FbmNvZGluZwo+ - PgplbmRvYmoKMjggMCBvYmoKKE1hYyBPUyBYIDEwLjYuOCBRdWFydHogUERGQ29udGV4 - dCkKZW5kb2JqCjI5IDAgb2JqCihEOjIwMTIwNTMwMTcyNzQ0WjAwJzAwJykKZW5kb2Jq - CjEgMCBvYmoKPDwgL1Byb2R1Y2VyIDI4IDAgUiAvQ3JlYXRpb25EYXRlIDI5IDAgUiAv - TW9kRGF0ZSAyOSAwIFIgPj4KZW5kb2JqCnhyZWYKMCAzMAowMDAwMDAwMDAwIDY1NTM1 - IGYgCjAwMDAwMjQwNzMgMDAwMDAgbiAKMDAwMDAwMzk3NSAwMDAwMCBuIAowMDAwMDAx - ODM5IDAwMDAwIG4gCjAwMDAwMDM4MjYgMDAwMDAgbiAKMDAwMDAwMDAyMiAwMDAwMCBu - IAowMDAwMDAxODE5IDAwMDAwIG4gCjAwMDAwMDE5NDMgMDAwMDAgbiAKMDAwMDAwMzc5 - MCAwMDAwMCBuIAowMDAwMDAyODk0IDAwMDAwIG4gCjAwMDAwMjM3OTQgMDAwMDAgbiAK - MDAwMDAwOTU0OSAwMDAwMCBuIAowMDAwMDAyMDY2IDAwMDAwIG4gCjAwMDAwMDI4NzQg - MDAwMDAgbiAKMDAwMDAwMjkzMCAwMDAwMCBuIAowMDAwMDAzNzcwIDAwMDAwIG4gCjAw - MDAwMDM5MDkgMDAwMDAgbiAKMDAwMDAwNDEzOCAwMDAwMCBuIAowMDAwMDA0MDIzIDAw - MDAwIG4gCjAwMDAwMDQxMTYgMDAwMDAgbiAKMDAwMDAwNDIzMSAwMDAwMCBuIAowMDAw - MDA5MDg3IDAwMDAwIG4gCjAwMDAwMDkxMDggMDAwMDAgbiAKMDAwMDAwOTMzMyAwMDAw - MCBuIAowMDAwMDA5NzI0IDAwMDAwIG4gCjAwMDAwMjMyODEgMDAwMDAgbiAKMDAwMDAy - MzMwMyAwMDAwMCBuIAowMDAwMDIzNTM2IDAwMDAwIG4gCjAwMDAwMjM5NzkgMDAwMDAg - biAKMDAwMDAyNDAzMSAwMDAwMCBuIAp0cmFpbGVyCjw8IC9TaXplIDMwIC9Sb290IDE2 - IDAgUiAvSW5mbyAxIDAgUiAvSUQgWyA8ZWFkZDM3NTdlMzUyZGMyMDc3NjU1NDZhMzVj - N2E2NmY+CjxlYWRkMzc1N2UzNTJkYzIwNzc2NTU0NmEzNWM3YTY2Zj4gXSA+PgpzdGFy - dHhyZWYKMjQxNDgKJSVFT0YKMSAwIG9iago8PC9BdXRob3IgKEtyc3RlIEFzYW5vdmlj - XG5Kb25hdGhhbiBCYWNocmFjaCkvQ3JlYXRpb25EYXRlIChEOjIwMTEwOTEzMDY1NjAw - WikvQ3JlYXRvciAoT21uaUdyYWZmbGUgUHJvZmVzc2lvbmFsIDUuMy42KS9Nb2REYXRl - IChEOjIwMTIwNTMwMTcyNzAwWikvUHJvZHVjZXIgMjggMCBSIC9UaXRsZSAoY29uZHVw - ZGF0ZXMuZ3JhZmZsZSk+PgplbmRvYmoKeHJlZgoxIDEKMDAwMDAyNDkwNiAwMDAwMCBu - IAp0cmFpbGVyCjw8L0lEIFs8ZWFkZDM3NTdlMzUyZGMyMDc3NjU1NDZhMzVjN2E2NmY+ - IDxlYWRkMzc1N2UzNTJkYzIwNzc2NTU0NmEzNWM3YTY2Zj5dIC9JbmZvIDEgMCBSIC9Q - cmV2IDI0MTQ4IC9Sb290IDE2IDAgUiAvU2l6ZSAzMD4+CnN0YXJ0eHJlZgoyNTExNgol - JUVPRgo= - - QuickLookThumbnail - - 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 - AAEAAQ== - - ReadOnly - NO - RowAlign - 1 - RowSpacing - 36 - SheetTitle - Canvas 1 - SmartAlignmentGuidesActive - YES - SmartDistanceGuidesActive - YES - UniqueID - 1 - UseEntirePage - - VPages - 1 - WindowInfo - - CurrentSheet - 0 - ExpandedCanvases - - - name - Canvas 1 - - - Frame - {{72, 4}, {1368, 874}} - ListView - - OutlineWidth - 142 - RightSidebar - - ShowRuler - - Sidebar - - SidebarWidth - 120 - VisibleRegion - {{-16, 224.5}, {609.5, 360}} - Zoom - 2 - ZoomValues - - - Canvas 1 - 2 - 1 - - - - saveQuickLookFiles - YES - - diff --git a/doc/tutorial/figs/condupdates.pdf b/doc/tutorial/figs/condupdates.pdf deleted file mode 100644 index 8ba9abb9..00000000 Binary files a/doc/tutorial/figs/condupdates.pdf and /dev/null differ diff --git a/doc/tutorial/figs/cpu.png b/doc/tutorial/figs/cpu.png deleted file mode 100644 index cc0e89b8..00000000 Binary files a/doc/tutorial/figs/cpu.png and /dev/null differ diff --git a/doc/tutorial/retreat-talk.tex b/doc/tutorial/retreat-talk.tex deleted file mode 100644 index 3c59131e..00000000 --- a/doc/tutorial/retreat-talk.tex +++ /dev/null @@ -1,1067 +0,0 @@ -\documentclass[xcolor=pdflatex,dvipsnames,table]{beamer} -\usepackage{epsfig,graphicx} -\usepackage{palatino} -\usepackage{fancybox} -\usepackage{relsize} -\usepackage[procnames]{listings} -\usepackage{array} - -\input{../style/scala.tex} -\input{../style/talk.tex} - -\title[Chisel]{Chisel: Constructing Hardware In a Scala Embedded Language} -\author[Bachrach et al]{Jonathan Bachrach, Huy Vo, Brian Richards, \\ -Yunsup Lee, Andrew Waterman, Rimas Avizienis, Henry Cook, \\ -John Wawrzynek, Krste Asanovic} -\date{\today} -\institute[parlab]{EECS UC Berkeley} - -\begin{document} - -{ -\setbeamertemplate{footline}{} -\begin{frame} - \titlepage -\end{frame} -} -\addtocounter{framenumber}{-1} - -\begin{frame}[fragile] -\frametitle{21st Century Architecture Design} -{\Large\textbf{Harder to get hardware / software efficiency gains}} -\vskip5mm -\begin{itemize} -\item Need massive design-space exploration -\begin{itemize} -\item Hardware and software codesign and cotuning -\end{itemize} -\item Need meaningful results -\begin{itemize} -\item Cycle counts -\item Cycle time, power and area -\item Real chips -\end{itemize} -\item Traditional architectural simulators, hardware-description - languages, and tools are inadequate -\begin{itemize} -\item Slow -\item Inaccurate -\item Error prone -\item Difficult to modify and parameterize -\end{itemize} -\end{itemize} -\end{frame} - -\begin{frame}[fragile] -\frametitle{Bottom Line -- Shorten Design Loop} -{\LARGE\textbf{Make it}} -\vskip2mm -\begin{itemize} -\item Easier to make design changes -\begin{itemize} -\item Fewer lines of design code ( \textbf{>> 3x} ) -\item More reusable code -\item Parameterize designs -\end{itemize} -\item Faster to test results ( \textbf{>> 8x} ) -\begin{itemize} -\item Fast compilation -\item Fast simulation -\item Easy testing -\item Easy verification -\end{itemize} -\end{itemize} -\vskip0.8cm -{\LARGE\textbf{Result}} -\begin{itemize} -\item Explore more design space -\end{itemize} - -\end{frame} - -\begin{frame}[fragile] -\frametitle{Chisel is ...} - -\begin{columns}[c] - -\column{0.55\textwidth} - -\begin{itemize} -\item Best of hardware and software design ideas -\item Embedded within Scala language to leverage mindshare and language design -\item Algebraic construction and wiring -\item Hierarchical, object oriented, and functional construction -\item Abstract data types and interfaces -\item Bulk connections -\item Multiple targets -\begin{itemize} -\item Simulation and synthesis -\item Memory IP is target-specific -\end{itemize} -\end{itemize} - -\column{0.40\textwidth} - -\begin{center} -single source \\ -\includegraphics[width=0.99\textwidth]{../manual/figs/targets.pdf} \\ -multiple targets \\ -\end{center} - -\end{columns} - -\end{frame} - -\begin{frame}[fragile] -\frametitle{The Scala Programming Language} - -\begin{columns}[c] - -\column{0.75\textwidth} - -\begin{itemize} -\item Compiled to JVM -\begin{itemize} -\item Good performance -\item Great Java interoperability -\item Mature debugging, execution environments -\end{itemize} -\item Object Oriented -\begin{itemize} -\item Factory Objects, Classes -\item Traits, overloading etc -\end{itemize} -\item Functional -\begin{itemize} -\item Higher order functions -\item Anonymous functions -\item Currying etc -\end{itemize} -\item Extensible -\begin{itemize} -\item Domain Specific Languages (DSLs) -\end{itemize} -\end{itemize} - -\column{0.25\textwidth} - -\begin{center} -\includegraphics[height=0.4\textheight]{figs/programming-scala.pdf} \\ -\includegraphics[height=0.4\textheight]{figs/programming-in-scala.pdf} -\end{center} - -\end{columns} -\end{frame} - -\begin{frame}[fragile] -\frametitle{Algebraic Graph Construction} - -\begin{columns} -\column{0.35\textwidth} -{\lstset{basicstyle={\Large\ttfamily}} -\begin{scala} -Mux(x > y, x, y) -\end{scala} -} - -\column{0.6\textwidth} - -\begin{center} -\includegraphics[width=0.9\textwidth]{figs/max2.pdf} -\end{center} -\end{columns} -\end{frame} - -\begin{frame}[fragile] -\frametitle{Creating Component} - -\begin{columns} -\column{0.45\textwidth} - -{\lstset{basicstyle={\scriptsize\ttfamily}} -\begin{scala} -class Max2 extends Component { - val io = new Bundle { - val x = UFix(width = 8).asInput - val y = UFix(width = 8).asInput - val z = UFix(width = 8).asOutput } - io.z := Mux(io.x > io.y, io.x, io.y) -} -\end{scala} -} - -\column{0.45\textwidth} -\begin{center} -\includegraphics[width=0.95\textwidth]{figs/Max2c.pdf} \\ -\end{center} -\end{columns} - -\end{frame} - -\begin{frame}[fragile] -\frametitle{Connecting Components} - -\begin{columns} -\column{0.25\textwidth} -\begin{scala} -val m1 = new Max2() -m1.io.x := a -m1.io.y := b -val m2 = new Max2() -m2.io.x := c -m2.io.y := d -val m3 = new Max2() -m3.io.x := m1.io.z -m3.io.y := m2.io.z -\end{scala} - -\column{0.7\textwidth} - -\begin{center} -\includegraphics[width=0.99\textwidth]{figs/Max4.pdf} \\ -\end{center} -\end{columns} - -\end{frame} - - -\begin{frame}[fragile] -\frametitle{Defining Construction Functions} - -\begin{columns} - -\column{0.45\textwidth} - -\begin{scala} -def Max2 = Mux(x > y, x, y) -\end{scala} -\begin{scala} -Max2(x, y) -\end{scala} - -\column{0.5\textwidth} - -\begin{center} -\includegraphics[width=0.95\textwidth]{figs/Max2.pdf} \\[1cm] -\end{center} - -\end{columns} - -\end{frame} - -\begin{frame}[fragile] -\frametitle{Functional Construction} - -\begin{columns} - -\column{0.45\textwidth} - -\begin{scala} -Reduce(Array(a, b, c, d), Max2) -\end{scala} - -\column{0.5\textwidth} - -\begin{center} -\includegraphics[width=0.99\textwidth]{figs/reduceMax.pdf} \\ -\end{center} - -\end{columns} - -\end{frame} - -\begin{frame}[fragile] -\frametitle{Example} -\begin{columns} - -\column{0.45\textwidth} - -\begin{footnotesize} -\begin{scala} -class GCD extends Component { - val io = new Bundle { - val a = UFix(INPUT, 16) - val b = UFix(INPUT, 16) - val z = UFix(OUTPUT, 16) - val valid = Bool(OUTPUT) } - val x = Reg(resetVal = io.a) - val y = Reg(resetVal = io.b) - when (x > y) { - x := x - y - } .otherwise { - y := y - x - } - io.z := x - io.valid := y === UFix(0) -} -\end{scala} -\end{footnotesize} - -\column{0.45\textwidth} - -\begin{center} -\includegraphics[width=0.9\textwidth]{figs/gcd.pdf} -\end{center} - -\end{columns} -\end{frame} - -\begin{frame}[fragile] -\frametitle{Primitive Datatypes} -\begin{itemize} -\item{Chisel has 4 primitive datatypes} -\begin{description} -\item[Bits] -- raw collection of bits -\item[Fix] -- signed fixed-point number -\item[UFix] -- unsigned fixed-point number -\item[Bool] -- Boolean value -\end{description} -\item Can do arithmetic and logic with these datatypes -\end{itemize} - -\textbf{Example Literal Constructions} -\begin{scala} -val sel = Bool(false) -val a = UFix(25) -val b = Fix(-35) -\end{scala} -where \verb+val+ is a Scala keyword used to declare variables whose values won't change -\end{frame} - -\begin{frame}[fragile] -\frametitle{Aggregate Data Types} - -\textbf{Bundle} - -\begin{itemize} -\item User-extensible collection of values with named fields -\item Similar to structs -\end{itemize} - -\begin{footnotesize} -% \textbf{Bundle Example} -\begin{scala} -class MyFloat extends Bundle{ - val sign = Bool() - val exponent = UFix(width=8) - val significand = UFix(width=23) -} -\end{scala} -\end{footnotesize} - -\textbf{Vec} - -\begin{itemize} -\item Create indexable collection of values -\item Similar to arrays -\end{itemize} - -\begin{footnotesize} -% \textbf{Vec Example} -\begin{scala} -val myVec = Vec(5){ Fix(width=23) } -\end{scala} -\end{footnotesize} - -\end{frame} - - -\begin{frame}[fragile] -\frametitle{Abstract Data Types} -\begin{itemize} -\item The user can construct new data types -\begin{itemize} -\item Allows for compact, readable code -\end{itemize} -\item Example: Complex numbers -\begin{itemize} -\item Useful for FFT, Correlator, other DSP -\item Define arithmetic on complex numbers -\end{itemize} -\end{itemize} - -\begin{footnotesize} -\begin{scala} -class Complex(val real: Fix, val imag: Fix) - extends Bundle { - def + (b: Complex): Complex = - new Complex(real + b.real, imag + b.imag) - ... -} -val a = new Complex(Fix(32), Fix(-16)) -val b = new Complex(Fix(-15), Fix(21)) -val c = a + b -\end{scala} -\end{footnotesize} - -\end{frame} - -\begin{frame}[fragile] -\frametitle{Polymorphism and Parameterization} -\begin{itemize} -\item Chisel users can define their own parameterized functions -\begin{itemize} -\item Parameterization encourages reusability -\item Data types can be inferred and propagated -\end{itemize} -\end{itemize} - -\textbf{Example Shift Register:} -\begin{scala} -def delay[T <: Data](x: T, n: Int): T = - if(n == 0) x else Reg(delay(x, n - 1)) -\end{scala} -where -\begin{itemize} -\item The input \verb+x+ is delayed n cycles -\item \verb+x+ can by of any type that extends from \verb+Data+ -\end{itemize} - -\end{frame} - -\begin{frame}[fragile, shrink] -\frametitle{Functional Composition} - -% \begin{itemize} -% \item natural -% \item reusable -% \item composable -% \end{itemize} -% \vskip1cm - -\begin{Large} -\begin{columns} - -\column{0.45\textwidth} -\verb+Map(ins, x => x * y)+ \\ -\begin{center} -\includegraphics[height=0.6\textheight]{figs/map.pdf} \\[2cm] -\end{center} - -\column{0.45\textwidth} -\verb+Chain(n, in, x => f(x))+ \\ -\begin{center} -\includegraphics[width=0.9\textwidth]{figs/chain.pdf} \\ -\end{center} - -\verb+Reduce(data, Max)+ \\ -\begin{center} -\includegraphics[width=0.9\textwidth]{figs/reduce.pdf} \\ -\end{center} - - -\end{columns} - -\end{Large} - -\end{frame} - -% \begin{frame}[fragile, shrink] -% \frametitle{Chain} -% -% \begin{columns} -% -% \column{0.6\textwidth} -% -% \begin{scala} -% def Chain[T <: Data] -% (n: Int, in: T, f: T => T): T = { -% if (n == 1) -% in -% else -% chain(n-1, f(in), f) -% } -% \end{scala} -% usage: -% \begin{scala} -% Chain(n, in, x => x + x) -% \end{scala} -% -% \column{0.3\textwidth} -% -% \begin{center} -% \includegraphics[width=0.9\textwidth]{figs/chain.pdf} \\ -% \end{center} -% -% \end{columns} -% \end{frame} -% -% \begin{frame}[fragile, shrink] -% \frametitle{Map} -% -% \begin{columns} -% -% \column{0.6\textwidth} -% -% \begin{scala} -% def Map[S <: Data, T <: Data] -% (ins: Seq[T], f: S => T): T -% \end{scala} -% usage: -% \begin{scala} -% Map(ins, h => Reg(h * Reg(x))) -% \end{scala} -% -% \column{0.3\textwidth} -% -% \begin{center} -% \includegraphics[height=0.7\textheight]{figs/map.pdf} \\ -% \end{center} -% -% \end{columns} -% \end{frame} -% -% \begin{frame}[fragile, shrink]{Reduce} -% -% \begin{columns} -% -% \column{0.6\textwidth} -% -% \begin{scala} -% def Reduce[T <: Data] -% (ins: Seq[T], f: (T, T) => T): T = { -% val len = ins.length -% if (len == 1) -% ins(0) -% else -% f(Reduce(in.slice(0, len/2), f), -% Reduce(in.slice(len/2, len), f)) -% } -% \end{scala} -% usage: -% \begin{scala} -% def Max[T <: Num](x: T, y: T) = -% Mux(x > y, x, y) -% Reduce(data, Max) -% \end{scala} -% -% \column{0.3\textwidth} -% -% \begin{center} -% \includegraphics[width=0.9\textwidth]{figs/Reduce.pdf} \\ -% \end{center} -% -% \end{columns} -% -% \end{frame} - -\begin{frame}[fragile] -\frametitle{Generator} -\begin{footnotesize} -\begin{scala} -class Cache(cache_type: Int = DIR_MAPPED, - associativity: Int = 1, - line_size: Int = 128, - cache_depth: Int = 16, - write_policy: Int = WRITE_THRU - ) extends Component { - val io = new Bundle() { - val cpu = new IoCacheToCPU() - val mem = new IoCacheToMem().flip() - } - val addr_idx_width = log2(cache_depth).toInt - val addr_off_width = log2(line_size/32).toInt - val addr_tag_width = 32 - addr_idx_width - addr_off_width - 2 - val log2_assoc = log2(associativity).toInt - ... - if (cache_type == DIR_MAPPED) - ... -\end{scala} -\end{footnotesize} - -\end{frame} - -\begin{frame}[fragile] -\frametitle{State Elements} - -Simplest element is positive edge triggered register: -\begin{scala} -val prev_in = Reg(in) -\end{scala} -Can assign data input later using wiring -\begin{scala} -val pc = Reg(){ UFix(width = 16) } -pc := pc + UFix(1, 16) -\end{scala} -Can quickly define more useful circuits -\begin{scala} -def risingEdge(x: Bool) = x && !Reg(x) -\end{scala} - -\end{frame} - -\begin{frame}[fragile] -\frametitle{Conditional Updates} - -\begin{columns} - -\column{0.45\textwidth} - -Convenient to specify updates spread across several statements -\begin{scala} -val r = Reg() { UFix(width = 16) } -when (c === UFix(0)) { - r := r + UFix(1) -} -\end{scala} -or -{\lstset{frame=shadowbox} -\begin{scala} -when (c1) { r := e1 } -when (c2) { r := e2 } -\end{scala} -} - -\column{0.45\textwidth} - -\shadowbox{ -\includegraphics[width=0.95\textwidth]{figs/condupdates.pdf} } - -\end{columns} -\end{frame} - -\begin{frame}[fragile] -\frametitle{Composition of Conditional Updates} - -Nesting -\begin{scala} -when (a) { when (b) { body } } -\end{scala} -Chaining -\begin{scala} -when (c1) { u1 } -.elsewhen (c2) { u2 } -.otherwise { ud } -\end{scala} -Dynamic Scoping -\begin{scala} -def condUpdateR (c: Bool, d: Data) = when (c) { r := d } -\end{scala} -\begin{scala} -when (a) { condUpdateR(b, x) } -\end{scala} -\begin{scala} -when (a) { when (b) { r := x } } -\end{scala} - -\end{frame} - -\begin{frame}[fragile] -\frametitle{Symmetry of Conditional Updates} - -Regs and Wires -\begin{scala} -x := init -when (isEnable) { - x := data -} -\end{scala} - -Vecs and Mems -\begin{scala} -when (isEnable) { - m(addr) := data -} -\end{scala} - -\end{frame} - -\begin{frame}[fragile] -\frametitle{Object Oriented Conditional Updates} - -% \begin{scala} -% class DecoupledIO[T <: Data]()(gen: => T) extends Bundle { -% val valid = Bool(dir = OUTPUT) -% val ready = Bool(dir = INPUT) -% val data = gen.asOutput -% } -% -% class EnqIO[T <: Data]()(gen: => T) extends DecoupledIO[T]()(gen) { -% def enq(dat: T): T = { valid := Bool(true); data := dat; dat } -% valid := Bool(false) -% } -% -% class Packet extends Bundle { -% val header = UFix(width = 8) -% val body = Bits(width = 64) -% } -% \end{scala} -% -% example: - -\begin{columns} -\column{0.57\textwidth} - -{\lstset{basicstyle={\scriptsize\ttfamily}} -\begin{scala} -val in = (new DeqIo()){ new Packet() } -val out = (new EnqIo()){ new Packet() } -when (in.valid && out.ready) { - out.enq(filter(in.deq())) -} -\end{scala} - -\vskip5mm - -\begin{scala} -val in = (new DeqIo()){ new Packet() } -val outs = Vec(4){ new EnqIo()){ new Packet() } } -val tbl = Mem(4){ UFix(width = 2) } -when (in.valid) { - val k = tbl(in.data.header) - when (outs(k).ready) { - outs(k).enq(in.deq()) - } -} -\end{scala} -} - -\column{0.38\textwidth} - -\includegraphics[width=0.99\textwidth]{figs/filter.pdf} \\[20mm] -\includegraphics[width=0.99\textwidth]{figs/router.pdf} - -\end{columns} - -\end{frame} - -\begin{frame}[fragile] -\frametitle{Component Testing} - -% \begin{itemize} -% \item write tests in Scala -% \item bind values using dot notation -% \end{itemize} - -\begin{columns} -\column{0.45\textwidth} - -{\lstset{basicstyle={\scriptsize\ttfamily}} -\begin{scala} -class Mux2IO extends Bundle { - val sel = Bits(width = 1).asInput - val in0 = Bits(width = 1).asInput - val in1 = Bits(width = 1).asInput - val out = Bits(width = 1).asOutput -} -\end{scala} -} -\begin{center} -\includegraphics[width=0.9\textwidth]{figs/mux2.pdf} -\end{center} - -\column{0.5\textwidth} -{\lstset{basicstyle={\scriptsize\ttfamily}} -\begin{scala} -class Mux2Tests extends Iterator[Mux2IO] { - var i = 0 - val n = pow(2, 3) - def hasNext = i < n - def next = { - val io = new Mux2IO - val k = Bits(i, width = log2up(n)) - io.sel := k(0) - io.in0 := k(1) - io.in1 := k(2) - io.out := Mux(k(0), k(1), k(2)) - i += 1 - io - } -} -\end{scala} -} - -\end{columns} - -\end{frame} - -\begin{frame}[fragile] -\frametitle{Chisel Line Count Breakdown} - -\begin{columns} - -\column{0.3\textwidth} - -\begin{itemize} -\item \verb+~+5200 lines total -\item Embeds into Scala well -\end{itemize} - -\column{0.7\textwidth} - -\begin{center} -\includegraphics[width=0.9\textwidth]{figs/linecount.png} -\end{center} - -\end{columns} - -\end{frame} - -\begin{frame} -\frametitle {Chisel versus Hand-Coded Verilog} - -\begin{itemize} -\item 3-stage RISCV CPU hand-coded in Verilog -\item Translated to Chisel -\item Resulted in 3x reduction in lines of code -\item Most savings in wiring -\item Lots more savings to go ... -% \item Chisel-generated Verilog gives comparable synthesis quality of results -\end{itemize} - -\end{frame} - -\begin{frame}[fragile] -\frametitle{Process Language} - -\begin{columns} - -\column{0.5\textwidth} - -Composeable State Machines -\begin{scala} -Do{ ... } -Exec(c){ a } / Exec{ a } -Stop -Skip / Wait(n) -Seq(a, ...) -Par(a, ...) -Alt(c, a1, a2) -While(c){ a } / Loop{ a } -\end{scala} - -Each process block uses a \verb+when+ -\begin{scala} -when (io.start) { ... } -\end{scala} -to ensure that state updates are updated only when process execute. - -\column{0.45\textwidth} - -\begin{center} -\includegraphics[width=0.9\textwidth]{figs/process.pdf} \\ -\end{center} - -\end{columns} - -\end{frame} - -\begin{frame}[fragile, shrink] -\frametitle{Process Language Example} - -\begin{scala} -class Multiply extends Component { - val io = new Bundle{ - val start = Bool(INPUT); - val x = UFix(dir = INPUT, width = 32) - val y = UFix(dir = INPUT, width = 32) - val z = UFix(dir = OUTPUT, width = 32) - val finish = Bool(OUTPUT) } - val a = Reg(){ UFix(0, 32) } - val b = Reg(){ UFix(0, 32) } - val acc = Reg(){ UFix(0, 32) } - val finish = - Exec(io.start) { - Seq(Do{ a := io.x; b := io.y; acc := UFix(0, 32) }, - While(b != UFix(0, 32)) { - Do{ a := (a << UFix(1)) - b := (b >> UFix(1)) - acc := Mux(b(0) === Bits(1), acc+a, acc) } }) - } - io.finish := finish - io.z := acc -} -\end{scala} - -\end{frame} - -\begin{frame}[fragile] -\frametitle{Transactors and Beyond} -\begin{columns} -\column{0.53\textwidth} -{\lstset{basicstyle={\scriptsize\ttfamily}} -\begin{scala} -class Router extends Transactor { - val n = 2 - val io = new RouterIO(n) - val tbl = Mem(32){ UFix(width = sizeof(n)) } - defRule("rd") { - val cmd = io.reads.deq() - io.replies.enq(tbl.read(cmd.addr)) - } - defRule("wr") { - val cmd = io.writes.deq() - tbl.write(cmd.addr, cmd.data) - } - defRule("rt") { - val pkt = io.in.deq() - io.outs(tbl.read(pkt.header)).enq(pkt) - } -} -\end{scala} -} -\column{0.42\textwidth} -\includegraphics[width=0.99\textwidth]{figs/trouter.pdf} -\end{columns} - -\end{frame} - -% \begin{frame}{Related Work} -% -% \begin{itemize} -% \item SystemVerilog -% \begin{itemize} -% \item Lacks general purpose programming and extensibility -% \end{itemize} -% \item Lava -% \begin{itemize} -% \item Elegant but focus on spatial layout -% \end{itemize} -% \item Domain specific (bluespec + esterel + autoesl) -% \begin{itemize} -% \item Powerful but needs to match task at hand -% \end{itemize} -% \item Generator language (Genesis2 + spiralFFT) -% \begin{itemize} -% \item Either inherit poor abstraction qualities of underlying HDL or -% \item Do not provide complete solution -% \end{itemize} -% \end{itemize} -% -% \end{frame} - -\begin{frame}[fragile] -\frametitle{Rocket Microarchitecture} -\begin{itemize} -\item 6-stage RISC decoupled integer datapath + 5-stage IEEE FPU + MMU - and non-blocking caches -\item Completely written in Chisel -\end{itemize} -\includegraphics[width=\textwidth]{figs/rocket-microarchitecture.pdf} - -\end{frame} - -\begin{frame}[fragile] -\frametitle{Single Source / Multiple Targets} - -\begin{center} -single source \\ -\includegraphics[width=0.95\textwidth]{../manual/figs/targets.pdf} \\ -multiple targets \ -\end{center} - -\end{frame} - - -\begin{frame}[fragile] -\frametitle{Fast Cycle-Accurate Simulation in C++} - -\begin{itemize} -\item Compiles to single class -\begin{itemize} -\item Keep state and top level io in class fields -\item \verb+clock_lo+ and \verb+clock_hi+ methods -\end{itemize} -\item Generates calls to fast multiword library using C++ templates -\begin{itemize} -\item specializing for small word cases -\item remove branching as much as possible to utilize maximum ILP in processor -\end{itemize} -\end{itemize} - -\end{frame} - -\begin{frame}[fragile] -\frametitle{Simulator Comparison} - -\textbf{Comparison of simulation time when booting Tessellation OS} -\vskip0.5cm - -\begin{footnotesize} -\begin{tabular}{lrrrrrr} -\textbf{Simulator} & \textbf{Compile} & \textbf{Compile} & \textbf{Run} & \textbf{Run} & \textbf{Total} & \textbf{Total} \\ -& \textbf{Time (s)} & \textbf{Speedup} & \textbf{Time (s)} & \textbf{Speedup} & \textbf{Time (s)} & \textbf{Speedup} \\ -\hline -VCS & 22 & 1.000 & 5368 & 1.00 & 5390 & 1.00 \\ -Chisel C++ & 119 & 0.184 & 575 & 9.33 & 694 & 7.77\\ -Virtex-6 & 3660 & 0.006 & 76 & 70.60 & 3736 & 1.44\\ -\end{tabular} -\end{footnotesize} - - -\end{frame} - -\begin{frame} -\frametitle{Simulation Crossover Points} - -% \begin{columns} -% \begin{tabular}{ll} -% \textbf{Simulation} & \textbf{Worth it if ...} \\ -% \hline -% Chisel C++ & millions of cycles \\ -% FPGA & billions of cycles \\ -% \end{tabular} -% -% \column{0.55\textwidth} - -\begin{center} -\includegraphics[height=0.8\textheight]{figs/perf.pdf} -\end{center} - -% \end{columns} - -\end{frame} - -\begin{frame}[fragile] -\frametitle{Data Parallel Processor Tape Out Results} - -\begin{center} -Completely written in Chisel -\includegraphics[height=0.7\textheight]{figs/ibm45.png} - -\begin{footnotesize} -The data-parallel processor layout results using IBM 45nm SOI 10-metal layer process using memory compiler generated 6T and 8T SRAM blocks. -\end{footnotesize} -\end{center} - -\end{frame} - -\begin{frame}[fragile] -\frametitle{Products} - -\begin{itemize} -\item Open source with BSD license -\begin{itemize} -\item \verb+chisel.eecs.berkeley.edu+ -\item complete set of documentation -\item bootcamp / release june 8, 2012 -\end{itemize} -\item Library of components -\begin{itemize} -\item queues, decoders, encoders, popcount, scoreboards, integer ALUs, LFSR, Booth multiplier, iterative divider, ROMs, RAMs, CAMs, TLB, caches, prefetcher, fixed-priority arbiters, round-robin arbiters, IEEE-754/2008 floating-point units -\end{itemize} -\item Set of educational processors including: -\begin{itemize} -\item microcoded processor, one-stage, two-stage, and five-stage pipelines, and an out-of-order processor, all with accompanying visualizations. -\end{itemize} -\end{itemize} - -\end{frame} - -\begin{frame}[fragile] -\frametitle{Future} - -\begin{itemize} -\item Automated design space exploration -\item Insertion of activity counters for power monitors -\item Automatic fault insertion -\item Faster and more scalable simulation -\item More generators -\item More little languages -\item Compilation to UCLID -\end{itemize} - -\end{frame} - - -\end{document} diff --git a/doc/tutorial/tutorial.tex b/doc/tutorial/tutorial.tex deleted file mode 100644 index 4ddb7a05..00000000 --- a/doc/tutorial/tutorial.tex +++ /dev/null @@ -1,2073 +0,0 @@ -\documentclass[twocolumn,10pt]{article} -\setlength\textwidth{6.875in} -\setlength\textheight{8.875in} -% set both margins to 2.5 pc -\setlength{\oddsidemargin}{-0.1875in}% 1 - (8.5 - 6.875)/2 -\setlength{\evensidemargin}{-0.1875in} -\setlength{\marginparwidth}{0pc} -\setlength{\marginparsep}{0pc}% -\setlength{\topmargin}{0in} \setlength{\headheight}{0pt} -\setlength{\headsep}{0pt} -\setlength{\footskip}{37pt}% -%\setlength{\columnsep}{0.3125in} -%\setlength{\columnwidth}{3.28125in}% (6.875 - 0.3125)/2 = 3.28125in -\setlength{\parindent}{1pc} -\newcommand{\myMargin}{1.00in} -\usepackage[top=\myMargin, left=\myMargin, right=\myMargin, bottom=\myMargin, nohead]{geometry} -\usepackage{epsfig,graphicx} -\usepackage{palatino} -\usepackage{fancybox} -\usepackage{url} -\usepackage[procnames]{listings} - -\input{../style/scala.tex} - -\lstset{frame=, basicstyle={\footnotesize\ttfamily}} - -\newcommand{\todo}[1]{\emph{TODO: #1}} -\newcommand{\comment}[1]{\emph{Comment: #1}} - -% uncomment following for final submission -\renewcommand{\todo}[1]{} -\renewcommand{\comment}[1]{} - -\newenvironment{commentary} -{ \vspace{-0.1in} - \begin{quotation} - \noindent - \small \em - \rule{\linewidth}{1pt}\\ -} -{ - \end{quotation} -} - -% \newenvironment{kode}% -% {\footnotesize -% %\setlength{\parskip}{0pt} -% %\setlength{\topsep}{0pt} -% %\setlength{\partopsep}{0pt} -% \verbatim} -% {\endverbatim -% %\vspace*{-0.1in} -% } - -% \newenvironment{kode}% -% {\VerbatimEnvironment -% \footnotesize\begin{Sbox}\begin{minipage}{6in}\begin{Verbatim}}% -% {\end{Verbatim}\end{minipage}\end{Sbox} -% \setlength{\fboxsep}{8pt}\fbox{\TheSbox}} - -% \newenvironment{kode} -% {\begin{Sbox} -% \footnotesize -% \begin{minipage}{6in} -% %\setlength{\parskip}{0pt} -% %\setlength{\topsep}{0pt} -% %\setlength{\partopsep}{0pt} -% \verbatim} -% {\endverbatim -% \end{minipage} -% \end{Sbox} -% \fbox{\TheSbox} -% %\vspace*{-0.1in} -% } - -\title{Chisel 2.2 Tutorial} -\author{Jonathan Bachrach, Krste Asanovi\'{c}, John Wawrzynek \\ -EECS Department, UC Berkeley\\ -{\tt \{jrb|krste|johnw\}@eecs.berkeley.edu} -} -\date{\today} - -\newenvironment{example}{\VerbatimEnvironment\begin{footnotesize}\begin{Verbatim}}{\end{Verbatim}\end{footnotesize}} -\newcommand{\kode}[1]{\begin{footnotesize}{\tt #1}\end{footnotesize}} - -\def\code#1{{\tt #1}} - -\def\note#1{\noindent{\bf [Note: #1]}} -%\def\note#1{} - -\begin{document} -\maketitle{} - -% TODO: default -% TODO: enum yields Bits -% TODO: why hardware construction languages - -\section{Introduction} - -This document is a tutorial introduction to {\em Chisel} (Constructing -Hardware In a Scala Embedded Language). Chisel is a hardware -construction language embedded in the high-level programming language -Scala. At some point we will provide a proper reference manual, in -addition to more tutorial examples. In the meantime, this document -along with a lot of trial and error should set you on your way to -using Chisel. Chisel is really only a set of special class -definitions, predefined objects, and usage conventions within Scala, -so when you write a Chisel program you are actually writing a Scala -program. However, for the tutorial we don't presume that you -understand how to program in Scala. We will point out necessary Scala -features through the Chisel examples we give, and significant hardware -designs can be completed using only the material contained herein. -But as you gain experience and want to make your code simpler or more -reusable, you will find it important to leverage the underlying power -of the Scala language. We recommend you consult one of the excellent -Scala books to become more expert in Scala programming. - -Chisel is still in its infancy and you are likely to encounter some -implementation bugs, and perhaps even a few conceptual design -problems. However, we are actively fixing and improving the language, -and are open to bug reports and suggestions. Even in its early state, -we hope Chisel will help designers be more productive in building -designs that are easy to reuse and maintain. - -\begin{commentary} -Through the tutorial, we format commentary on our design choices as in -this paragraph. You should be able to skip the commentary sections -and still fully understand how to use Chisel, but we hope you'll find -them interesting. - -We were motivated to develop a new hardware language by years of -struggle with existing hardware description languages in our research -projects and hardware design courses. Verilog and VHDL were developed -as hardware {\em simulation} languages, and only later did they become -a basis for hardware {\em synthesis}. Much of the semantics of these -languages are not appropriate for hardware synthesis and, in fact, -many constructs are simply not synthesizable. Other constructs are -non-intuitive in how they map to hardware implementations, or their -use can accidently lead to highly inefficient hardware structures. -While it is possible to use a subset of these languages and yield -acceptable results, they nonetheless present a cluttered and confusing -specification model, particularly in an instructional setting. - -However, our strongest motivation for developing a new hardware -language is our desire to change the way that electronic system design -takes place. We believe that it is important to not only teach -students how to design circuits, but also to teach them how to design -{\em circuit generators}---programs that automatically generate -designs from a high-level set of design parameters and constraints. -Through circuit generators, we hope to leverage the hard work of -design experts and raise the level of design abstraction for everyone. -To express flexible and scalable circuit construction, circuit -generators must employ sophisticated programming techniques to make -decisions concerning how to best customize their output circuits -according to high-level parameter values and constraints. While -Verilog and VHDL include some primitive constructs for programmatic -circuit generation, they lack the powerful facilities present in -modern programming languages, such as object-oriented programming, -type inference, support for functional programming, and reflection. - -Instead of building a new hardware design language from scratch, we -chose to embed hardware construction primitives within an existing -language. We picked Scala not only because it includes the -programming features we feel are important for building circuit -generators, but because it was specifically developed as a base for -domain-specific languages. -\end{commentary} - -\section{Hardware expressible in Chisel} - -% The initial version of Chisel only supports the expression of -% synchronous RTL (Register-Transfer Level) designs, with a single -% common clock. Synchronous RTL circuits can be expressed as a -% hierarchical composition of modules containing combinational logic and -% clocked state elements. Although Chisel assumes a single global -% clock, local clock gating logic is automatically generated for every -% state element in the design to save power. -% \begin{commentary} -% Modern hardware designs often include multiple islands of logic, where -% each island uses a different clock and where islands must correctly -% communicate across clock island boundaries. Although clock-crossing -% synchronization circuits are notoriously difficult to design, there -% are known good solutions for most scenarios, which can be packaged as -% library elements for use by designers. As a result, most effort in -% new designs is spent in developing and verifying the functionality -% within each synchronous island rather than on passing values between -% islands. -% -% In its current form, Chisel can be used to describe each of the -% synchronous islands individually. Existing tool frameworks can tie -% together these islands into a complete design. For example, a -% separate outer simulation framework can be used to model the assembly -% of islands running together. It should be noted that exhaustive -% dynamic verification of asynchronous communications is usually -% impossible and that more formal static approaches are usually -% necessary. -% \end{commentary} - -This version of Chisel also only supports binary logic, and does not -support tri-state signals. -\begin{commentary} -We focus on binary logic designs as they constitute the vast majority -of designs in practice. We omit support for tri-state logic in the -current Chisel language as this is in any case poorly supported by -industry flows, and difficult to use reliably outside of controlled -hard macros. -\end{commentary} - -\section{Datatypes in Chisel} - -Chisel datatypes are used to specify the type of values held in state -elements or flowing on wires. While hardware designs ultimately -operate on vectors of binary digits, other more abstract -representations for values allow clearer specifications and help the -tools generate more optimal circuits. In Chisel, a raw collection of -bits is represented by the \code{Bits} type. Signed and unsigned integers -are considered subsets of fixed-point numbers and are represented by -types \code{SInt} and \code{UInt} respectively. Signed fixed-point -numbers, including integers, are represented using two's-complement -format. Boolean values are represented as type \code{Bool}. Note -that these types are distinct from Scala's builtin types such as -\code{Int}. Additionally, Chisel defines {\em Bundles} for making -collections of values with named fields (similar to {\em structs} in -other languages), and {\em Vecs} for indexable collections of -values. Bundles and Vecs will be covered later. - -Constant or literal values are expressed using Scala integers or -strings passed to constructors for the types: -\begin{scala} -UInt(1) // decimal 1-bit lit from Scala Int. -UInt("ha") // hexadecimal 4-bit lit from string. -UInt("o12") // octal 4-bit lit from string. -UInt("b1010") // binary 4-bit lit from string. - -SInt(5) // signed decimal 4-bit lit from Scala Int. -SInt(-8) // negative decimal 4-bit lit from Scala Int. -UInt(5) // unsigned decimal 3-bit lit from Scala Int. - -Bool(true) // Bool lits from Scala lits. -Bool(false) -\end{scala} - -Underscores can be used as separators in long string literals to aid -readability, but are ignored when creating the value, e.g.: -\begin{scala} -UInt("h_dead_beef") // 32-bit lit of type UInt -\end{scala} - -By default, the Chisel compiler will size each constant to the minimum -number of bits required to hold the constant, including a sign bit for -signed types. Bit widths can also be specified explicitly on -literals, as shown below: -\begin{scala} -UInt("ha", 8) // hexadecimal 8-bit lit of type UInt -UInt("o12", 6) // octal 6-bit lit of type UInt -UInt("b1010", 12) // binary 12-bit lit of type UInt - -SInt(5, 7) // signed decimal 7-bit lit of type SInt -UInt(5, 8) // unsigned decimal 8-bit lit of type UInt -\end{scala} - -\noindent -For literals of type \code{UInt}, the value is -zero-extended to the desired bit width. For literals of type -\code{SInt}, the value is sign-extended to fill the desired bit width. -If the given bit width is too small to hold the argument value, then a -Chisel error is generated. - -\begin{commentary} -We are working on a more concise literal syntax for Chisel using -symbolic prefix operators, but are stymied by the limitations of Scala -operator overloading and have not yet settled on a syntax that is -actually more readable than constructors taking strings. - -We have also considered allowing Scala literals to be automatically -converted to Chisel types, but this can cause type ambiguity and -requires an additional import. - -The SInt and UInt types will also later support an optional exponent -field to allow Chisel to automatically produce optimized fixed-point -arithmetic circuits. -\end{commentary} - -\section{Combinational Circuits} - -A circuit is represented as a graph of nodes in Chisel. Each node is -a hardware operator that has zero or more inputs and that drives one -output. A literal, introduced above, is a degenerate kind of node -that has no inputs and drives a constant value on its output. One way -to create and wire together nodes is using textual expressions. For -example, we could express a simple combinational logic circuit -using the following expression: - -\begin{scala} -(a & b) | (~c & d) -\end{scala} - -The syntax should look familiar, with \code{\&} and \code{|} -representing bitwise-AND and -OR respectively, and \code{\~{}} -representing bitwise-NOT. The names \code{a} through \code{d} -represent named wires of some (unspecified) width. - -Any simple expression can be converted directly into a circuit tree, -with named wires at the leaves and operators forming the internal -nodes. The final circuit output of the expression is taken from the -operator at the root of the tree, in this example, the bitwise-OR. - -Simple expressions can build circuits in the shape of trees, but to -construct circuits in the shape of arbitrary directed acyclic graphs -(DAGs), we need to describe fan-out. In Chisel, we do this by naming -a wire that holds a subexpression that we can then reference multiple -times in subsequent expressions. We name a wire in Chisel by -declaring a variable. For example, consider the select expression, -which is used twice in the following multiplexer description: -\begin{scala} -val sel = a | b -val out = (sel & in1) | (~sel & in0) -\end{scala} - -\noindent -The keyword \code{val} is part of Scala, and is used to name variables -that have values that won't change. It is used here to name the -Chisel wire, \code{sel}, holding the output of the first bitwise-OR -operator so that the output can be used multiple times in the second -expression. - -\section{Builtin Operators} - -Chisel defines a set of hardware operators for the builtin types shown -in Table~\ref{tbl:chisel-operators}. -\begin{table*} -\begin{center} -\begin{tabular}{|l|l|} -\hline -Example & Explanation \\ -\hline -\hline -\multicolumn{2}{|l|}{Bitwise operators. Valid on SInt, UInt, Bool.} \\ -\hline -\hline -\verb!val invertedX = ~x! & Bitwise NOT \\ -\verb!val hiBits = x & UInt("h_ffff_0000") ! & Bitwise AND \\ -\verb!val flagsOut = flagsIn | overflow ! & Bitwise OR \\ -\verb!val flagsOut = flagsIn ^ toggle ! & Bitwise XOR \\ -\hline -\hline -\multicolumn{2}{|l|}{Bitwise reductions. Valid on SInt and - UInt. Returns Bool. } \\ -\hline -\hline -\verb!val allSet = andR(x) ! & AND reduction \\ -\verb!val anySet = orR(x) ! & OR reduction \\ -\verb!val parity = xorR(x) ! & XOR reduction \\ -\hline -\hline -\multicolumn{2}{|l|}{Equality comparison. Valid on SInt, -UInt, and Bool. Returns Bool.} \\ -\hline -\hline -\verb@val equ = x === y@ & Equality \\ -\verb@val neq = x != y@ & Inequality \\ -\hline -\hline -\multicolumn{2}{|l|}{Shifts. Valid on SInt and UInt.} \\ -\hline -\hline -\verb@val twoToTheX = SInt(1) << x@ & Logical left shift. \\ -\verb@val hiBits = x >> UInt(16)@ & Right shift (logical on UInt and\& -arithmetic on SInt). \\ -% \verb@val scaledX = x >>> 3@ & Arithmetic right shift, copies in sign bits. \\ -\hline -\hline -\multicolumn{2}{|l|}{Bitfield manipulation. Valid on SInt, UInt, and Bool. } \\ -\hline -\hline -\verb@val xLSB = x(0)@ & Extract single bit, LSB has index 0. \\ -\verb@val xTopNibble = x(15,12)@ & Extract bit field from end to start -bit position. \\ -\verb@val usDebt = Fill(3, UInt("hA"))@ & Replicate a bit string multiple times. \\ -\verb@val float = Cat(sign,exponent,mantissa)@ & Concatenates bit fields, with first argument on left.\\ -\hline -\hline -\multicolumn{2}{|l|}{Logical operations. Valid on Bools. } \\ -\hline -\verb@val sleep = !busy@ & Logical NOT \\ -\verb@val hit = tagMatch && valid @ & Logical AND \\ -\verb@val stall = src1busy || src2busy@ & Logical OR \\ -\verb@val out = Mux(sel, inTrue, inFalse)@ & Two-input mux where sel is a Bool \\ % {\bf Why?} \\ -\hline -\hline -\multicolumn{2}{|l|}{Arithmetic operations. Valid on Nums: SInt and UInt. } \\ -\hline -\verb@val sum = a + b@ & Addition \\ -\verb@val diff = a - b @ & Subtraction \\ -\verb@val prod = a * b @ & Multiplication \\ -\verb@val div = a / b @ & Division \\ -\verb@val mod = a % b @ & Modulus \\ -\hline -\hline -\multicolumn{2}{|l|}{Arithmetic comparisons. Valid on Nums: SInt and - UInt. Returns Bool.} \\ -\hline -\verb@val gt = a > b@ & Greater than \\ -\verb@val gte = a >= b@ & Greater than or equal \\ -\verb@val lt = a < b@ & Less than \\ -\verb@val lte = a <= b@ & Less than or equal \\ -\hline -\end{tabular} -\end{center} -\caption{Chisel operators on builtin data types.} -\label{tbl:chisel-operators} -\end{table*} - -\subsection{Bitwidth Inference} - -Users are required to set bitwidths of ports and registers, but otherwise, -bit widths on wires are automatically inferred unless set manually by the user. -% TODO: how do you set the width explicitly? -The bit-width inference engine starts from the graph's input ports and -calculates node output bit widths from their respective input bit widths according to the following set of rules: - -\begin{tabular}{ll} -{\bf operation} & {\bf bit width} \\ -\verb|z = x + y| & \verb|wz = max(wx, wy)| \\ -\verb+z = x - y+ & \verb|wz = max(wx, wy)|\\ -\verb+z = x & y+ & \verb+wz = min(wx, wy)+ \\ -\verb+z = Mux(c, x, y)+ & \verb+wz = max(wx, wy)+ \\ -\verb+z = w * y+ & \verb!wz = wx + wy! \\ -\verb+z = x << n+ & \verb!wz = wx + maxNum(n)! \\ -\verb+z = x >> n+ & \verb+wz = wx - minNum(n)+ \\ -\verb+z = Cat(x, y)+ & \verb!wz = wx + wy! \\ -\verb+z = Fill(n, x)+ & \verb+wz = wx * maxNum(n)+ \\ -% \verb+z = x < y+ & \verb+<= > >= && || != ===+ & \verb+wz = 1+ \\ -\end{tabular} - -\noindent -where for instance $wz$ is the bit width of wire $z$, and the \verb+&+ -rule applies to all bitwise logical operations. - -\comment{maxNum and MinNum need to be explained.} - -The bit-width inference process continues until no bit width changes. -Except for right shifts by known constant amounts, the bit-width -inference rules specify output bit widths that are never smaller than -the input bit widths, and thus, output bit widths either grow or stay -the same. Furthermore, the width of a register must be specified by -the user either explicitly or from the bitwidth of the reset value. -From these two requirements, we can show that the bit-width inference -process will converge to a fixpoint. - -\begin{commentary} -Our choice of operator names was constrained by the Scala language. -We have to use triple equals \code{===} for equality to allow the -native Scala equals operator to remain usable. - -We are also planning to add further operators that constrain bitwidth -to the larger of the two inputs. -\end{commentary} - -\section{Functional Abstraction} - -We can define functions to factor out a repeated piece of logic that -we later reuse multiple times in a design. For example, we can wrap -up our earlier example of a simple combinational logic block as -follows: -\begin{scala} -def clb(a: UInt, b: UInt, c: UInt, d: UInt) = - (a & b) | (~c & d) -\end{scala} - -\noindent -where \code{clb} is the function which takes \code{a}, \code{b}, -\code{c}, \code{d} as arguments and returns a wire to the output of a -boolean circuit. The \code{def} keyword is part of Scala and -introduces a function definition, with each argument followed by a colon then its type, -and the function return type given after the colon following the -argument list. The equals (\code{=}) -sign separates the function argument list from the function -definition. - -We can then use the block in another circuit as follows: -\begin{scala} -val out = clb(a,b,c,d) -\end{scala} - -% TODO: SHIFTER DONE FUNCTIONAL WITH LOOP - -%% Because Scala has powerful type inference, we can in many cases drop -%% the type declarations on the function: -%% \begin{scala} -%% def clb(a, b, c, d) = (a & b) | (~c & d) // No types needed. - -%% def bigblock(a: Bool, b: Bool, c: Bool, d: Bool, -%% f: UInt, g: UInt, h: UInt, i: UInt): Bool = -%% clb(a, b, c, clb(f,g,h,i)!=0) - -%% \end{scala} - -%% Here, we use \code{clb} twice. The inner \verb!clb! works with -%% fixed-point values to calculate the value of an internal node that is -%% compared with 0 to give a \code{Bool}, while the outer \verb!clb! -%% works with \code{Bool} values and returns the result of the -%% function. Scala will perform type inference statically to check -%% that there are no type errors. - -We will later describe many powerful ways to use functions to -construct hardware using Scala's functional programming support. - -\section{Bundles and Vecs} - -\code{Bundle} and \code{Vec} are classes that allow the user to expand -the set of Chisel datatypes with aggregates of other types. - -Bundles group together several named fields of potentially different -types into a coherent unit, much like a \code{struct} in C. Users -define their own bundles by defining a class as a subclass of -\code{Bundle}: -\begin{scala} -class MyFloat extends Bundle { - val sign = Bool() - val exponent = UInt(width = 8) - val significand = UInt(width = 23) -} - -val x = new MyFloat() -val xs = x.sign -\end{scala} - -\noindent -A Scala convention is to capitalize the name of new classes and we -suggest you follow that convention in Chisel too. The \code{width} -named parameter to the \code{UInt} constructor specificies the number -of bits in the type. - -Vecs create an indexable vector of elements, and are constructed as -follows: -\begin{scala} -// Vector of 5 23-bit signed integers. -val myVec = Vec.fill(5){ SInt(width = 23) } - -// Connect to one element of vector. -val reg3 = myVec(3) -\end{scala} - -\noindent -(Note that we have to specify the type of the \code{Vec} elements -inside the trailing curly brackets, as we have to pass the bitwidth -parameter into the \code{SInt} constructor.) - -The set of primitive classes -(\code{SInt}, \code{UInt}, and \code{Bool}) plus the aggregate -classes (\code{Bundles} and \code{Vec}s) all inherit from a common -superclass, \code{Data}. Every object that ultimately inherits from -\code{Data} can be represented as a bit vector in a hardware design. - -Bundles and Vecs can be arbitrarily nested to build complex data -structures: -\begin{scala} -class BigBundle extends Bundle { - // Vector of 5 23-bit signed integers. - val myVec = Vec.fill(5) { SInt(width = 23) } - val flag = Bool() - // Previously defined bundle. - val f = new MyFloat() -} -\end{scala} - -\noindent -Note that the builtin Chisel primitive and aggregate classes do not -require the \code{new} when creating an instance, whereas new user -datatypes will. A Scala \code{apply} constructor can be defined so -that a user datatype also does not require \code{new}, as described in -Section~\ref{sec:funconstructor}. - -\section{Ports} - -Ports are used as interfaces to hardware components. A port is simply -any \code{Data} object that has directions assigned to its members. - -Chisel provides port constructors to allow a direction to be added -(input or output) to an object at construction time. Primitive port -constructors take the direction as the first -argument (where the direction is \code{INPUT} or -\code{OUTPUT}) and the number of bits as the second argument (except -booleans which are always one bit). - -An example port declaration is as follows: -\begin{scala} -class Decoupled extends Bundle { - val ready = Bool(OUTPUT) - val data = UInt(INPUT, 32) - val valid = Bool(INPUT) -} -\end{scala} - -\noindent -After defining \code{Decoupled}, it becomes a new type that can be -used as needed for module interfaces or for named collections of -wires. - -The direction of an object can also be assigned at instantation time: -\begin{scala} -class ScaleIO extends Bundle { - val in = new MyFloat().asInput - val scale = new MyFloat().asInput - val out = new MyFloat().asOutput -} -\end{scala} - -\noindent -The methods \code{asInput} and \code{asOutput} force all modules of -the data object to the requested direction. - -By folding directions into the object declarations, Chisel is able to -provide powerful wiring constructs described later. -%% \begin{scala} -%% class MuxBundle extends Bundle { -%% val sel = UInt(INPUT, 1) -%% val in0 = UInt(INPUT, 1) -%% val in1 = UInt(INPUT, 1) -%% val out = UInt(OUTPUT, 1) -%% } - -%% class Mux2 extends Module { -%% val io = new MuxBundle() -%% io.out := (io.sel & io.in1) | (~io.sel & io.in0) -%% } -%% \end{scala} - - -\section{Modules} - -Chisel {\em modules} are very similar to Verilog {\em modules} in -defining a hierarchical structure in the generated circuit. -%Like functional generators, we can also parameterize the construction of -%circuits by turning them into object-oriented modules. Unlike -%functional generators, modules also provide a coarse hierarchy on a -%circuit and permit a level of generator abstraction that is often -%useful. -The hierarchical module namespace is accessible in downstream tools -to aid in debugging and physical layout. A user-defined module is -defined as a {\em class} which: -\begin{itemize} -\item inherits from \code{Module}, -\item contains an interface stored in a port field named \code{io}, and -\item wires together subcircuits in its constructor. -\end{itemize} -As an example, consider defining your own two-input multiplexer as a -module: -\begin{scala} -class Mux2 extends Module { - val io = new Bundle{ - val sel = UInt(INPUT, 1) - val in0 = UInt(INPUT, 1) - val in1 = UInt(INPUT, 1) - val out = UInt(OUTPUT, 1) - } - io.out := (io.sel & io.in1) | (~io.sel & io.in0) -} -\end{scala} - -\noindent -The wiring interface to a module is a collection of ports in the -form of a \code{Bundle}. The interface to the module is defined -through a field named \code{io}. For \code{Mux2}, \code{io} is -defined as a bundle with four fields, one for each multiplexer port. - -The \code{:=} assignment operator, used here in the body of the -definition, is a special operator in Chisel that wires the input of -left-hand side to the output of the right-hand side. - -\subsection{Module Hierarchy} - -We can now construct circuit hierarchies, where we build larger modules out -of smaller sub-modules. For example, we can build a 4-input -multiplexer module in terms of the \code{Mux2} module by wiring -together three 2-input multiplexers: - -\begin{scala} -class Mux4 extends Module { - val io = new Bundle { - val in0 = UInt(INPUT, 1) - val in1 = UInt(INPUT, 1) - val in2 = UInt(INPUT, 1) - val in3 = UInt(INPUT, 1) - val sel = UInt(INPUT, 2) - val out = UInt(OUTPUT, 1) - } - val m0 = Module(new Mux2()) - m0.io.sel := io.sel(0) - m0.io.in0 := io.in0; m0.io.in1 := io.in1 - - val m1 = Module(new Mux2()) - m1.io.sel := io.sel(0) - m1.io.in0 := io.in2; m1.io.in1 := io.in3 - - val m3 = Module(new Mux2()) - m3.io.sel := io.sel(1) - m3.io.in0 := m0.io.out; m3.io.in1 := m1.io.out - - io.out := m3.io.out -} -\end{scala} - -\noindent -We again define the module interface as \code{io} and wire up the -inputs and outputs. In this case, we create three \code{Mux2} -children modules, using the \code{Module} constructor function and -the Scala \code{new} keyword to create a -new object. We then wire them up to one another and to the ports of -the \code{Mux4} interface. - -\section{Running and Testing Examples} - -Now that we have defined modules, we will discuss how we actually run and test a circuit. Chisel translates into either \verb@C++@ or Verilog. In order to build a circuit we need to call \code{chiselMain}: - -\begin{scala} -object tutorial { - def main(args: Array[String]) = { - chiselMain(args, () => Module(new Mux2())) - } -} -\end{scala} - -\begin{figure} -\begin{center} -\includegraphics[width=0.45\textwidth]{../tutorial/figs/DUT.pdf} -\end{center} -\caption{DUT run using a Tester object in Scala with stdin and stdout connected} -\label{fig:dut} -\end{figure} - -Testing is a crucial part of circuit design, -and thus in Chisel we provide a mechanism for -testing circuits by providing test vectors within Scala using -subclasses of the \code{Tester} class: - -\begin{scala} -class Tester[T <: Module] (val c: T, val isTrace: Boolean = true) { - var t: Int - var ok: Boolean - val rnd: Random - def int(x: Boolean): BigInt - def int(x: Int): BigInt - def int(x: Bits): BigInt - def reset(n: Int = 1) - def step(n: Int): Int - def pokeAt(data: Mem[T], index: Int, x: BigInt) - def poke(data: Bits, x: BigInt) - def poke(data: Aggregate, x: Array[BigInt]) - def peekAt(data: Mem[T], index: Int) - def peek(data: Bits): BigInt - def peek(data: Aggregate): Array[BigInt] - def expect (good: Boolean, msg: String): Boolean - def expect (data: Bits, target: BigInt): Boolean -} -\end{scala} - -\noindent -which binds a tester to a module -and allows users to write tests using the given debug protocol. In particular, users utilize: -\begin{itemize} -\item \code{poke} to set input port and state values, -\item \code{step} to execute the circuit one time unit, -\item \code{peek} to read port and state values, and -\item \code{expect} to compare peeked circuit values to expected arguments. -\end{itemize} - -\noindent -Users connect tester instances to modules using: - - -\begin{scala} -object chiselMainTest { - def apply[T <: Module] - (args: Array[String], comp: () => T)( - tester: T => Tester[T]): T -} -\end{scala} - -\noindent -When \code{-{-}test} is given as an argument to \code{chiselMainTest}, a -tester instance runs the Design Under Test (DUT) in a separate -process with \code{stdin} and \code{stdout} connected so that debug commands can -be sent to the DUT and responses can be received from the DUT as shown in -Figure~\ref{fig:dut}. -\noindent - -For example, in the following: - -\begin{scala} -class Mux2Tests(c: Mux2) extends Tester(c) { - val n = pow(2, 3).toInt - for (s <- 0 until 2) { - for (i0 <- 0 until 2) { - for (i1 <- 0 until 2) { - poke(c.io.sel, s) - poke(c.io.in1, i1) - poke(c.io.in0, i0) - step(1) - expect(c.io.out, (if (s == 1) i1 else i0)) - } - } - } -} -\end{scala} - -\noindent -assignments for each input of \verb+Mux2+ is set to the appropriate values using \verb+poke+. For this particular example, we are testing the \verb+Mux2+ by hardcoding the inputs to some known values and checking if the output corresponds to the known one. To do this, on each iteration we generate appropriate inputs to the module and tell the simulation to assign these values to the inputs of the device we are testing \verb+c+, step the circuit, and test the expected value. -\comment{Maybe elaborate a little bit what a step does. I assume it is one clock tick -Is a step needed as well for testing plain combinational circuits?} -Finally, the following shows how the tester is invoked: - -\begin{scala} -chiselMainTest(args + "--test", () => Module(new Mux2())){ - c => new Mux2Tests(c) -} -\end{scala} - -Other command arguments are as follows: -\begin{tabular}{lll} -\verb+--targetDir+ & target pathname prefix \\ -\verb+--genHarness+ & generate harness file for C++ \\ -\verb+--backend v+ & generate verilog \\ -\verb+--backend c+ & generate C++ (default)\\ -\verb+--vcd+ & enable vcd dumping \\ -\verb+--debug+ & put all wires in class file \\ -\end{tabular} - -\comment{What does it mean to generate a harness file?} - -\section{State Elements} -\label{sec:sequential} - -% SINGLE CLK and RESET - -The simplest form of state element supported by Chisel is a -positive edge-triggered register, which can be instantiated -as: -\begin{scala} -val reg = Reg(next = in) -\end{scala} - -\noindent -This circuit has an output that is a copy of the input signal \verb+in+ -delayed by one clock cycle. Note that we do not have to specify the -type of \verb+Reg+ as it will be automatically inferred from its input -when instantiated in this way. In the current version of Chisel, -clock and reset are global signals that are implicity included where -needed. - -Using registers, we can quickly define a number of useful circuit -constructs. For example, a rising-edge detector that takes a boolean -signal in and outputs true when the current value is true and the -previous value is false is given by: -\begin{scala} -def risingedge(x: Bool) = x && !Reg(next = x) -\end{scala} - -Counters are an important sequential circuit. To construct an -up-counter that counts up to a maximum value, \verb+max+, then wraps -around back to zero (i.e., modulo \verb!max+1!), we write: -\begin{scala} -def counter(max: UInt) = { - val x = Reg(init = UInt(0, max.getWidth)) - x := Mux(x === max, UInt(0), x + UInt(1)) - x -} -\end{scala} - -\noindent -The counter register is created in the \verb!counter! function -with a reset value of \verb!0! (with width large enough to hold \verb+max+), -to which the register will be initialized when the global reset for the circuit is asserted. -The \verb!:=! assignment to \verb!x! in \verb!counter! wires an update combinational circuit -which increments the counter value unless it hits the \verb+max+ at which point it wraps back to zero. -Note that when \verb!x! appears on the right-hand side of -an assigment, its output is referenced, whereas when on the left-hand -side, its input is referenced. - -Counters can be used to build a number of useful sequential circuits. -For example, we can build a pulse generator by outputting true when -a counter reaches zero: -\begin{scala} -// Produce pulse every n cycles. -def pulse(n: UInt) = counter(n - UInt(1)) === UInt(0) -\end{scala} - -\noindent -A square-wave generator can then be toggled by the pulse train, -toggling between true and false on each pulse: -\begin{scala}[escapechar=@] -// Flip internal state when input true. -def toggle(p: Bool) = { - val x = Reg(init = Bool(false)) - x := Mux(p, !x, x) - x -} - -// Square wave of a given period. -def squareWave(period: UInt) = toggle(pulse(period/2)) -\end{scala} - -\subsection{Forward Declarations} - -Purely combinational circuits cannot have cycles between nodes, and -Chisel will report an error if such a cycle is detected. Because they -do not have cycles, combinational circuits can always be constructed -in a feed-forward manner, by adding new nodes whose inputs are derived -from nodes that have already been defined. Sequential circuits -naturally have feedback between nodes, and so it is sometimes -necessary to reference an output wire before the producing node has -been defined. Because Scala evaluates program statements -sequentially, we allow data nodes to serve as a wire providing -a declaration of a node that can be used immediately, but whose -input will be set later. -For example, in a simple CPU, we need to define the \verb!pcPlus4! -and \verb!brTarget! wires so they can be referenced before defined: -\begin{scala} -val pcPlus4 = UInt() -val brTarget = UInt() -val pcNext = Mux(io.ctrl.pcSel, brTarget, pcPlus4) -val pcReg = Reg(next = pcNext, init = UInt(0, 32)) -pcPlus4 := pcReg + UInt(4) -... -brTarget := addOut -\end{scala} - -\noindent -The wiring operator -\verb!:=! is used to wire up -the connection after \verb!pcReg! and \verb!addOut! are defined. - -\subsection{Conditional Updates} - -In our previous examples using registers, we simply wired their inputs -to combinational logic blocks. When describing the operation of state -elements, it is often useful to instead specify when updates to the -registers will occur and to specify these updates spread across -several separate statements. Chisel provides conditional update rules -in the form of the \code{when} construct to support this style of -sequential logic description. For example, -\begin{scala} -val r = Reg(UInt(16)) -when (c === UInt(0) ) { - r := r + UInt(1) -} -\end{scala} - -\noindent -where register \code{r} is updated at the end of the current clock -cycle only if \verb+c+ is zero. The argument to \code{when} is a -predicate circuit expression that returns a \code{Bool}. The update -block following \code{when} can only contain update statements using -the assignment operator \verb+:=+, simple expressions, and named wires -defined with \code{val}. - -In a sequence of conditional updates, the last conditional update -whose condition is true takes priority. For example, -\begin{scala} -when (c1) { r := UInt(1) } -when (c2) { r := UInt(2) } -\end{scala} - -\noindent -leads to \code{r} being updated according to the following truth table: -\begin{center} -{\small -\begin{tabular}{|c|c|c|l|} -\hline -c1 & c2 & r & \\ -\hline -0 & 0 & r & r unchanged \\ -0 & 1 & 2 & \\ -1 & 0 & 1 & \\ -1 & 1 & 2& c2 takes precedence over c1 \\ -\hline -\end{tabular} -} -\end{center} - -\begin{figure}[h] -\centering -\includegraphics[width=3in]{figs/condupdates.pdf} -\caption{Equivalent hardware constructed for conditional updates. - Each \code{when} statement adds another level of data mux and ORs - the predicate into the enable chain. The compiler effectively adds - the termination values to the end of the chain automatically.} -\label{fig:condupdates} -\end{figure} - -Figure~\ref{fig:condupdates} shows how each conditional update can be -viewed as inserting a mux before the input of a register to select -either the update expression or the previous input according to the -\code{when} predicate. In addition, the predicate is OR-ed into a -firing signal that drives the load enable of the register. The -compiler places initialization values at the beginning of the chain so -that if no conditional updates fire in a clock cycle, the load enable -of the register will be deasserted and the register value will not -change. - -Chisel provides some syntactic sugar for other common forms of -conditional update. The \verb+unless+ construct is the same as -\verb+when+ but negates its condition. In other words, -\begin{scala} -unless (c) { body } -\end{scala} -is the same as -\begin{scala} -when (!c) { body } -\end{scala} - -% The \verb+otherwise+ construct is the same as \verb+when+ with a true -% condition. In other words, -% \begin{scala} -% otherwise { body } -% \end{scala} -% -% \noindent -% is the same as -% \begin{scala} -% when (Bool(true)) { body } -% \end{scala} - -The update block can target multiple registers, and there can be -different overlapping subsets of registers present in different update -blocks. Each register is only affected by conditions in which it -appears. The same is possible for combinational circuits (update -of a \code{Wire}). Note that all combinational -circuits need a default value. For example: -\begin{scala} -r := SInt(3); s := SInt(3) -when (c1) { r := SInt(1); s := SInt(1) } -when (c2) { r := SInt(2) } -\end{scala} - -\noindent -leads to \code{r} and \code{s} being updated according to the -following truth table: -\begin{scala} -c1 c2 r s -0 0 3 3 -0 1 2 3 // r updated in c2 block, s at top level. -1 0 1 1 -1 1 2 1 -\end{scala} - -\begin{commentary} -We are considering adding a different form of conditional update, -where only a single update block will take effect. These atomic -updates are similar to Bluespec guarded atomic actions. -% TODO: when / .elsewhen / .otherwise -\end{commentary} - -Conditional update constructs can be nested and any given block is -executed under the conjunction of all outer nesting conditions. For -example, -\begin{scala} -when (a) { when (b) { body } } -\end{scala} - -\noindent -is the same as: -\begin{scala} -when (a && b) { body } -\end{scala} - -Conditionals can be chained together using -\verb+when+, \verb+.elsewhen+, \verb+.otherwise+ corresponding to -\verb+if+, \verb+else if+ and \verb+else+ in Scala. For example, -\begin{scala} -when (c1) { u1 } -.elsewhen (c2) { u2 } -.otherwise { ud } -\end{scala} -\noindent -is the same as: -\begin{scala} -when (c1) { u1 } -when (!c1 && c2) { u2 } -when (!(c1 || c2)) { ud } -\end{scala} - -We introduce the \code{switch} statement for conditional updates -involving a series of comparisons against a common key. For example, -\begin{scala} -switch(idx) { - is(v1) { u1 } - is(v2) { u2 } -} -\end{scala} - -\noindent -is equivalent to: -\begin{scala} -when (idx === v1) { u1 } -.elsewhen (idx === v2) { u2 } -\end{scala} - -Chisel also allows a \code{Wire}, i.e., the output of some -combinational logic, to be the target of conditional update statements -to allow complex combinational logic expressions to be built -incrementally. Chisel does not allow a combinational output to be -incompletely specified and will report an error if an unconditional -update is not encountered for a combinational output. -\begin{commentary} -In Verilog, if a procedural specification of a combinational logic -block is incomplete, a latch will silently be inferred causing many -frustrating bugs. - -It could be possible to add more analysis to the Chisel compiler, to -determine if a set of predicates covers all possibilities. But for -now, we require a single predicate that is always true in the -chain of conditional updates to a \code{Wire}. -\end{commentary} - - -\subsection{Finite State Machines} - -A common type of sequential circuit used in digital design is a Finite -State Machine (FSM). An example of a simple FSM is a parity -generator: - -% \begin{scala} -% class Parity extends Module { -% val io = new Bundle { -% val in = Bool(INPUT) -% val out = Bool(OUTPUT) } -% val s_even :: s_odd :: Nil = Enum(2, UInt()) -% val state = Reg(init = s_even) -% switch(state, Array( -% (s_even, () => { when (io.in) { state := s_odd } }), -% (s_odd, () => { when (io.in) { state := s_even } }) )) -% io.out := state === s_odd -% } -% \end{scala} - -\begin{scala} -class Parity extends Module { - val io = new Bundle { - val in = Bool(dir = INPUT) - val out = Bool(dir = OUTPUT) } - val s_even :: s_odd :: Nil = Enum(UInt(), 2) - val state = Reg(init = s_even) - when (io.in) { - when (state === s_even) { state := s_odd } - when (state === s_odd) { state := s_even } - } - io.out := (state === s_odd) -} -\end{scala} - -\noindent -where \verb+Enum(UInt(), 2)+ generates two \verb+UInt+ literals and -where the states are updated when \verb+in+ is true. It is worth -noting that all of the mechanisms for FSMs are built upon registers, -wires, and conditional updates. - -Below is a more complicated FSM example which is a circuit for -accepting money for a vending machine: -\begin{scala} -class VendingMachine extends Module { - val io = new Bundle { - val nickel = Bool(dir = INPUT) - val dime = Bool(dir = INPUT) - val rdy = Bool(dir = OUTPUT) } - val s_idle :: s_5 :: s_10 :: s_15 :: s_ok :: Nil = - Enum(UInt(), 2) - val state = Reg(init = s_idle) - when (state === s_idle) { - when (io.nickel) { state := s_5 } - when (io.dime) { state := s_10 } - } - when (state === s_5) { - when (io.nickel) { state := s_10 } - when (io.dime) { state := s_15 } - } - when (state === s_10) { - when (io.nickel) { state := s_15 } - when (io.dime) { state := s_ok } - } - when (state === s_15) { - when (io.nickel) { state := s_ok } - when (io.dime) { state := s_ok } - } - when (state === s_ok) { - state := s_idle - } - io.rdy := (state === s_ok) -} -\end{scala} - -\noindent -Here is the vending machine FSM defined with \code{switch} statement: -\begin{scala} -class VendingMachine extends Module { - val io = new Bundle { - val nickel = Bool(dir = INPUT) - val dime = Bool(dir = INPUT) - val rdy = Bool(dir = OUTPUT) } - val s_idle :: s_5 :: s_10 :: s_15 :: s_ok :: Nil = Enum(UFIx(), 5) - val state = Reg(init = s_idle) - switch (state) { - is (s_idle) { - when (io.nickel) { state := s_5 } - when (io.dime) { state := s_10 } - } is (s_5) { - when (io.nickel) { state := s_10 } - when (io.dime) { state := s_15 } - } is (s_10) { - when (io.nickel) { state := s_15 } - when (io.dime) { state := s_ok } - } is (s_15) { - when (io.nickel) { state := s_ok } - when (io.dime) { state := s_ok } - } is (s_ok) { - state := s_idle - } - } - io.rdy := (state === s_ok) -} -\end{scala} - -\section{Memories} - -Chisel provides facilities for creating both read only and -read/write memories. - -\subsection{ROM} - -Users can define read only memories with a \code{Vec}: - -\begin{scala} -Vec(inits: Seq[T]) -Vec(elt0: T, elts: T*) -\end{scala} - -\noindent -where \verb+inits+ is a sequence of initial \verb+Data+ literals that -initialize the ROM. -For example, users can -create a small ROM initialized to \verb+1, 2, 4, 8+ and -loop through all values using a counter as an address generator as follows: - -\begin{scala} -val m = Vec(Array(UInt(1), UInt(2), UInt(4), UInt(8))) -val r = m(counter(UInt(m.length))) -\end{scala} - -\noindent -We can create an \verb+n+ value sine lookup table using a ROM initialized as follows: - -\begin{scala} -def sinTable (amp: Double, n: Int) = { - val times = - Range(0, n, 1).map(i => (i*2*Pi)/(n.toDouble-1) - Pi) - val inits = - times.map(t => SInt(round(amp * sin(t)), width = 32)) - Vec(inits) -} -def sinWave (amp: Double, n: Int) = - sinTable(amp, n)(counter(UInt(n)) -\end{scala} - -\noindent -where \verb+amp+ is used to scale the fixpoint values stored in the ROM. - -\subsection{Mem} - -Memories are given special treatment in Chisel since hardware -implementations of memory have many variations, e.g., FPGA memories -are instantiated quite differently from ASIC memories. Chisel defines -a memory abstraction that can map to either simple Verilog behavioral -descriptions, or to instances of memory modules that are available -from external memory generators provided by foundry or IP vendors. - -Chisel supports random-access memories via the \code{Mem} construct. -Writes to Mems are positive-edge-triggered and reads are either -combinational or positive-edge-triggered. - -\begin{scala} -object Mem { - def apply[T <: Data](type: T, depth: Int, - seqRead: Boolean = false): Mem -} - -class Mem[T <: Data](type: T, depth: Int, - seqRead: Boolean = false) - extends Updateable { - def apply(idx: UInt): T -} -\end{scala} - -Ports into Mems are created by applying a \code{UInt} index. A 32-entry -register file with one write port and two combinational read ports might be -expressed as follows: - -\begin{scala} -val rf = Mem(UInt(width = 64), 32) -when (wen) { rf(waddr) := wdata } -val dout1 = rf(waddr1) -val dout2 = rf(waddr2) -\end{scala} - -If the optional parameter \code{seqRead} is set, Chisel will attempt to infer -sequential read ports when the read address is a Reg. A one-read, -one-write SRAM might be described as follows: - -\begin{scala} -val ram1r1w = - Mem(UInt(width = 32), 1024, seqRead = true) -val reg_raddr = Reg(UInt()) -when (wen) { ram1r1w(waddr) := wdata } -when (ren) { reg_raddr := raddr } -val rdata = ram1r1w(reg_raddr) -\end{scala} - -Single-ported SRAMs can be inferred when the read and write conditions are -mutually exclusive in the same \code{when} chain: - -\begin{scala} -val ram1p = - Mem(UInt(width = 32), 1024, seqRead = true) -val reg_raddr = Reg(UInt()) -when (wen) { ram1p(waddr) := wdata } -.elsewhen (ren) { reg_raddr := raddr } -val rdata = ram1p(reg_raddr) -\end{scala} - -If the same Mem address is both written and sequentially read on the same clock -edge, or if a sequential read enable is cleared, then the read data is -undefined. - -Mem also supports write masks for subword writes. A given bit is written if -the corresponding mask bit is set. - -\begin{scala} -val ram = Mem(UInt(width = 32), 256) -when (wen) { ram.write(waddr, wdata, wmask) } -\end{scala} - - -% For example, an -% audio recorder could be defined as follows: -% -% \begin{scala} -% def audioRecorder(n: Int, button: Bool) = { -% val addr = counter(UInt(n)) -% val ram = Mem(n) -% ram(addr) := button -% ram(Mux(button(), UInt(0), addr)) -% } -% \end{scala} -% -% \noindent -% where a counter is used as an address generator into a memory. -% The device records while \verb+button+ is \verb+true+, or plays back when \verb+false+. - - -\section{Interfaces and Bulk Connections} -\label{sec:interfaces} - -For more sophisticated modules it is often useful to define and -instantiate interface classes while defining module IO. First and -foremost, interface classes promote reuse allowing users to capture -once and for all common interfaces in a useful form. Secondly, -interfaces allow users to dramatically reduce wiring by supporting -{\em bulk connections} between producer and consumer modules. Finally, -users can make changes in large interfaces in one place reducing the -number of updates required when adding or removing pieces of the -interface. - -\subsection{Port Classes, Subclasses, and Nesting} - -As we saw earlier, users can define their own interfaces by defining a class that subclasses \verb+Bundle+. -For example, a user could define a simple link for handshaking data as follows: - -\begin{scala} -class SimpleLink extends Bundle { - val data = UInt(16, OUTPUT) - val valid = Bool(OUTPUT) -} -\end{scala} - -\noindent -We can then extend \verb+SimpleLink+ by adding parity bits using -bundle inheritance: - -\begin{scala} -class PLink extends SimpleLink { - val parity = UInt(5, OUTPUT) -} -\end{scala} - -\noindent -In general, users can organize their interfaces into hierarchies using inheritance. - -From there we can define a filter interface by nesting two -\verb+PLink+s into a new \verb+FilterIO+ bundle: - -\begin{scala} -class FilterIO extends Bundle { - val x = new PLink().flip - val y = new PLink() -} -\end{scala} - -\noindent -where \verb+flip+ recursively changes the ``gender'' of a bundle, -changing input to output and output to input. - -We can now define a filter by defining a filter class extending module: - -\begin{scala} -class Filter extends Module { - val io = new FilterIO() - ... -} -\end{scala} - -\noindent -where the \verb+io+ field contains \verb+FilterIO+. - -\subsection{Bundle Vectors} - -Beyond single elements, vectors of elements form richer hierarchical interfaces. -For example, in order to create a crossbar with a vector of inputs, producing a vector of outputs, and selected by a UInt input, -we utilize the \verb+Vec+ constructor: - -\begin{scala} -class CrossbarIo(n: Int) extends Bundle { - val in = Vec.fill(n){ new PLink().flip() } - val sel = UInt(INPUT, sizeof(n)) - val out = Vec.fill(n){ new PLink() } -} -\end{scala} - -% \begin{scala} -% class CrossbarIo(n: Int) extends Bundle { -% val in = Vec.fill(n){ UInt(w, INPUT) } -% val sel = Vec.fill(n){ UInt(sizeof(n), INPUT) } -% val out = Vec.fill(n){ UInt(w, OUTPUT) } -% } -% \end{scala} - -\noindent -where \verb+Vec+ takes a size as the first argument and a block returning a port as the second argument. - -\subsection{Bulk Connections} - -We can now compose two filters into a filter block as follows: - -\begin{scala} -class Block extends Module { - val io = new FilterIO() - val f1 = Module(new Filter()) - val f2 = Module(new Filter()) - - f1.io.x <> io.x - f1.io.y <> f2.io.x - f2.io.y <> io.y -} -\end{scala} - -\noindent -where \verb+<>+ bulk connects interfaces of opposite gender between -sibling modules or interfaces of same gender between parent/child modules. -Bulk connections connect leaf ports of the same name to each other. -After all connections are made and the circuit is being elaborated, -Chisel warns users if ports have other than exactly one connection to them. - -\subsection{Interface Views} - -\begin{figure} -\centerline{\includegraphics[width=3in]{figs/cpu.png}} -\caption{Simple CPU involving control and data path submodules and host and memory interfaces.} -\label{fig:cpu} -\end{figure} - -Consider a simple CPU consisting of control path and data path submodules and host and memory interfaces shown in Figure~\ref{fig:cpu}. -In this CPU we can see that the control path and data path each connect only to a part of the instruction and data memory interfaces. -Chisel allows users to do this with partial fulfillment of interfaces. -A user first defines the complete interface to a ROM and Mem as follows: - -\begin{scala} -class RomIo extends Bundle { - val isVal = Bool(INPUT) - val raddr = UInt(INPUT, 32) - val rdata = UInt(OUTPUT, 32) -} - -class RamIo extends RomIo { - val isWr = Bool(INPUT) - val wdata = UInt(INPUT, 32) -} -\end{scala} - -\noindent -Now the control path can build an interface in terms of these interfaces: - -\begin{scala} -class CpathIo extends Bundle { - val imem = RomIo().flip() - val dmem = RamIo().flip() - ... -} -\end{scala} - -\noindent -and the control and data path modules can be built by partially assigning to -this interfaces as follows: - -\begin{scala} -class Cpath extends Module { - val io = new CpathIo(); - ... - io.imem.isVal := ...; - io.dmem.isVal := ...; - io.dmem.isWr := ...; - ... -} - -class Dpath extends Module { - val io = new DpathIo(); - ... - io.imem.raddr := ...; - io.dmem.raddr := ...; - io.dmem.wdata := ...; - ... -} -\end{scala} - -\noindent -We can now wire up the CPU using bulk connects as we would with other bundles: - -\begin{scala} -class Cpu extends Module { - val io = new CpuIo() - val c = Module(new CtlPath()) - val d = Module(new DatPath()) - c.io.ctl <> d.io.ctl - c.io.dat <> d.io.dat - c.io.imem <> io.imem - d.io.imem <> io.imem - c.io.dmem <> io.dmem - d.io.dmem <> io.dmem - d.io.host <> io.host -} -\end{scala} - -\noindent -Repeated bulk connections of partially assigned control and data path interfaces -completely connect up the CPU interface. - -% A Bool can be automatically treated as a single bit UInt (with values -% 0 or 1), but an Int or UInt cannot be used as a Bool without an -% explicit cast. -% -% Lit(5) // means a constant node with decimal value 5. Bit width will -% // be inferred automatically if possible -% -% A node is a hardware operator that has zero or more inputs and that -% drives one output. An example of a node with zero inputs is a -% constant generator. -% -% \begin{scala} -% Lit(10, 4) // means a constant node of type UInt that is 4 bits -% // wide with decimal 10. -% Lit(10) -% LitInt(10, 4) -% LitUInt(10, 4) -% Lit(-1,4) -% \end{scala} -% -% can more concisely write: -% -% Module correspond to Verilog modules -% Cell is a sub-module, Chisel Module - -\section{Functional Creation of Modules} -\label{sec:funconstructor} - -It is also useful to be able to make a functional interface for -module construction. For instance, we could build a constructor -that takes multiplexer inputs as parameters and returns the -multiplexer output: - -\begin{scala} -object Mux2 { - def apply (sel: UInt, in0: UInt, in1: UInt) = { - val m = new Mux2() - m.io.in0 := in0 - m.io.in1 := in1 - m.io.sel := sel - m.io.out - } -} -\end{scala} - -\noindent -where \code{object Mux2} creates a Scala singleton object on the \code{Mux2} -module class, and \code{apply} defines a method for creation of a \code{Mux2} instance. -% -With this \code{Mux2} creation function, the specification of \code{Mux4} now is -significantly simpler. - -\begin{scala} -class Mux4 extends Module { - val io = new Bundle { - val in0 = UInt(INPUT, 1) - val in1 = UInt(INPUT, 1) - val in2 = UInt(INPUT, 1) - val in3 = UInt(INPUT, 1) - val sel = UInt(INPUT, 2) - val out = UInt(OUTPUT, 1) - } - io.out := Mux2(io.sel(1), - Mux2(io.sel(0), io.in0, io.in1), - Mux2(io.sel(0), io.in2, io.in3)) -} -\end{scala} - -Selecting inputs is so useful that Chisel builds it in and calls it -\code{Mux}. However, unlike \code{Mux2} defined above, the builtin version allows any datatype on -\code{in0} and \code{in1} as long as they have a common super class. -In Section~\ref{sec:parameterization} we will see how to define this -ourselves. - -Chisel provides \code{MuxCase} which is an n-way \code{Mux} -\begin{scala} -MuxCase(default, Array(c1 -> a, c2 -> b, ...)) -\end{scala} - -\noindent -where each condition / value is represented as a tuple in a Scala -array and where \code{MuxCase} can be translated into the following -\code{Mux} expression: - -\begin{scala} -Mux(c1, a, Mux(c2, b, Mux(..., default))) -\end{scala} - -\noindent -Chisel also provides \code{MuxLookup} which is an n-way indexed multiplexer: - -\begin{scala} -MuxLookup(idx, default, - Array(UInt(0) -> a, UInt(1) -> b, ...)) -\end{scala} - -\noindent -which can be rewritten in terms of:\verb+MuxCase+ as follows: - -\begin{scala} -MuxCase(default, - Array((idx === UInt(0)) -> a, - (idx === UInt(1)) -> b, ...)) -\end{scala} - -\noindent -Note that the cases (eg. c1, c2) must be in parentheses. - -% TODO: higher order filter - -% \Noindent -% where the overall expression returns the value corresponding to the first condition evaluating to true. - -% FUNCTIONAL CREATION -% -% want to go from io to constructor -% -% \begin{scala} -% val io = new Bundle{ -% val sel = UInt(INPUT, 1) -% val in0 = UInt(INPUT, 1) -% val in1 = UInt(INPUT, 1) -% val out = UInt(OUTPUT, 1) -% } -% def Mux2(sel: UInt, in0: UInt, in0: UInt): UInt = { -% val m = new Mux2() -% m.io.wire(Array("sel" => sel, "in0" => in0, "in1" => in1), "out") -% } -% \end{scala} - -% picture of box in box - - - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -\section{Polymorphism and Parameterization} -\label{sec:parameterization} - -Scala is a strongly typed language and uses parameterized types to specify generic functions and classes. -In this section, we show how Chisel users can define their own reusable functions and classes using parameterized classes. -\begin{commentary} -This section is advanced and can be skipped at first reading. -\end{commentary} - -\subsection{Parameterized Functions} - -Earlier we defined \code{Mux2} on \code{Bool}, but now we show how we can define a generic multiplexer function. -We define this function as taking a boolean condition and con and alt arguments (corresponding to then and else expressions) of type \code{T}: - -\begin{scala} -def Mux[T <: Bits](c: Bool, con: T, alt: T): T { ... } -\end{scala} - -\noindent -where \code{T} is required to be a subclass of \code{Bits}. -Scala ensures that in each usage of \code{Mux}, it can find a common superclass of the actual con and alt argument types, -otherwise it causes a Scala compilation type error. -For example, - -\begin{scala} -Mux(c, UInt(10), UInt(11)) -\end{scala} - -\noindent -yields a \code{UInt} wire because the \code{con} and \code{alt} arguments are each of type \code{UInt}. - -% Earlier we defined \code{Mux2} on \code{Bool}, but now we show how we can define a generic \code{Mux}. -% We define a function that takes a condition and two functions of no arguments (called thunks) for the {\it then} and {\it else} cases: -% -% \begin{scala} -% def Mux[T <: UInt](c: Bool, con: T, alt: T): T -% def Mux[T <: UInt](c: Bool)(con: => T)(alt: => T): T -% \end{scala} -% -% \noindent -% where the two thunk return types are parameterized to be a type \code{T} that is a subclass of \code{UInt}. -% Scala ensures that it finds a common superclass of the two thunks' return types. - -We now present a more advanced example of parameterized functions for defining an inner product FIR digital filter generically over Chisel \code{Num}'s. -The inner product FIR filter can be mathematically defined as: -\begin{equation} -y[t] = \sum_j w_j * x_j[t-j] -\end{equation} - -\noindent -where $x$ is the input and $w$ is a vector of weights. -In Chisel this can be defined as: - -% MS: just out of curiosity: does this example generate several delay lines? -\begin{scala} -def delays[T <: Data](x: T, n: Int): List[T] = - if (n <= 1) List(x) else x :: Delays(RegNext(x), n-1) - -def FIR[T <: Data with Num[T]](ws: Seq[T], x: T): T = - (ws, Delays(x, ws.length)).zipped. - map( _ * _ ).reduce( _ + _ ) -\end{scala} - -\noindent -where -\code{delays} creates a list of incrementally increasing delays of its input and -\code{reduce} constructs a reduction circuit given a binary combiner function \code{f}. -In this case, \code{reduce} creates a summation circuit. -Finally, the \code{FIR} function is constrained to work on inputs of type \code{Num} where Chisel multiplication and addition are defined. - -\subsection{Parameterized Classes} - -Like parameterized functions, we can also parameterize classes to make them more reusable. -For instance, we can generalize the Filter class to use any kind of link. -We do so by parameterizing the \verb+FilterIO+ class and defining the constructor to take a zero argument type constructor function as follow: - -\begin{scala} -class FilterIO[T <: Data](type: T) extends Bundle { - val x = type.asInput.flip - val y = type.asOutput -} -\end{scala} - -\noindent -We can now define \verb+Filter+ by defining a module class that also takes a link type constructor argument and passes it through to the \verb+FilterIO+ interface constructor: - -\begin{scala} -class Filter[T <: Data](type: T) extends Module { - val io = new FilterIO(type) - ... -} -\end{scala} - -\noindent -We can now define a \verb+PLink+ based \verb+Filter+ as follows: -\begin{scala} -val f = Module(new Filter(new PLink())) -\end{scala} - -\noindent -where the curly braces \verb+{ }+ denote a zero argument function (aka thunk) that in this case creates the link type. - -A generic FIFO could be defined as shown in Figure~\ref{fig:fifo} and -used as follows: - -\begin{scala} -class DataBundle extends Bundle { - val A = UInt(width = 32) - val B = UInt(width = 32) -} - -object FifoDemo { - def apply () = new Fifo(new DataBundle, 32) -} -\end{scala} - -\begin{figure}[ht] -\begin{scala} -class Fifo[T <: Data] (type: T, n: Int) - extends Module { - val io = new Bundle { - val enq_val = Bool(INPUT) - val enq_rdy = Bool(OUTPUT) - val deq_val = Bool(OUTPUT) - val deq_rdy = Bool(INPUT) - val enq_dat = type.asInput - val deq_dat = type.asOutput - } - val enq_ptr = Reg(init = UInt(0, sizeof(n))) - val deq_ptr = Reg(init = UInt(0, sizeof(n))) - val is_full = Reg(init = Bool(false)) - val do_enq = io.enq_rdy && io.enq_val - val do_deq = io.deq_rdy && io.deq_val - val is_empty = !is_full && (enq_ptr === deq_ptr) - val deq_ptr_inc = deq_ptr + UInt(1) - val enq_ptr_inc = enq_ptr + UInt(1) - val is_full_next = - Mux(do_enq && ~do_deq && (enq_ptr_inc === deq_ptr), - Bool(true), - Mux(do_deq && is_full, Bool(false), is_full)) - enq_ptr := Mux(do_enq, enq_ptr_inc, enq_ptr) - deq_ptr := Mux(do_deq, deq_ptr_inc, deq_ptr) - is_full := is_full_next - val ram = Mem(n) - when (do_enq) { - ram(enq_ptr) := io.enq_dat - } - io.enq_rdy := !is_full - io.deq_val := !is_empty - ram(deq_ptr) <> io.deq_dat -} -\end{scala} -\caption{Parameterized FIFO example.} -\label{fig:fifo} -\end{figure} - -It is also possible to define a generic decoupled interface: - -\begin{scala} -class DecoupledIO[T <: Data](data: T) - extends Bundle { - val ready = Bool(INPUT) - val valid = Bool(OUTPUT) - val bits = data.clone.asOutput -} -\end{scala} - -\noindent -This template can then be used to add a handshaking protocol to any -set of signals: - -\begin{scala} -class DecoupledDemo - extends DecoupledIO()( new DataBundle ) -\end{scala} - -\noindent -The FIFO interface in Figure~\ref{fig:fifo} can be now be simplified as -follows: - -\begin{scala} -class Fifo[T <: Data] (data: T, n: Int) - extends Module { - val io = new Bundle { - val enq = new DecoupledIO( data ).flip() - val deq = new DecoupledIO( data ) - } - ... -} -\end{scala} - - -\section{Multiple Clock Domains} - -Chisel 2.0 introduces support of multiple clock domains. - -\subsection{Creating Clock domains} - -In order to use multiple clock domains, users must create multiple clocks. -In Chisel, clocks are first class nodes created with a reset signal parameter and defined as follows: - -\begin{scala} -class Clock (reset: Bool) extends Node { - def reset: Bool // returns reset pin -} -\end{scala} - -\noindent -% Having reset in clock makes it easier to pass around. -In Chisel there is a builtin implicit clock that state elements use by default: - -\begin{scala} -var implicitClock = new Clock( implicitReset ) -\end{scala} - -The clock for state elements and modules can be defined using an additional named parameter called clock: - -\begin{scala} -Reg(... clock: Clock = implicitClock) -Mem(... clock: Clock = implicitClock) -Module(... clock: Clock = implicitClock) -\end{scala} - -\subsection{Crossing Clock Domains} - -There are two ways that circuits can be defined to send data between clock domains. -The first and most primitive way is by using a synchronizer circuit comprised of two registers as follows: - -\begin{scala} -// signalA is in clock domain clockA, -// want a version in clockB as signalB -val s1 = Reg(init = UInt(0), clock = clockB) -val s2 = Reg(init = UInt(0), clock = clockB) -s1 := signalA -s2 := s1; -signalB := s2 -\end{scala} - -\noindent -Due to metastability issues, this technique is limited to communicating one bit data between domains. - -The second and more general way to send data between domains is by using an asynchronous queue: - -\begin{scala} -class AsyncQueue[T<:Data] - (gen: T, depth: Int, enq_clk: Clock, deq_clock: Clock) - extends Module -\end{scala} - -\noindent -When get a version of signalA from clock domains clockA to clockB by specifying the standard queue parameters and the two clocks and then using the standard decoupled ready/valid signals: - -\begin{scala} -val queue = - new AsyncQueue(Uint(width = 32), 2, clockA, clockB) -fifo.enq.bits := signalA -signalB := fifo.deq.bits -fifo.valid := condA -fifo.ready := condB -... -\end{scala} - -\subsection{Backend Specific Multiple Clock Domains} - -Each Chisel backend requires the user to setup up and control multiple clocks in a backend specific manner. For the purposes of showing how to drive a multi clock design, consider the example of hardware with two modules communicating using an AsyncQueue with each module on separate clocks: \verb+fastClock+ and \verb+slowClock+. - -\subsubsection{C++} - -In the C++ backend, for every clock \verb+i+ there is a -\begin{itemize} -\item \verb+uint64_t clk_i+ field representing the clock \verb+i+'s period, -\item \verb+uint63_t clk_i_cnt+ field representing the clock \verb+i+'s current count, -\item \verb+clock_lo_i+ and \verb+clock_hi_i+, -\item \verb+int reset()+ function which ensures that all \verb+clock_lo+ and \verb+clock_hi+ functions are called at least once, and -\item \verb+int clock(reset)+ function which computes min delta, invokes appropriate \verb+clock_lo+ and \verb+clock_hi+'s and returns min delta used. -\end{itemize} - -\noindent -In order to set up a C++ simulation, the user -\begin{itemize} -\item initializes all period fields to desired period -\item initializes all count fields to desired phase, -\item calls \verb+reset+ and then -\item repeated calls clock to step the simulation. -\end{itemize} - -\noindent -The following is a C++ example of a main function for the \verb+slowClock+ / \verb+fastClock+ example: - -\begin{scala} -int main(int argc, char** argv) { - ClkDomainTest_t dut; - dut.init(1); - dut.clk = 2; - dut.clk_cnt = 1; - dut.fastClock = 4; - dut.fastClock_cnt = 0; - dut.slowClock = 6; - dut.slowClock_cnt = 0; - for (int i = 0; i < 12; i ++) - dut.reset(); - for (int i = 0; i < 96; i ++) - dut.clock(LIT<1>(0)); -} -\end{scala} - -\subsubsection{Verilog} - -In Verilog, - -\begin{itemize} -\item Chisel creates a new port for each clock / reset, -\item Chisel wires all the clocks to the top module, and -\item the user must create an \verb+always+ block clock driver for every clock \verb+i+. -\end{itemize} - -\noindent -The following is a Verilog example of a top level harness to drive the \verb+slowClock+ / \verb+fastClock+ example circuit: - -\begin{scala} -module emulator; - reg fastClock = 0, slowClock = 0, - resetFast = 1, resetSlow = 1; - wire [31:0] add, mul, test; - always #2 fastClock = ~fastClock; - always #4 slowClock = ~slowClock; - initial begin - #8 - resetFast = 0; - resetSlow = 0; - #400 - $finish; - end - ClkDomainTest dut ( - .fastClock(fastClock), - .slowClock(slowClock), - .io_resetFast(resetFast), - .io_resetSlow(resetSlow), - .io_add(add), .io_mul(mul), .io_test(test)); -endmodule -\end{scala} - -\noindent -See \url{http://www.asic-world.com/verilog/verifaq2.html} for more information about simulating clocks in Verilog. - -\section{Acknowlegements} - -Many people have helped out in the design of Chisel, and we thank them -for their patience, bravery, and belief in a better way. Many -Berkeley EECS students in the Isis group gave weekly feedback as the -design evolved including but not limited to Yunsup Lee, Andrew -Waterman, Scott Beamer, Chris Celio, etc. Yunsup Lee gave us feedback -in response to the first RISC-V implementation, called TrainWreck, -translated from Verilog to Chisel. Andrew Waterman and Yunsup Lee -helped us get our Verilog backend up and running and Chisel TrainWreck -running on an FPGA. Brian Richards was the first actual Chisel user, -first translating (with Huy Vo) John Hauser's FPU Verilog code to -Chisel, and later implementing generic memory blocks. Brian gave many -invaluable comments on the design and brought a vast experience in -hardware design and design tools. Chris Batten shared his fast -multiword C++ template library that inspired our fast emulation -library. Huy Vo became our undergraduate research assistant and was -the first to actually assist in the Chisel implementation. We -appreciate all the EECS students who participated in the Chisel -bootcamp and proposed and worked on hardware design projects all of -which pushed the Chisel envelope. We appreciate the work that James -Martin and Alex Williams did in writing and translating network and -memory controllers and non-blocking caches. Finally, Chisel's -functional programming and bit-width inference ideas were inspired by -earlier work on a hardware description language called Gel~\cite{gel} designed in -collaboration with Dany Qumsiyeh and Mark Tobenkin. - -% \note{Who else?} - -\begin{thebibliography}{50} -\bibitem{chisel-dac12} Bachrach, J., Vo, H., Richards, B., Lee, Y., Waterman, - A., Avi\v{z}ienis, Wawrzynek, J., Asanovi\'{c} \textsl{Chisel: - Constructing Hardware in a Scala Embedded Language}. -in DAC '12. -\bibitem{gel} Bachrach, J., Qumsiyeh, D., Tobenkin, M. \textsl{Hardware Scripting in Gel}. -in Field-Programmable Custom Computing Machines, 2008. FCCM '08. 16th. -\end{thebibliography} - -\end{document} diff --git a/install_maven_libs b/install_maven_libs deleted file mode 100755 index 849eb8ee..00000000 --- a/install_maven_libs +++ /dev/null @@ -1,9 +0,0 @@ -#!/bin/bash -pushd lib - -mvn install:install-file -Dfile=oscar-algo_2.10-1.0-M1.jar -DgroupId=ucl.ac.be -DartifactId=oscar-algo -Dversion=2.10-1.0-M1 -Dpackaging=jar -mvn install:install-file -Dfile=oscar-cp_2.10-1.0-M1.jar -DgroupId=ucl.ac.be -DartifactId=oscar-cp -Dversion=2.10-1.0-M1 -Dpackaging=jar -mvn install:install-file -Dfile=oscar-util_2.10-1.0-M1.jar -DgroupId=ucl.ac.be -DartifactId=oscar-util -Dversion=2.10-1.0-M1 -Dpackaging=jar -mvn install:install-file -Dfile=oscar-visual_2.10-1.0-M1.jar -DgroupId=ucl.ac.be -DartifactId=oscar-visual -Dversion=2.10-1.0-M1 -Dpackaging=jar - -popd diff --git a/man.mk b/man.mk new file mode 100644 index 00000000..be0a296e --- /dev/null +++ b/man.mk @@ -0,0 +1,19 @@ +# make fragment to build man pages. + +LATEX2MAN := latex2man +MAN_PAGES := chisel.man + +# Set the current release info +# RELEASE_TAGTEXT is something like: v2.2.18 125 g3501d7f +# i.e., the output of git describe with dashes replaced by spaces +RELEASE_TAGTEXT=$(subst -, ,$(shell git describe --tags release)) +RELEASE_TAG=$(firstword $(RELEASE_TAGTEXT)) +RELEASE_DATETEXT=$(shell git log -1 --format="%ai" $(RELEASE_TAG)) +RELEASE_DATE=$(firstword $(RELEASE_DATETEXT)) + +all: $(MAN_PAGES) + +%.man: %.mtt + sed -e "s/@VERSION@/$(RELEASE_TAG)/" -e "s/@DATE@/$(RELEASE_DATE)/" $(notdir $<) > $(basename $@).ttex ;\ + latex2man $(basename $@).ttex $@ + diff --git a/pom.xml b/pom.xml deleted file mode 100644 index 3384db01..00000000 --- a/pom.xml +++ /dev/null @@ -1,147 +0,0 @@ - - - - 4.0.0 - - edu.berkeley.eecs - chisel - 2.3-SNAPSHOT - Chisel HDL - Chisel HDL DSL based in Scala. - - - - org.scala-lang - scala-library - 2.10.3 - - - - ucl.ac.be - oscar-algo - 2.10-1.0-M1 - - - - ucl.ac.be - oscar-cp - 2.10-1.0-M1 - - - - ucl.ac.be - oscar-util - 2.10-1.0-M1 - - - - ucl.ac.be - oscar-visual - 2.10-1.0-M1 - - - - junit - junit - 4.11 - test - - - - org.scalatest - scalatest_2.10 - 2.0.RC2 - test - - - - - - - - - net.alchim31.maven - scala-maven-plugin - 3.1.6 - - - - org.apache.maven.plugins - maven-compiler-plugin - 2.0.2 - - - - - - - - - net.alchim31.maven - scala-maven-plugin - - - scala-compile-first - process-resources - - add-source - compile - - - - scala-test-compile - process-test-resources - - testCompile - - - - - - - org.apache.maven.plugins - maven-compiler-plugin - - - compile - - compile - - - - - - - org.apache.maven.plugins - maven-surefire-plugin - - - **/*Suite.class - - - - - - - - - - - skip - - true - - - - - - ignore - - true - true - - - - - diff --git a/project/build.properties b/project/build.properties index 748703f7..c091b86c 100644 --- a/project/build.properties +++ b/project/build.properties @@ -1 +1 @@ -sbt.version=0.13.7 +sbt.version=0.13.16 diff --git a/project/build.scala b/project/build.scala deleted file mode 100644 index aaf1bfca..00000000 --- a/project/build.scala +++ /dev/null @@ -1,78 +0,0 @@ -import sbt._ -import Keys._ - -object BuildSettings extends Build { - - val buildSettings = Defaults.defaultSettings ++ Seq ( - organization := "edu.berkeley.cs", - // version := "2.2.26", - version := "2.3-SNAPSHOT", - name := "chisel", - scalaVersion := "2.10.4", - crossScalaVersions := Seq("2.10.4", "2.11.5"), - //sourceDirectory := new File("@srcTop@"), - publishMavenStyle := true, - publishArtifact in Test := false, - pomIncludeRepository := { x => false }, - pomExtra := ( - http://chisel.eecs.berkeley.edu/ - - - BSD-style - http://www.opensource.org/licenses/bsd-license.php - repo - - - - https://github.com/ucb-bar/chisel.git - scm:git:github.com/ucb-bar/chisel.git - - - - jackbackrack - Jonathan Bachrach - http://people.csail.mit.edu/jrb/ - - - huytbvo - Huy Vo - - - ), - - publishTo <<= version { v: String => - val nexus = "https://oss.sonatype.org/" - if (v.trim.endsWith("SNAPSHOT")) - Some("snapshots" at nexus + "content/repositories/snapshots") - else - Some("releases" at nexus + "service/local/staging/deploy/maven2") - }, - - resolvers ++= Seq( - "Sonatype Snapshots" at "http://oss.sonatype.org/content/repositories/snapshots", - "Sonatype Releases" at "http://oss.sonatype.org/content/repositories/releases" - ), - - /* Bumping "com.novocode" % "junit-interface" % "0.11", causes DelayTest testSeqReadBundle to fail - * in subtly disturbing ways on Linux (but not on Mac): - * - some fields in the generated .h file are re-named, - * - an additional field is added - * - the generated .cpp file has additional differences: - * - different temps in clock_lo - * - missing assignments - * - change of assignment order - * - use of "Tx" vs. "Tx.values" - */ - libraryDependencies += "com.novocode" % "junit-interface" % "0.10" % "test", - libraryDependencies += "org.scalatest" %% "scalatest" % "2.2.4" % "test", - libraryDependencies <+= (scalaVersion)("org.scala-lang" % "scala-reflect" % _), - - // Execute tests in the current project serially. - // Tests from other projects may still run concurrently. - parallelExecution in Test := false, - scalacOptions ++= Seq("-deprecation", "-feature", "-language:reflectiveCalls", "-language:implicitConversions", "-language:existentials") - ) ++ org.scalastyle.sbt.ScalastylePlugin.Settings - - lazy val root = Project("chisel", file("."), settings=buildSettings) -} - diff --git a/project/plugins.sbt b/project/plugins.sbt index 2aa5113c..daa639b3 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -2,9 +2,8 @@ resolvers += Resolver.url("scalasbt", new URL("http://scalasbt.artifactoryonline resolvers += Classpaths.sbtPluginReleases -addSbtPlugin("com.typesafe.sbt" % "sbt-pgp" % "0.8") +addSbtPlugin("org.scalastyle" %% "scalastyle-sbt-plugin" % "0.8.0") -addSbtPlugin("org.scalastyle" %% "scalastyle-sbt-plugin" % "0.3.2") - -addSbtPlugin("org.scoverage" % "sbt-scoverage" % "1.0.4") +addSbtPlugin("org.scoverage" % "sbt-scoverage" % "1.3.5") +addSbtPlugin("com.eed3si9n" % "sbt-buildinfo" % "0.6.1") diff --git a/scalastyle-config.xml b/scalastyle-config.xml index bc9620e4..a2fad84b 100644 --- a/scalastyle-config.xml +++ b/scalastyle-config.xml @@ -9,7 +9,7 @@ class dat_api : public dat_api_base { +public: + dat_api(dat_t* new_dat): dat_api_base(w), dat_ptr(new_dat) { } + inline std::string get_value() { + return dat_ptr->to_str(); + } + inline bool put_value(std::string &value) { + return dat_from_hex(value, *dat_ptr); + } + inline size_t get_value(val_t* values) { + size_t i = 0; + for ( ; i < get_num_words() ; i++) { + val_t value = dat_ptr->values[i]; + values[i] = (i == (get_num_words()-1)) ? value & mask : value; + } + return i; + } + inline size_t put_value(val_t* values) { + size_t i = 0; + for ( ; i < get_num_words() ; i++) { + val_t value = values[i]; + dat_ptr->values[i] = (i == (get_num_words()-1)) ? value & mask : value; + } + return i; + } + inline size_t get_width() { return w; } + inline size_t get_num_words() { return dat_ptr->n_words_of(); } + +private: + dat_t* dat_ptr; +}; + +inline std::string itos(int in, bool is_hex = true) { + std::stringstream out; + if (is_hex) out << std::hex; + out << in; + return out.str(); +} + +class clk_api: public dat_api_base { +public: + clk_api(clk_t* new_clk): dat_api_base(1), clk_ptr(new_clk) { } + inline std::string get_value() { return itos(clk_ptr->len); } + inline bool put_value(std::string &value) { return false; } + inline size_t get_value(val_t* values) { + values[0] = (val_t) clk_ptr->len; + return 1; + } + inline size_t put_value(val_t* values) { + clk_ptr->len = (size_t) values[0]; + clk_ptr->cnt = (size_t) values[0]; + return 1; + } + inline size_t get_width() { return 8*sizeof(size_t); } + inline size_t get_num_words() { return 1; } + +private: + clk_t* clk_ptr; +}; + +class emul_api_t: public sim_api_t { +public: + emul_api_t(mod_t* m) { + module = m; + is_exit = false; + } + inline bool exit() { return is_exit; } + +protected: + mod_t* module; + +private: + virtual inline void put_value(dat_api_base* &sig, std::string& value, bool force=false) { + sig->put_value(value); + } + + virtual inline size_t put_value(dat_api_base* &sig, uint64_t* data, bool force=false) { + return sig->put_value(data); + } + + virtual inline std::string get_value(dat_api_base* &sig) { + return sig->get_value(); + } + + virtual inline size_t get_value(dat_api_base* &sig, uint64_t* data) { + return sig->get_value(data); + } + + virtual inline size_t get_chunk(dat_api_base* &sig) { + return sig->get_num_words(); + } + + virtual inline void reset() { + module->clock(LIT<1>(1)); + // FIXME: should call twice to get the output for now + module->clock_lo(LIT<1>(0), false); + } + + virtual inline void start() { } + + bool is_exit; + virtual inline void finish() { + module->clock(LIT<1>(0)); // to vcd-dump the last cycle + is_exit = true; + } + + virtual inline void step() { + module->clock(LIT<1>(0)); + // FIXME: should call twice to get the output for now + module->clock_lo(LIT<1>(0), false); + } + + virtual inline void update() { + module->clock_lo(LIT<1>(0), false); + } +}; + +#endif diff --git a/src/main/resources/emulator.h b/src/main/resources/emulator.h index 1286f432..d57b3366 100644 --- a/src/main/resources/emulator.h +++ b/src/main/resources/emulator.h @@ -1,3 +1,1773 @@ -// metaheader for the Chisel emulator and API -#include "emulator_mod.h" -#include "emulator_api.h" +// Header for Chisel emulator module +// defines the mod_t class as well as bit operation functions + +#ifndef __IS_EMULATOR_MOD__ +#define __IS_EMULATOR_MOD__ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace std; + +typedef uint64_t val_t; +typedef int64_t sval_t; +typedef uint32_t half_val_t; +#if defined(__GNUC__) && defined(__SIZEOF_INT128__) +#define __HAVE_DUB_VAL_T__ +typedef unsigned __int128 dub_val_t; +#endif + +union flo2int_t { + float f; + val_t i; +}; + +inline float toFloat (val_t x) { + flo2int_t f2i; + f2i.i = x; + return f2i.f; +} + +inline val_t fromFloat (float x) { + flo2int_t f2i; + f2i.f = x; + return f2i.i; +} + +union dbl2int_t { + double f; + val_t i; +}; + +inline double toDouble (val_t x) { + dbl2int_t f2i; + f2i.i = x; + return f2i.f; +} + +inline val_t fromDouble (double x) { + dbl2int_t f2i; + f2i.f = x; + return f2i.i; +} + +#define TERNARY(c, t, f) ((f) ^ (((f) ^ (t)) & -(c))) + +#if defined(__GNUC__) && defined(__x86_64__) +#define TERNARY_1(c, t, f) ({ \ + val_t __res; \ + if (!__builtin_constant_p(c)) { \ + __res = (f); \ + val_t __t = (t); \ + uint8_t __c = (c); \ + asm ("testb $1, %1; cmovne %2, %0" : "+r"(__res) : "rm"(__c), "rm"(__t) : "cc"); \ + } else __res = TERNARY(c, t, f); \ + __res; }) +#else +#define TERNARY_1(c, t, f) TERNARY(c, t, f) +#endif + +#define MASK(v, c) ((v) & -(val_t)(c)) +#ifndef MIN +#define MIN(a, b) TERNARY((a) < (b), (a), (b)) +#endif +#ifndef MAX +#define MAX(a, b) TERNARY((a) > (b), (a), (b)) +#endif +#define CLAMP(a, min, max) MAX(MIN(a, max), min) + +template struct CeilLog { + static uint32_t const v = CeilLog<(x >> 1), shifted + 1, sticky | (x & 1)>::v; +}; + +template struct CeilLog<0, shifted, sticky> { + static uint32_t const v = -1; +}; + +template struct CeilLog<1, shifted, sticky> { + static uint32_t const v = sticky ? shifted + 1 : shifted; +}; + +#define val_n_bits() (sizeof(val_t)*8) +#define val_n_half_bits() (val_n_bits()/2) +#define val_all_ones() val_all_ones_or_zeroes(1) +#define val_all_ones_or_zeroes(bit) (val_t(0) - val_t(bit)) +#define val_n_words(n_bits) (1+((n_bits)-1)/val_n_bits()) +#define val_n_half_words(n_bits) (1+((n_bits)-1)/val_n_half_bits()) +#define val_top_bit(v) (val_t(v) >> (val_n_bits()-1)) +#define val_n_full_words(n_bits) ((n_bits)/val_n_bits()) +#define val_n_word_bits(n_bits) ((n_bits) % val_n_bits()) +inline val_t val_n_nibs( void ) { return val_n_bits()>>2; } +inline val_t val_half_mask( void ) { return (((val_t)1)<<(val_n_half_bits()))-1; } +inline val_t val_lo_half( val_t n_bits ) { return n_bits & val_half_mask(); } +inline val_t val_hi_half( val_t n_bits ) { return n_bits >> val_n_half_bits(); } +inline val_t val_n_rem_word_bits( val_t n_bits ) { return val_n_bits() - val_n_word_bits(n_bits); } +//inline val_t dub_val_lo_half( dub_val_t bits ) { return (val_t)bits; } +//inline val_t dub_val_hi_half( dub_val_t bits ) { return (val_t)(bits >> val_n_bits()); } + + +inline void val_to_half_vals ( val_t *fvals, half_val_t *hvals, int nf ) { + for (int i = 0; i < nf; i++) { + hvals[i*2] = val_lo_half(fvals[i]); + hvals[i*2+1] = val_hi_half(fvals[i]); + } +} +inline void half_val_to_vals ( half_val_t *hvals, val_t *vals, int nf ) { + for (int i = 0; i < nf; i++) + vals[i] = ((val_t)hvals[i*2+1] << val_n_half_bits()) | hvals[i*2]; +} + +template class dat_t; +template class datz_t; + +template int datz_eq(dat_t d1, datz_t d2); + +template inline dat_t DAT(val_t value) { + dat_t res(value); + return res; } + +template inline dat_t DAT(val_t val1, val_t val0) { + dat_t res; res.values[0] = val0; res.values[1] = val1; return res; +} + +const static char hex_digs[] = + {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; + +static void add_n (val_t d[], val_t s0[], val_t s1[], int nw, int nb) { + val_t carry = 0; + for (int i = 0; i < nw; i++) { + d[i] = s0[i] + s1[i] + carry; + carry = ((s0[i] + s1[i]) < s0[i]) || (d[i] < carry); + } +} + +static void neg_n (val_t d[], val_t s0[], int nw, int nb) { + val_t borrow = 0; + for (int i = 0; i < nw; i++) { + d[i] = -s0[i] - borrow; + borrow = s0[i] || d[i]; + } +} + +static void sub_n (val_t d[], val_t s0[], val_t s1[], int nw, int nb) { + val_t borrow = 0; + for (int i = 0; i < nw; i++) { + d[i] = s0[i] - s1[i] - borrow; + borrow = (s0[i] < (s0[i] - s1[i])) || (s0[i] - s1[i]) < d[i]; + } +} + +static void mul_n (val_t d[], val_t s0[], val_t s1[], int nb0, int nb1) { +// Adapted from Hacker's Delight, from Knuth +#if BYTE_ORDER != LITTLE_ENDIAN +# error mul_n assumes a little-endian architecture +#endif + int nbd = nb0 + nb1; + for (int i = 0; i < val_n_words(nbd); i++) + d[i] = 0; + + half_val_t* w = reinterpret_cast(d); + half_val_t* u = reinterpret_cast(s0); + half_val_t* v = reinterpret_cast(s1); + int m = val_n_half_words(nb0), n = val_n_half_words(nb1), p = val_n_half_words(nbd); + + for (int j = 0; j < n; j++) { + val_t k = 0; + for (int i = 0; i < MIN(m, p-j); i++) { + val_t t = (val_t)u[i]*v[j] + w[i+j] + k; + w[i+j] = t; + k = t >> val_n_half_bits(); + } + if (j+m < p) + w[j+m] = k; + } +} + +/** Right shift with sign extension + * d is where to store the result + * s0 is the number to be shifted + * amount is by how much it is to be shifted + * nw is the number of val_n_bits() bit words in the source + * w is the total number of bits in s0 + */ +static void rsha_n (val_t d[], const val_t s0[], const unsigned int amount, const unsigned int nw, const unsigned int w) { + + unsigned int n_shift_bits = amount % val_n_bits(); + int n_shift_words = amount / val_n_bits(); + unsigned int n_rev_shift_bits = val_n_bits() - n_shift_bits; + int is_zero_carry = n_shift_bits == 0; + // get the msb which is total bits (w) - bits in non most sig word - 1 to have 1 bit remaining + int msb = s0[nw-1] >> (w - (nw-1)*val_n_bits() - 1); + val_t carry = 0; + + // Limit the right shift to be a positive number and no more than nw in the source ie. cant shift beyond zero width + n_shift_words = (n_shift_words < 0) ? 0 : n_shift_words; + n_shift_words = (n_shift_words > nw) ? nw : n_shift_words; + + for (int i = 0; i < nw; i++) + d[i] = 0; + + for (int i = nw-1; i >= n_shift_words; i--) { + val_t val = s0[i]; + d[i - n_shift_words] = ( val >> n_shift_bits ) | carry; + carry = is_zero_carry ? 0 : val << n_rev_shift_bits; + } + + // If don't need sign extension return + if (msb == 0) { + return; + } + + // Where sign extension begins + int boundary = (w - amount); + + for (int i = nw-1; i >= 0; i--) { + int idx = i*val_n_bits(); + if (idx > boundary) { + d[i] = val_all_ones(); + } else { + // set the sign extended part of this word + d[i] = d[i] | (val_all_ones() << (boundary - idx)); + // set the bits above w to zero as they are beyond the length of s0 + d[nw-1] = d[nw-1] & (val_all_ones() >> (nw*val_n_bits() - w)); + return; + } + } +} + +static void rsh_n (val_t d[], const val_t s0[], const unsigned int amount, const unsigned int nw) { + val_t carry = 0; + unsigned int n_shift_bits = amount % val_n_bits(); + int n_shift_words = amount / val_n_bits(); + unsigned int n_rev_shift_bits = val_n_bits() - n_shift_bits; + int is_zero_carry = n_shift_bits == 0; + n_shift_words = (n_shift_words < 0) ? 0 : n_shift_words; + n_shift_words = (n_shift_words > nw) ? nw : n_shift_words; + for (int i = 0; i < n_shift_words; i++) + d[nw-i-1] = 0; + for (int i = nw-1; i >= n_shift_words; i--) { + val_t val = s0[i]; + d[i-n_shift_words] = val >> n_shift_bits | carry; + carry = is_zero_carry ? 0 : val << n_rev_shift_bits; + } +} + +static void lsh_n (val_t d[], const val_t s0[], const int amount, const int nwd, const int nws) { + val_t carry = 0; + int n_shift_bits = amount % val_n_bits(); + int n_shift_words = amount / val_n_bits(); + int n_rev_shift_bits = val_n_bits() - n_shift_bits; + int is_zero_carry = n_shift_bits == 0; + for (int i = 0; i < nwd; i++) + d[i] = 0; + for (int i = 0; i < (nws-n_shift_words); i++) { + val_t val = s0[i]; + d[i+n_shift_words] = val << n_shift_bits | carry; + carry = is_zero_carry ? 0 : val >> n_rev_shift_bits; + } +} + +static inline val_t mask_val(int n) { + val_t res = val_all_ones() >> (val_n_bits()-n); + return res; +} + +static inline void mask_n (val_t d[], int nw, int nb) { + int n_full_words = val_n_full_words(nb); + int n_word_bits = val_n_word_bits(nb); + for (int i = 0; i < n_full_words; i++) + d[i] = val_all_ones(); + for (int i = n_full_words; i < nw; i++) + d[i] = 0; + if (n_word_bits > 0) + d[n_full_words] = mask_val(n_word_bits); +} + +static inline val_t log2_1 (val_t v) { +#ifdef __GNUC__ + return TERNARY(v != 0, val_n_bits() - 1 - __builtin_clzll(v), 0); +#else + val_t r; + val_t shift; + r = (v > 0xFFFFFFFF) << 5; v >>= r; + shift = (v > 0xFFFF ) << 4; v >>= shift; r |= shift; + shift = (v > 0xFF ) << 3; v >>= shift; r |= shift; + shift = (v > 0xF ) << 2; v >>= shift; r |= shift; + shift = (v > 0x3 ) << 1; v >>= shift; r |= shift; + r |= (v >> 1); + return r; +#endif +} + +static inline val_t reverse_1 (val_t v) { + v = ((v >> 1) & 0x5555555555555555) | ((v & 0x5555555555555555) << 1); + v = ((v >> 2) & 0x3333333333333333) | ((v & 0x3333333333333333) << 2); + v = ((v >> 4) & 0x0F0F0F0F0F0F0F0F) | ((v & 0x0F0F0F0F0F0F0F0F) << 4); + v = ((v >> 8) & 0x00FF00FF00FF00FF) | ((v & 0x00FF00FF00FF00FF) << 8); + v = ((v >> 16) & 0x0000FFFF0000FFFF) | ((v & 0x0000FFFF0000FFFF) << 16); + v = ( v >> 32 ) | ( v << 32); + return v; +} + +static inline val_t priority_encode_1 (val_t v) { +#ifdef __GNUC__ + return TERNARY(v != 0, __builtin_ctzll(v), 0); +#else + if (v == 0) + return 0; + val_t r; + val_t shift; + r = !(v & 0xFFFFFFFF) << 5; v >>= r; + shift = !(v & 0xFFFF ) << 4; v >>= shift; r |= shift; + shift = !(v & 0xFF ) << 3; v >>= shift; r |= shift; + shift = !(v & 0xF ) << 2; v >>= shift; r |= shift; + shift = !(v & 0x3 ) << 1; v >>= shift; r |= shift; + shift = !(v & 0x1 ) << 0; v >>= shift; r |= shift; + return r; +#endif +} + +#define ispow2(x) (((x) & ((x)-1)) == 0) +static inline val_t nextpow2_1(val_t x) { + x--; + x |= x >> 1; + x |= x >> 2; + x |= x >> 4; + x |= x >> 8; + x |= x >> 16; + x |= x >> 32; + x++; + return x; +} + +/* +#define __FLOAT_WORD_ORDER LITTLE_ENDIAN + +static inline uint32_t log2_1_32 (uint32_t v) { + union { uint32_t u[2]; double d; } t; // temp + + t.u[__FLOAT_WORD_ORDER==LITTLE_ENDIAN] = 0x43300000; + t.u[__FLOAT_WORD_ORDER!=LITTLE_ENDIAN] = v; + t.d -= 4503599627370496.0; + return (t.u[__FLOAT_WORD_ORDER==LITTLE_ENDIAN] >> 20) - 0x3FF; +} + +static inline val_t log2_1 (val_t v) { + uint32_t r_lo = (uint32_t)v; + uint32_t r_hi = (uint32_t)(v >> 32); + return (((val_t)log2_1_32(r_hi)) << 32)|((val_t)log2_1_32(r_lo)); +} +*/ + +/* +static inline val_t log2_1 (val_t v) { + v |= (v >> 1); + v |= (v >> 2); + v |= (v >> 4); + v |= (v >> 8); + v |= (v >> 16); + v |= (v >> 32); + return ones64(v) - 1; +} +*/ + +/* +static inline val_t log2_1 (val_t v) { + val_t res = 0; + while (v >>= 1) + res++; + return res; +} +*/ + +static inline val_t log2_n (val_t s0[], int nw) { + val_t off = (nw-1)*val_n_bits(); + for (int i = nw-1; i >= 0; i--) { + val_t s0i = s0[i]; + if (s0i > 0) { + val_t res = log2_1(s0i); + return res + off; + } + off -= val_n_bits(); + } + return 0; +} + +template +struct bit_word_funs { + static void fill (val_t d[], val_t s0) { + for (int i = 0; i < nw; i++) + d[i] = s0; + } + static void fill_nb (val_t d[], val_t s0, int nb) { + mask_n(d, nw, nb); + for (int i = 0; i < nw; i++) + d[i] = d[i] & s0; + // printf("FILL-NB N\n"); + } + static void copy (val_t d[], val_t s0[], int sww) { + if (sww > nw) { + for (int i = 0; i < nw; i++) { + // printf("A I %d\n", i); fflush(stdout); + d[i] = s0[i]; + } + } else { + for (int i = 0; i < sww; i++) { + // printf("B I %d\n", i); fflush(stdout); + d[i] = s0[i]; + } + for (int i = sww; i < nw; i++) { + // printf("C I %d\n", i); fflush(stdout); + d[i] = 0; + } + } + } + static void mask (val_t d[], int nb) { + mask_n(d, nw, nb); + } + static void add (val_t d[], val_t s0[], val_t s1[], int nb) { + add_n(d, s0, s1, nw, nb); + } + static void neg (val_t d[], val_t s0[], int nb) { + neg_n(d, s0, nw, nb); + } + static void sub (val_t d[], val_t s0[], val_t s1[], int nb) { + sub_n(d, s0, s1, nw, nb); + } + static void mul (val_t d[], val_t s0[], val_t s1[], int nb0, int nb1) { + mul_n(d, s0, s1, nb0, nb1); + } + static void bit_xor (val_t d[], val_t s0[], val_t s1[]) { + for (int i = 0; i < nw; i++) + d[i] = s0[i] ^ s1[i]; + } + static void bit_and (val_t d[], val_t s0[], val_t s1[]) { + for (int i = 0; i < nw; i++) + d[i] = s0[i] & s1[i]; + } + static void bit_or (val_t d[], val_t s0[], val_t s1[]) { + for (int i = 0; i < nw; i++) + d[i] = s0[i] | s1[i]; + } + static void bit_neg (val_t d[], val_t s0[], int nb) { + val_t msk[nw]; + mask_n(msk, nw, nb); + for (int i = 0; i < nw; i++) + d[i] = ~s0[i] & msk[i]; + } + static bool ltu (val_t s0[], val_t s1[]) { + val_t diff[nw]; + sub(diff, s0, s1, nw*val_n_bits()); + return val_top_bit(diff[nw-1]); + } + static bool lt (val_t s0[], val_t s1[], int w) { + int msb_0 = (s0[1] >> (w - (nw-1)*val_n_bits() - 1)) & 0x1; + int msb_1 = (s1[1] >> (w - (nw-1)*val_n_bits() - 1)) & 0x1; + if (msb_0 != msb_1) { + return msb_0; + } else { + val_t diff[nw]; + sub(diff, s0, s1, nw*val_n_bits()); + return val_top_bit(diff[nw-1]); + } + } + static bool lteu (val_t s0[], val_t s1[]) { + val_t diff[nw]; + sub(diff, s1, s0, nw*val_n_bits()); + return !val_top_bit(diff[nw-1]); + } + static bool lte (val_t s0[], val_t s1[], int w) { + int msb_0 = (s0[1] >> (w - (nw-1)*val_n_bits() - 1)) & 0x1; + int msb_1 = (s1[1] >> (w - (nw-1)*val_n_bits() - 1)) & 0x1; + if (msb_0 != msb_1) { + return msb_0; + } else { + val_t diff[nw]; + sub(diff, s1, s0, nw*val_n_bits()); + return !val_top_bit(diff[nw-1]); + } + } + static bool eq (val_t s0[], val_t s1[]) { + for (int i = 0; i < nw; i++) + if (s0[i] != s1[i]) + return false; + return true; + } + static bool neq (val_t s0[], val_t s1[]) { + return !eq(s0, s1); + } + static void rsha (val_t d[], const val_t s0[], const int amount, const int w) { + rsha_n(d, s0, amount, nw, w); + } + static void rsh (val_t d[], const val_t s0[], const int amount) { + rsh_n(d, s0, amount, nw); + } + static void lsh (val_t d[], const val_t s0[], const int amount) { + lsh_n(d, s0, amount, nw, nw); + } + static void extract (val_t d[], const val_t s0[], const int e, const int s) { + // TODO: FINISH THIS + const int bw = e-s+1; + val_t msk[nw]; + mask_n(msk, nw, bw); + if (s == 0) { + // printf("EXT E %d S %d NW %d NB %d: ", e, s, nw, nb); + for (int i = 0; i < nw; i++) { + d[i] = s0[i] & msk[i]; + // printf("%d:%llx ", i, d[i]); + } + } else { + rsh_n(d, s0, s, nw); + // printf("EXT E %d S %d NW %d NB %d: ", e, s, nw, nb); + for (int i = 0; i < nw; i++) { + // printf("I%d:R%llx:M%llx:", i, d[i], msk[i]); + d[i] = d[i] & msk[i]; + // printf("D%llx ", d[i]); + } + } + // printf("\n"); + } + + static void inject (val_t d[], val_t s0[], int e, int s) { + // Opposite of extract: Assign s0 to a subfield of d. + const int bw = e-s+1; + val_t msk[nw]; + val_t msk_lsh[nw]; + val_t s0_lsh[nw]; + mask_n(msk, nw, bw); + lsh_n(msk_lsh, msk, s, nw, nw); + lsh_n(s0_lsh, s0, s, nw, nw); + for (int i = 0; i < nw; i++) { + d[i] = (d[i] & ~msk_lsh[i]) | (s0_lsh[i] & msk_lsh[i]); + } + } + + static void set (val_t d[], val_t s0[]) { + for (int i = 0; i < nw; i++) + d[i] = s0[i]; + } + static void log2 (val_t d[], val_t s0[]) { + d[0] = log2_n(s0, nw); + } +}; + +template <> +struct bit_word_funs<1> { + static void fill (val_t d[], val_t s0) { + d[0] = s0; + } + static void fill_nb (val_t d[], val_t s0, int nb) { + d[0] = mask_val(nb) & s0; + } + static void copy (val_t d[], val_t s0[], int sww) { + d[0] = s0[0]; + } + static void mask (val_t d[], int nb) { + d[0] = mask_val(nb); + } + static void add (val_t d[], val_t s0[], val_t s1[], int nb) { + d[0] = (s0[0] + s1[0]) & mask_val(nb); + } + static void sub (val_t d[], val_t s0[], val_t s1[], int nb) { + d[0] = (s0[0] - s1[0]) & mask_val(nb); + } + static void neg (val_t d[], val_t s0[], int nb) { + d[0] = (- s0[0]) & mask_val(nb); + } + static void mul (val_t d[], val_t s0[], val_t s1[], int nb0, int nb1) { + d[0] = s0[0] * s1[0]; + } + static bool ltu (val_t s0[], val_t s1[]) { + return (s0[0] < s1[0]); + } + static bool lt (val_t s0[], val_t s1[], int w) { + sval_t a = s0[0] << (val_n_bits() - w); + sval_t b = s1[0] << (val_n_bits() - w); + return (a < b); + } + static bool lteu (val_t s0[], val_t s1[]) { + return (s0[0] <= s1[0]); + } + static bool lte (val_t s0[], val_t s1[], int w) { + sval_t a = s0[0] << (val_n_bits() - w); + sval_t b = s1[0] << (val_n_bits() - w); + return (a <= b); + } + static void bit_neg (val_t d[], val_t s0[], int nb) { + d[0] = ~s0[0] & mask_val(nb); + } + static void bit_xor (val_t d[], val_t s0[], val_t s1[]) { + d[0] = (s0[0] ^ s1[0]); + } + static void bit_and (val_t d[], val_t s0[], val_t s1[]) { + d[0] = (s0[0] & s1[0]); + } + static void bit_or (val_t d[], val_t s0[], val_t s1[]) { + d[0] = (s0[0] | s1[0]); + } + static bool eq (val_t s0[], val_t s1[]) { + return s0[0] == s1[0]; + } + static bool neq (val_t s0[], val_t s1[]) { + return s0[0] != s1[0]; + } + static void lsh (val_t d[], const val_t s0[], const int amount) { + d[0] = (s0[0] << amount); + } + static void rsh (val_t d[], const val_t s0[], const int amount) { + d[0] = (s0[0] >> amount); + } + static void rsha (val_t d[], const val_t s0[], const int amount, const int w) { + d[0] = s0[0] << (val_n_bits() - w); + d[0] = (sval_t(d[0]) >> (val_n_bits() - w + amount)) & mask_val(w); + } + static void extract (val_t d[], const val_t s0[], const int e, const int s) { + const int bw = e-s+1; + d[0] = (s0[0] >> s) & mask_val(bw); + } + + static void inject (val_t d[], val_t s0[], int e, int s) { + // Opposite of extract: Assign s0 to a subfield of d. + const int bw = e-s+1; + val_t msk = mask_val(bw); + d[0] = ((s0[0] & msk) << s) | (d[0] & ~(msk << s)); + } + + static void set (val_t d[], val_t s0[]) { + d[0] = s0[0]; + } + static void log2 (val_t d[], val_t s0[]) { + d[0] = log2_1(s0[0]); + } +}; + +template <> +struct bit_word_funs<2> { + static void fill (val_t d[], val_t s0) { + d[0] = s0; + d[1] = s0; + } + static void fill_nb (val_t d[], val_t s0, int nb) { + d[0] = s0; + d[1] = mask_val(nb - val_n_bits()) & s0; + } + static void copy (val_t d[], val_t s0[], int sww) { + d[0] = s0[0]; + d[1] = sww > 1 ? s0[1] : 0; + } + static void mask (val_t d[], int nb) { + mask_n(d, 2, nb); + } + static void add (val_t d[], val_t x[], val_t y[], int nb) { + val_t x0 = x[0]; + val_t sum0 = x0 + y[0]; + val_t carry0 = (sum0 < x0); + d[0] = sum0; + val_t sum1 = x[1] + y[1] + carry0; + d[1] = sum1; + } + static void sub (val_t d[], val_t s0[], val_t s1[], int nb) { + val_t d0 = s0[0] - s1[0]; + d[1] = s0[1] - s1[1] - (s0[0] < d0); + d[0] = d0; + } + static void neg (val_t d[], val_t s0[], int nb) { + val_t d0 = -s0[0]; + d[1] = -s0[1] - (s0[0] != 0); + d[0] = d0; + } + static void mul (val_t d[], val_t s0[], val_t s1[], int nb0, int nb1) { +#ifdef __HAVE_DUB_VAL_T__ + dub_val_t a = s0[0], b = s1[0]; + if (nb0 > val_n_bits()) a |= dub_val_t(s0[1]) << val_n_bits(); + if (nb1 > val_n_bits()) b |= dub_val_t(s1[1]) << val_n_bits(); + dub_val_t res = a * b; + d[0] = res; + d[1] = res >> val_n_bits(); +#else + mul_n(d, s0, s1, nb0, nb1); +#endif + } + static bool ltu (val_t s0[], val_t s1[]) { + return ((s0[1] < s1[1]) | (s0[1] == s1[1] & s0[0] < s1[0])); + } + static bool lt (val_t s0[], val_t s1[], int w) { + int msb_0 = (s0[1] >> (w - val_n_bits() - 1)) & 0x1; + int msb_1 = (s1[1] >> (w - val_n_bits() - 1)) & 0x1; + int cond = msb_0 ^ msb_1; + return (cond && msb_0) + || (!cond && ((s0[1] < s1[1]) | (s0[1] == s1[1] & s0[0] < s1[0]))); + } + static bool lteu (val_t s0[], val_t s1[]) { + return ((s0[1] < s1[1]) | (s0[1] == s1[1] & s0[0] <= s1[0])); + } + static bool lte (val_t s0[], val_t s1[], int w) { + int msb_0 = (s0[1] >> (w - val_n_bits() - 1)) & 0x1; + int msb_1 = (s1[1] >> (w - val_n_bits() - 1)) & 0x1; + int cond = msb_0 ^ msb_1; + return (cond && msb_0) + || (!cond && ((s0[1] < s1[1]) | (s0[1] == s1[1] & s0[0] <= s1[0]))); + } + static void bit_xor (val_t d[], val_t s0[], val_t s1[]) { + d[0] = (s0[0] ^ s1[0]); + d[1] = (s0[1] ^ s1[1]); + } + static void bit_and (val_t d[], val_t s0[], val_t s1[]) { + d[0] = (s0[0] & s1[0]); + d[1] = (s0[1] & s1[1]); + } + static void bit_or (val_t d[], val_t s0[], val_t s1[]) { + d[0] = (s0[0] | s1[0]); + d[1] = (s0[1] | s1[1]); + } + static void bit_neg (val_t d[], val_t s0[], int nb) { + d[0] = ~s0[0]; + d[1] = ~s0[1] & mask_val(nb - val_n_bits()); + } + static bool eq (val_t s0[], val_t s1[]) { + return (s0[0] == s1[0]) & (s0[1] == s1[1]); + } + static bool neq (val_t s0[], val_t s1[]) { + return (s0[0] != s1[0]) | (s0[1] != s1[1]); + } + static void extract (val_t d[], const val_t s0[], const int e, const int s) { + val_t msk[2]; + const int bw = e-s+1; + mask_n(msk, 2, bw); + if (s == 0) { + d[0] = s0[0] & msk[0]; + d[1] = s0[1] & msk[1]; + } else { + rsh(d, s0, s); + d[0] = d[0] & msk[0]; + d[1] = d[1] & msk[1]; + } + } + + static void inject (val_t d[], const val_t s0[], const int e, const int s) { + // Opposite of extract: Assign s0 to a subfield of d. + const int bw = e-s+1; + val_t msk[2]; + val_t msk_lsh[2]; + val_t s0_lsh[2]; + mask_n(msk, 2, bw); + lsh_n(msk_lsh, msk, s, 2, 2); + lsh_n(s0_lsh, s0, s, 2, 2); + d[0] = (d[0] & ~msk_lsh[0]) | (s0_lsh[0] & msk_lsh[0]); + d[1] = (d[1] & ~msk_lsh[1]) | (s0_lsh[1] & msk_lsh[1]); + } + + static void rsha (val_t d[], const val_t s0[], const int amount, const int w) { + sval_t hi = s0[1] << (2*val_n_bits() - w); + if (amount >= val_n_bits()) { + d[0] = hi >> (amount - w + val_n_bits()); + d[1] = hi >> (val_n_bits() - 1); + d[1] = d[1] >> (2*val_n_bits() - w); + } else if (amount == 0) { + d[0] = s0[0]; + d[1] = s0[1]; + } else { + int s = 2*val_n_bits() - w + amount; + d[0] = s0[0] >> amount; + d[0] = d[0] | ((hi >> (2*val_n_bits() - w)) << (val_n_bits() - amount)); + d[1] = hi >> (s >= val_n_bits() ? val_n_bits()-1 : s); + d[1] = d[1] & mask_val(w - val_n_bits()); + } + } + static void rsh (val_t d[], const val_t s0[], const int amount) { + if (amount >= val_n_bits()) { + d[1] = 0; + d[0] = s0[1] >> (amount - val_n_bits()); + } else if (amount == 0) { + d[0] = s0[0]; + d[1] = s0[1]; + } else { + d[1] = s0[1] >> amount; + d[0] = (s0[1] << (val_n_bits() - amount)) | (s0[0] >> amount); + } + } + static void lsh (val_t d[], const val_t s0[], const int amount) { + if (amount == 0) + { + d[1] = s0[1]; + d[0] = s0[0]; + } else if (amount >= val_n_bits()) { + d[1] = s0[0] << (amount - val_n_bits()); + d[0] = 0; + } else { + d[1] = (s0[1] << amount) | (s0[0] >> (val_n_bits() - amount)); + d[0] = (s0[0] << amount); + } + } + static void set (val_t d[], val_t s0[]) { + d[0] = s0[0]; + d[1] = s0[1]; + } + static void log2 (val_t d[], val_t s0[]) { + val_t s01 = s0[1]; + if (s01 > 0) + d[0] = log2_1(s01) + val_n_bits(); + else + d[0] = log2_1(s0[0]); + // d[0] = log2_n(s0, 2); + } +}; +template <> +struct bit_word_funs<3> { + static void fill (val_t d[], val_t s0) { + d[0] = s0; + d[1] = s0; + d[2] = s0; + } + static void fill_nb (val_t d[], val_t s0, int nb) { + d[0] = s0; + d[1] = s0; + d[2] = mask_val(nb - 2*val_n_bits()) & s0; + } + static void copy (val_t d[], val_t s0[], int sww) { + d[0] = s0[0]; + d[1] = sww > 1 ? s0[1] : 0; + d[2] = sww > 2 ? s0[2] : 0; + } + static void mask (val_t d[], int nb) { + mask_n(d, 3, nb); + } + static void add (val_t d[], val_t s0[], val_t s1[], int nb) { + add_n(d, s0, s1, 3, nb); + } + static void sub (val_t d[], val_t s0[], val_t s1[], int nb) { + sub_n(d, s0, s1, 3, nb); + } + static void neg (val_t d[], val_t s0[], int nb) { + neg_n(d, s0, 3, nb); + } + static void mul (val_t d[], val_t s0[], val_t s1[], int nb0, int nb1) { + mul_n(d, s0, s1, nb0, nb1); + } + static bool ltu (val_t s0[], val_t s1[]) { + return ((s0[2] < s1[2]) | ((s0[2] == s1[2]) & ((s0[1] < s1[1]) | ((s0[1] == s1[1]) & (s0[0] < s1[0]))))); + } + static bool lt (val_t s0[], val_t s1[], int w) { + int msb_0 = (s0[1] >> (w - 2*val_n_bits() - 1)) & 0x1; + int msb_1 = (s1[1] >> (w - 2*val_n_bits() - 1)) & 0x1; + int cond = msb_0 ^ msb_1; + return (cond && msb_0) + || (!cond && (((s0[2] < s1[2]) | ((s0[2] == s1[2]) & ((s0[1] < s1[1]) | ((s0[1] == s1[1]) & (s0[0] < s1[0]))))))); + } + static bool lteu (val_t s0[], val_t s1[]) { + return ((s0[2] < s1[2]) | ((s0[2] == s1[2]) & ((s0[1] < s1[1]) | ((s0[1] == s1[1]) & (s0[0] <= s1[0]))))); + } + static bool lte (val_t s0[], val_t s1[], int w) { + int msb_0 = (s0[1] >> (w - 2*val_n_bits() - 1)) & 0x1; + int msb_1 = (s1[1] >> (w - 2*val_n_bits() - 1)) & 0x1; + int cond = msb_0 ^ msb_1; + return (cond && msb_0) + || (!cond && ((s0[2] < s1[2]) | ((s0[2] == s1[2]) & ((s0[1] < s1[1]) | ((s0[1] == s1[1]) & (s0[0] <= s1[0])))))); + } + static void bit_xor (val_t d[], val_t s0[], val_t s1[]) { + d[0] = (s0[0] ^ s1[0]); + d[1] = (s0[1] ^ s1[1]); + d[2] = (s0[2] ^ s1[2]); + } + static void bit_and (val_t d[], val_t s0[], val_t s1[]) { + d[0] = (s0[0] & s1[0]); + d[1] = (s0[1] & s1[1]); + d[2] = (s0[2] & s1[2]); + } + static void bit_or (val_t d[], val_t s0[], val_t s1[]) { + d[0] = (s0[0] | s1[0]); + d[1] = (s0[1] | s1[1]); + d[2] = (s0[2] | s1[2]); + } + static void bit_neg (val_t d[], val_t s0[], int nb) { + d[0] = ~s0[0]; + d[1] = ~s0[1]; + d[2] = ~s0[2] & mask_val(nb - 2*val_n_bits()); + } + static bool eq (val_t s0[], val_t s1[]) { + return (s0[0] == s1[0]) & (s0[1] == s1[1]) & (s0[2] == s1[2]); + } + static bool neq (val_t s0[], val_t s1[]) { + return (s0[0] != s1[0]) | (s0[1] != s1[1]) | (s0[2] != s1[2]); + } + static void extract (val_t d[], const val_t s0[], const int e, const int s) { + val_t msk[3]; + const int bw = e-s+1; + mask_n(msk, 3, bw); + if (s == 0) { + d[0] = s0[0] & msk[0]; + d[1] = s0[1] & msk[1]; + d[2] = s0[2] & msk[2]; + } else { + rsh(d, s0, s); + d[0] = d[0] & msk[0]; + d[1] = d[1] & msk[1]; + d[2] = d[2] & msk[2]; + } + } + + static void inject (val_t d[], const val_t s0[], const int e, const int s) { + const int bw = e-s+1; + val_t msk[3]; + val_t msk_lsh[3]; + val_t s0_lsh[3]; + mask_n(msk, 3, bw); + lsh_n(msk_lsh, msk, s, 3, 3); + lsh_n(s0_lsh, s0, s, 3, 3); + d[0] = (d[0] & ~msk_lsh[0]) | (s0_lsh[0] & msk_lsh[0]); + d[1] = (d[1] & ~msk_lsh[1]) | (s0_lsh[1] & msk_lsh[1]); + d[2] = (d[2] & ~msk_lsh[2]) | (s0_lsh[2] & msk_lsh[2]); + } + + static void rsha (val_t d[], const val_t s0[], const int amount, const int w) { + rsha_n(d, s0, amount, 3, w); + } + static void rsh (val_t d[], const val_t s0[], const int amount) { + rsh_n(d, s0, amount, 3); + } + static void lsh (val_t d[], const val_t s0[], const int amount) { + lsh_n(d, s0, amount, 3, 3); + } + static void log2 (val_t d[], val_t s0[]) { + d[0] = log2_n(s0, 3); + } + static void set (val_t d[], val_t s0[]) { + d[0] = s0[0]; + d[1] = s0[1]; + d[2] = s0[2]; + } +}; + +static val_t __rand_val(val_t* seed) { + val_t x = *seed; + *seed = (x << 1) ^ (-(sval_t(x) < 0) & 0x1B); + return x; +} + +template +class dat_t { + public: + const static int n_words = ((w - 1) / 64) + 1; + // const static int n_words = (w >> CeilLog::v) + 1; + val_t values[n_words]; + inline int width ( void ) { return w; } + inline int n_words_of ( void ) { return n_words; } + inline bool to_bool ( void ) { return lo_word() != 0; } + inline val_t lo_word ( void ) { return values[0]; } + inline unsigned long to_ulong ( void ) { return (unsigned long)lo_word(); } + + std::string to_str () { + std::string rres, res; + int nn = (int)ceilf(w / 4.0); + for (int i = 0; i < n_words; i++) { + int n_nibs = nn < val_n_nibs() ? nn : val_n_nibs(); + for (int j = 0; j < n_nibs; j++) { + uint8_t nib = (values[i] >> (j*4))&0xf; + rres.push_back(hex_digs[nib]); + } + nn -= val_n_bits()/4; + } + // No prefix + // res.push_back('0'); + // res.push_back('x'); + for (int i = 0; i < rres.size(); i++) + res.push_back(rres[rres.size()-i-1]); + return res; + } + void randomize(val_t* seed) { + for (int i = 0; i < n_words; i++) + values[i] = __rand_val(seed); + if (val_n_word_bits(w)) + values[n_words-1] &= mask_val(val_n_word_bits(w)); + } + inline dat_t () { + } + template + inline dat_t (const dat_t& src) { + bit_word_funs::copy(values, (val_t*)src.values, src.n_words); + if (sw != w && val_n_word_bits(w)) + values[n_words-1] &= mask_val(val_n_word_bits(w)); + } + inline dat_t (const dat_t& src) { + bit_word_funs::set(values, (val_t*)src.values); + } + static inline dat_t from_vals(val_t val[n_words]) { + dat_t res; + for (int i = 0; i < n_words; i++) + res.values[i] = val[i]; + return res; + } + inline dat_t (val_t val) { + values[0] = val; + for (int i = 1; i < n_words; i++) + values[i] = 0; + } + template + dat_t mask(dat_t fill, int n) { + dat_t res; + bit_word_funs::mask(res.values, n); + return res; + } + template + dat_t mask(int n) { + dat_t res; + return res.mask(*this, n); + } + template + inline dat_t mask(void) { + dat_t res = mask(n); + return res; + } + val_t operator [] (size_t i) { + return values[i]; + } + dat_t operator + ( dat_t o ) { + dat_t res; + bit_word_funs::add(res.values, values, o.values, w); + return res; + } + dat_t operator - ( dat_t o ) { + dat_t res; + bit_word_funs::sub(res.values, values, o.values, w); + return res; + } + dat_t operator - ( ) { + return ~(*this) + DAT(1); + } + template + dat_t operator * ( dat_t o ) { + dat_t res; + bit_word_funs::mul(res.values, values, o.values, w, w2); + return res; + } + template + dat_t fix_times_fix( dat_t o ) { + if (w+w2 <= val_n_bits()) { + sval_t a = sval_t(values[0] << (val_n_bits()-w)) >> (val_n_bits()-w); + sval_t b = sval_t(o.values[0] << (val_n_bits()-w2)) >> (val_n_bits()-w2); + return dat_t((a * b) & mask_val(w+w2)); + } else { + val_t sgn_a = msb(); + dat_t abs_a = sgn_a ? -(*this) : (*this); + val_t sgn_b = o.msb(); + dat_t abs_b = sgn_b ? -o : o; + dat_t res = abs_a * abs_b; + return (sgn_a ^ sgn_b) ? -res : res; + } + } + dat_t operator / ( dat_t o ) { + dat_t res(0); + if (o == 0) { + res.fill_bit(1); + } else if (n_words == 1) { + res.values[0] = values[0] / o.values[0]; + } else { + dat_t<2*w> p = *this, d = o; + d = d << w; + + for (int i = w-1; i >= 0; i--) { + p = p << 1; + if (p >= d) { + p = p - d; + res.values[i / val_n_bits()] |= val_t(1) << (i % val_n_bits()); + } + } + } + return res; + } + dat_t operator % ( dat_t o ) { + return *this - *this / o * o; + } + dat_t ufix_times_fix( dat_t o ) { + return o.fix_times_ufix(*this); + } + template + dat_t fix_times_ufix( dat_t o ) { + if (w+w2 <= val_n_bits()) { + sval_t a = sval_t(values[0] << (val_n_bits()-w)) >> (val_n_bits()-w); + return dat_t((a * o.values[0]) & mask_val(w+w2)); + } else { + val_t sgn_a = msb(); + dat_t abs_a = sgn_a ? -(*this) : (*this); + dat_t res = abs_a * o; + return sgn_a ? -res : res; + } + } + inline bool operator < ( dat_t o ) { + return bit_word_funs::ltu(values, o.values); + } + inline bool operator <= ( dat_t o ) { + return bit_word_funs::lteu(values, o.values); + } + inline bool operator > ( dat_t o ) { + return o < *this; + } + inline bool operator >= ( dat_t o ) { + return o <= *this; + } + inline bool lt ( dat_t o ) { + return bit_word_funs::lt(values, o.values, w); + } + inline bool lte ( dat_t o ) { + return bit_word_funs::lte(values, o.values, w); + } + inline bool gt ( dat_t o ) { + return o.lt(*this); + } + inline bool gte ( dat_t o ) { + return o.lte(*this); + } + dat_t operator ^ ( dat_t o ) { + dat_t res; + bit_word_funs::bit_xor(res.values, values, o.values); + return res; + } + dat_t operator & ( dat_t o ) { + dat_t res; + bit_word_funs::bit_and(res.values, values, o.values); + return res; + } + dat_t operator | ( dat_t o ) { + dat_t res; + bit_word_funs::bit_or(res.values, values, o.values); + return res; + } + dat_t operator ~ ( void ) { + dat_t res; + bit_word_funs::bit_neg(res.values, values, w); + return res; + } + inline dat_t<1> operator ! ( void ) { + return DAT<1>(!lo_word()); + } + dat_t<1> operator && ( dat_t<1> o ) { + return DAT<1>(lo_word() & o.lo_word()); + } + dat_t<1> operator || ( dat_t<1> o ) { + return DAT<1>(lo_word() | o.lo_word()); + } + bool operator == ( dat_t o ) { + return bit_word_funs::eq(values, o.values); + } + bool operator == ( datz_t o ) { + return o == *this; + } + bool operator != ( dat_t o ) { + return bit_word_funs::neq(values, o.values); + } + dat_t operator << ( int amount ) { + dat_t res; + bit_word_funs::lsh(res.values, values, amount); + if (val_n_word_bits(w)) + res.values[n_words-1] &= mask_val(val_n_word_bits(w)); + return res; + } + inline dat_t operator << ( dat_t o ) { + return *this << o.lo_word(); + } + dat_t operator >> ( int amount ) { + dat_t res; + bit_word_funs::rsh(res.values, values, amount); + return res; + } + inline dat_t operator >> ( dat_t o ) { + return *this >> o.lo_word(); + } + dat_t rsha ( const dat_t o) { + dat_t res; + int amount = o.lo_word(); + bit_word_funs::rsha(res.values, values, amount, w); + return res; + } + dat_t& operator = ( dat_t o ) { + bit_word_funs::set(values, o.values); + return *this; + } + // Set values (typically to 0). + dat_t& operator = ( val_t val ) { + for (int i = 0; i < n_words; i++) + values[i] = val; + return *this; + } + dat_t fill_bit( val_t bit ) { + dat_t res; + val_t word = 0L - bit; + bit_word_funs::fill_nb(res.values, word, w); + return res; + } + // TODO: SPEED THIS UP + dat_t fill_byte( val_t byte, int nb, int n ) { + dat_t res; + bit_word_funs::fill(res.values, 0L); + for (size_t i = 0; i < n; i++) + res = (res << nb) | byte; + return res; + } + template + dat_t fill( void ) { + // TODO: GET RID OF IF'S + dat_t res; + if (w == 1) { + return res.fill_bit(lo_word()); + } else { + return res.fill_byte(lo_word(), w, n); + } + } + template + dat_t fill( dat_t n ) { + // TODO: GET RID OF IF'S + dat_t res; + if (w == 1) { + return res.fill_bit(lo_word()&1); + } else { + return res.fill_byte(lo_word(), w, n); + } + } + template + dat_t extract() { + dat_t res; + int i; + for (i = 0; i < val_n_full_words(dw); i++) + res.values[i] = values[i]; + if (val_n_word_bits(dw)) + res.values[i] = values[i] & mask_val(val_n_word_bits(dw)); + return res; + } + template + dat_t extract(const val_t e, const val_t s) { + const int bw = e-s+1; + dat_t msk = mask(bw); + dat_t x = (*this >> s); + return x & msk; + } + template + inline dat_t extract(const dat_t e, const dat_t s) { + return extract(e.lo_word(), s.lo_word()); + } + + template + dat_t inject(dat_t src, val_t e, val_t s) { + // Modify this.values in place. + dat_t inject_src(src); // Enlarged if needed to match inject_dst + bit_word_funs::inject(values, inject_src.values, e, s); + return *this; + } + + template + inline dat_t inject(dat_t src, dat_t e, dat_t s) { + return inject(src, e.lo_word(), s.lo_word()); + } + + + template + inline dat_t log2() { + dat_t res; + bit_word_funs::log2(res.values, values); + return res; + } + inline val_t bit(val_t b) { + return (values[val_n_full_words(b)] >> val_n_word_bits(b)) & 1; + } + inline val_t msb() { + return values[n_words-1] >> val_n_word_bits(w-1); + } + template + inline dat_t<1> bit(dat_t b) { + return bit(b.lo_word()); + } +}; + +class clk_t: public dat_t<1> { +public: + size_t len; + size_t cnt; +}; + +template +std::string dat_to_str(const dat_t& x) { + char s[w]; + s[dat_to_str(s, x)] = 0; + return s; +} + +static __inline__ int n_digits(int w, int base) { + return (int)ceil(log(2)/log(base)*w); +} + +template +int dat_to_str(char* s, dat_t x, int base = 16, char pad = '0') { + int n_digs = n_digits(w, base); + int j = n_digs-1, digit; + + do { + if (ispow2(base)) { + digit = x.lo_word() & (base-1); + x = x >> log2_1(base); + } else { + digit = (x % base).lo_word(); + x = x / base; + } + s[j] = (digit >= 10 ? 'a'-10 : '0') + digit; + } while (--j >= 0 && x != 0); + + for ( ; j >= 0; j--) + s[j] = pad; + + return n_digs; +} + +static __inline__ int dat_to_str(char* s, val_t x, int base = 16, char pad = '0') { + return dat_to_str(s, dat_t(x), base, pad); +} + +template +int fix_to_str(char* s, dat_t x, int base = 16, char pad = '0') { + bool neg = x.msb(); + s[0] = neg; + int len = dat_to_str(s+1, neg ? -x : x, base, pad); + return len+1; +} + +static __inline__ int flo_digits(int m, int e) { + return 2 + n_digits(m, 10) + 2 + n_digits(e, 10); +} + +template +int flo_to_str(char* s, dat_t x, char pad = ' ') { + char buf[1000]; + int n_digs = (w == 32) ? flo_digits(23, 8) : flo_digits(52, 11); + double val = (w == 32) ? toFloat(x.values[0]) : toDouble(x.values[0]); + // sprintf(buf, "%d %d%*e", w, n_digs, n_digs, val); + sprintf(buf, "%*e", n_digs, val); + assert(strlen(buf) == n_digs); + for (int i = 0; i < n_digs; i++) + s[i] = buf[i]; + s[n_digs] = 0; + // printf("N-DIGS = %d BUF %lu PAD %lu\n", n_digs, strlen(buf), n_digs-strlen(buf)); + // return strlen(buf); + return n_digs; +} + +template +int dat_as_str(char* s, const dat_t& x) { + int i, j; + for (i = 0, j = (w/8-1)*8; i < w/8; i++, j -= 8) { + char ch = x.values[j/val_n_bits()] >> (j % val_n_bits()); + if (ch == 0) break; + s[i] = ch; + } + for ( ; i < w/8; i++) + s[i] = ' '; + return w/8; +} + +static __inline__ int dat_as_str(char* s, val_t x) { + return dat_as_str(s, dat_t(x)); +} + +#if __cplusplus >= 201103L +static void __attribute__((unused)) dat_format(char* s, const char* fmt) +{ + for (char c; (c = *fmt); fmt++) { + if (c == '%' && *++fmt != '%') + abort(); + *s++ = c; + } + // Ensure the string is null terminated. + *s = '\0'; +} + +template +static void dat_format(char* s, const char* fmt, T value, Args... args) +{ + while (*fmt) { + if (*fmt == '%') { + switch(fmt[1]) { + case 'e': s += flo_to_str(s, value, ' '); break; + case 'h': s += dat_to_str(s, value, 16, '0'); break; + case 'b': s += dat_to_str(s, value, 2, '0'); break; + case 'd': s += dat_to_str(s, value, 10, ' '); break; + case 's': s += dat_as_str(s, value); break; + case '%': *s++ = '%'; break; + default: abort(); + } + return dat_format(s, fmt + 2, args...); + } else { + *s++ = *fmt++; + } + } + // Ensure the string is null terminated. + *s = '\0'; +} + +template +static dat_t dat_format(const char* fmt, Args... args) +{ +#if BYTE_ORDER != LITTLE_ENDIAN +# error dat_format assumes a little-endian architecture +#endif + // This makes so many assumptions it can't possibly work in the general case. + char str[w/8+1]; + dat_format(str, fmt, args...); + assert(strlen(str) < sizeof(str)); + + dat_t res; + res.values[res.n_words-1] = 0; + for (int i = 0; i < w/8; i++) + ((char*)res.values)[w/8-1-i] = str[i]; + return res; +} + +template +static ssize_t dat_fprintf(FILE *f, const char* fmt, Args... args) +{ + // Be generous. It doesn't really cost us anything. + char str[w*2+1]; + dat_format(str, fmt, args...); + ssize_t len = strlen(str); + assert(len < sizeof(str)); + return fwrite(str, 1, len, f); +} + +template +static ssize_t dat_prints(std::ostream& s, const char* fmt, Args... args) +{ + // This failed silently trying to print Flo's when the size was w/8+1. + // Be generous. It doesn't really cost us anything. + char str[w*2+1]; + dat_format(str, fmt, args...); + ssize_t len = strlen(str); + assert(len < sizeof(str)); + s.write(str, len); + ssize_t ret = s.good() ? len : -1; + return ret; +} +#endif /* C++11 */ + +template inline dat_t DAT(dat_t dat) { + dat_t res(dat); + return res; +} + +template inline dat_t LIT(val_t value) { + return DAT(value); +} + +template +inline dat_t mux ( dat_t<1> t, dat_t c, dat_t a ) { + dat_t mask; + bit_word_funs::fill(mask.values, -t.lo_word()); + return a ^ ((a ^ c) & mask); +} + +template +class datz_t : public dat_t { + public: + dat_t mask; + inline bool operator == ( dat_t o ) { + dat_t masked = (o & mask); + return (o & mask) == (dat_t)*this; + } +}; + +template datz_t inline LITZ(val_t value, val_t mask) { + datz_t res; res.mask.values[0] = mask; res.values[0] = value; return res; +} + +template < int w, int w1, int w2 > +inline dat_t cat(dat_t d1, dat_t d2) { + if (w <= val_n_bits() && w1 + w2 == w) + return DAT(d1.values[0] << (w2 & (val_n_bits()-1)) | d2.values[0]); + return DAT((DAT(d1) << w2) | DAT(d2)); +} + +template < int w1 > +inline dat_t<1> reduction_and(dat_t d) { + return DAT<1>(d == ~DAT(0)); +} + +template < int w1 > +inline dat_t<1> reduction_or(dat_t d) { + return DAT<1>(d != DAT(0)); +} + +// I am O(n) where n is number of bits in val_t. Future optimization would be log(n). +template < int w1 > +inline dat_t<1> reduction_xor(dat_t d) { + dat_t<1> res = DAT<1>(0); + val_t word = d.values[0]; + + for (int i = 1; i < d.n_words_of(); i++) + word ^= d.values[i]; + for (int i = 0; i < sizeof(val_t)*8; i++) { + res = res ^ DAT<1>(word & 1); + word = word >> 1; + } + + return res; +} + +template +class mem_t { + public: + dat_t contents[d]; + val_t dummy_seed; + val_t* seedp; + + int width() { + return w; + } + int length() { + return d; + } + + template + dat_t get (dat_t idx) { + return get(idx.lo_word() & (nextpow2_1(d)-1)); + } + dat_t get (val_t idx) { + if (/*!ispow2(d) &&*/ idx >= d) { + dat_t res; + res.randomize(seedp); + return res; + } + return contents[idx]; + } + val_t get (val_t idx, int word) { + if (/*!ispow2(d) &&*/ idx >= d) + return __rand_val(seedp) & ((word == val_n_full_words(w) && val_n_word_bits(w)) ? mask_val(w) : -1L); + return contents[idx].values[word]; + } + + template + void put (dat_t idx, dat_t val) { + put(idx.lo_word(), val); + } + void put (val_t idx, dat_t val) { + if (/*ispow2(d) ||*/ idx < d) + contents[idx] = val; + } + void put (val_t idx, int word, val_t val) { + if (/*ispow2(d) ||*/ idx < d) + contents[idx].values[word] = val; + } + + void print ( void ) { + for (int j = 0; j < d/4; j++) { + for (int i = 0; i < 4; i++) { + int idx = j*4+i; + printf("|%2d: %16llx| ", idx, contents[idx].lo_word()); + } + printf("\n"); + } + } + mem_t () { + dummy_seed = 1; + seedp = &dummy_seed; + for (int i = 0; i < d; i++) + contents[i] = DAT(0); + } + void randomize(val_t* seed) { + seedp = seed; + for (int i = 0; i < d; i++) + contents[i].randomize(seed); + } + size_t read_hex(const char *hexFileName) { + ifstream ifp(hexFileName); + if (ifp.fail()) { + printf("[error] Unable to open hex data file %s\n", hexFileName); + return -1; + } + std::string hex_line; + dat_t hex_dat; + for (int addr = 0; addr < d && !ifp.eof();) { + getline(ifp, hex_line); + if (dat_from_hex(hex_line, hex_dat) > 0) { + contents[addr++] = hex_dat; + } + } + ifp.close(); + return 0; + } +}; + +static __attribute__((unused)) char hex_to_char[] = "0123456789abcdef"; + +static int char_to_hex[] = { + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,-1,-1,-1,-1,-1,-1, + -1,10,11,12,13,14,15,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,10,11,12,13,14,15,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1 }; + +// dat_from_hex: Read a hex value from a std::string into a given dat_t variable. +// Author: B. Richards, for parsing data formatted for Verilog $readmemh +// Arguments: +// hex_line A string containing hex numbers with embedded x, _ characters +// res A dat_t object to fill in with a return value +// offset Starting index in hex_line +// Return value: +// Success: returns next character offset +// Fail: 0 +template +size_t dat_from_hex(std::string hex_line, dat_t& res, size_t offset = 0) { + size_t first_digit, last_digit, comment; + + // Scan for the hex data bounds. + bool neg = hex_line[offset] == '-'; + comment = hex_line.find_first_of("/", offset); + first_digit = hex_line.find_first_of("0123456789abcdefABCDEF", offset); + if (first_digit == std::string::npos) return 0; + if (comment != std::string::npos && comment < first_digit) return 0; + last_digit = hex_line.find_first_not_of("0123456789abcdefABCDEF_xX", first_digit); + if (last_digit == std::string::npos) { + last_digit = hex_line.length() - 1; + } else { + last_digit--; + } + + size_t rem = w % 64; + val_t mask = (rem) ? (1L << rem) - 1 : -1L; + // Convert the hex data to a dat_t, from right to left. + int digit_val; + val_t word_accum = 0; + int digit, w_index, bit; + for (digit = last_digit, w_index = 0, bit = 0; digit >= (int)first_digit && w_index < res.n_words; digit--) { + digit_val = char_to_hex[hex_line[digit]]; + if (digit_val >= 0) { + word_accum |= ((val_t)digit_val) << bit; + bit += 4; + if (bit == 64) { + if (w_index == res.n_words - 1) word_accum &= mask; + res.values[w_index++] = word_accum; + word_accum = 0L; + bit = 0; + } + } + } + if (bit != 0) { + if (w_index == res.n_words - 1) word_accum &= mask; + res.values[w_index++] = word_accum; + } + while(w_index < res.n_words) res.values[w_index++] = 0L; + if (neg) res = res - 1; + // Return a pointer to the character after the converted value. + return last_digit + 1; +} + +#pragma GCC push_options +#pragma GCC optimize ("no-stack-protector") + +template +void dat_dump (FILE* f, const dat_t& val, val_t name) { + size_t pos = 0; + char str[1 + w + 1 + s + 1]; + + str[pos++] = 'b'; + for (int i = 0; i < w; i++) + str[pos + w-i-1] = '0' + ((val.values[i/val_n_bits()] >> (i%val_n_bits())) & 1); + pos += w; + + str[pos++] = ' '; + for (int i = 0; i < s; i++) { + str[pos++] = name; + name >>= 8; + } + str[pos++] = '\n'; + + fwrite(str, 1, sizeof(str), f); +} + +#pragma GCC pop_options + +inline std::string read_tok(FILE* f) { + std::string res; + bool is_skipping = true; + for (;;) { + char c = fgetc(f); + if (feof(f)) + return res; + if (is_skipping) { + if (char_to_hex[c] != -1) { + res.push_back(c); + is_skipping = false; + } + } else { + if (char_to_hex[c] == -1) { + ungetc(c, f); + return res; + } + res.push_back(c); + } + } +} + +template +void dat_dump(FILE* file, const mem_t& val, val_t name) { +} + +template mem_t MEM( void ); + +class mod_t { + public: + mod_t(): dumpfile(NULL), timestep(0L) { } + virtual ~mod_t() {} + virtual void init ( val_t rand_init=false ) = 0; + virtual void clock_lo ( dat_t<1> reset, bool assert_fire=true ) = 0; + virtual void clock_hi ( dat_t<1> reset ) = 0; + virtual int clock ( dat_t<1> reset ) = 0; + virtual void setClocks ( std::vector< int >& periods ) { }; + + virtual void print ( FILE* f ) { }; + virtual void print ( std::ostream& s ) { }; + virtual void dump ( FILE* f, val_t t , dat_t<1> reset=LIT<1>(0) ) { }; + + void set_dumpfile(FILE* f) { dumpfile = f; } + + val_t timestep; + + void dump ( dat_t<1> reset=LIT<1>(0) ) { + if (dumpfile != NULL) dump(dumpfile, timestep, reset); + timestep += 1; + } + + protected: + FILE* dumpfile; +}; + +#define ASSERT(cond, msg) { \ + if (!(cond)) \ + throw std::runtime_error("Assertion failed: " msg); \ +} + +#define WARN(cond, msg) { \ + if (!(cond)) \ + printf("Assertion failed: %s\n", msg); \ +} + +#endif diff --git a/src/main/resources/emulator_api.h b/src/main/resources/emulator_api.h deleted file mode 100644 index ea245a0e..00000000 --- a/src/main/resources/emulator_api.h +++ /dev/null @@ -1,684 +0,0 @@ -// Header for Chisel emulator API -#ifndef __IS_EMULATOR_API__ -#define __IS_EMULATOR_API__ - -#include "emulator_mod.h" - -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wunused-function" -#pragma GCC diagnostic ignored "-Wsign-compare" -#pragma GCC diagnostic ignored "-Wunused-parameter" -#pragma GCC diagnostic ignored "-Wunused-variable" - -#include -#include -#include -#include -#include - -/** - * Converts an integer to a std::string without needing additional libraries - * or C++11. - */ -static std::string itos(int in) { - std::stringstream out; - out << in; - return out.str(); -} - -/** - * Copy one val_t array to another. - * nb must be the exact number of bits the val_t represents. - */ -static __attribute__((unused)) void val_cpy(val_t* dst, val_t* src, int nb) { - for (int i=0; i -bool dat_from_str(std::string in, dat_t& res, int pos = 0) { - int radix = 10; - int negate = 0; - - /* Handle leading minus sign. */ - if (!in.substr(pos, 1).compare("-")) { - pos++; - negate = 1; - } - - if (!in.substr(pos, 1).compare("d")) { - radix = 10; - pos++; - } else if (!in.substr(pos, 1).compare("h") - || !in.substr(pos, 1).compare("x")) { - radix = 16; - pos++; - } else if (!in.substr(pos, 2).compare("0h") - || !in.substr(pos, 2).compare("0x")) { - radix = 16; - pos += 2; - } else if (!in.substr(pos, 1).compare("b")) { - radix = 2; - pos++; - } else if (!in.substr(pos, 2).compare("0b")) { - radix = 2; - pos += 2; - } - - const int log_max_radix = 4; - assert(radix <= (1 << log_max_radix)); - - dat_t curr_base = 1; - res = 0; - - for (int rpos=in.length()-1; rpos>=pos; rpos--) { - char c = in[rpos]; - val_t c_val = 0; - if (c == '_') { - continue; - } - if (c >= '0' && c <= '9') { - c_val = c - '0'; - } else if (c >= 'a' && c <= 'z') { - c_val = c - 'a' + 10; - } else if (c >= 'A' && c <= 'Z') { - c_val = c - 'A' + 10; - } else { - std::cerr << "dat_from_str: Invalid character '" << c << "' in '" << in << "'" << std::endl; - return false; - } - if (c_val > radix /* || c_val < 0 */) { - std::cerr << "dat_from_str: Invalid character '" << c << "'" << - std::endl; - return false; - } - - dat_t temp_prod = curr_base * dat_t(c_val); - res = res + temp_prod; - curr_base = curr_base * dat_t(radix); - } - if (negate) { - res = -res; - } - return true; -} - -// API base class, providing common functions -class api_base { -public: - api_base(const char* new_name, const char* new_path) : - name(new_name), - path(new_path) - {} - // returns the fully qualified name of this object (path + dot + name) - std::string get_pathname() { - if (*path == '\0') { - return name; - } else { - return get_path() + "." + name; - } - } - // returns the short name of this object - std::string get_name() { - return name; - } - // returns the path of this object (without a trailing dot) - std::string get_path() { - return path; - } -protected: - const char* name; - const char* path; -}; - -// API base (non width templated) class for API accessors to dat_t -class dat_api_base : public api_base { -public: - dat_api_base(const char* new_name, const char* new_path) : - api_base(new_name, new_path) - {} - // returns the value of this wire as a string, or empty string on failure - virtual std::string get_value() = 0; - // sets the value of this wire from a string, returning true on success - virtual bool set_value(std::string value) = 0; - // returns the bitwidth of this wire - virtual std::string get_width() = 0; -}; - -// dat_api dummy class, does nothing except for return errors -// to be used when a real dat_api object can't be found -class dat_dummy : public dat_api_base { -public: - dat_dummy() : - dat_api_base("error", "") - {} - std::string get_value() { - return "error"; - } - - bool set_value(std::string value) { - return false; - } - - std::string get_width() { - return "error"; - } -}; - -template class dat_api : public dat_api_base { -public: - dat_api(dat_t* new_dat, const char* new_name, const char* new_path) : - dat_api_base(new_name, new_path), - dat_ptr(new_dat) - {} - - std::string get_value() { - return dat_ptr->to_str(); - } - - bool set_value(std::string value) { - return dat_from_str(value, *dat_ptr); - } - - std::string get_width() { - return itos(w); - } - -protected: - dat_t* dat_ptr; -}; - -// API base (non width/depth templated) class for API accessors to mem_t -class mem_api_base : public api_base { -public: - mem_api_base(const char* new_name, const char* new_path) : - api_base(new_name, new_path) - {} - // return the value of an element as a string, or empty string on failure - virtual std::string get_element(std::string index) = 0; - // sets the value of an element from a string, returning true on success - virtual bool set_element(std::string index, std::string value) = 0; - // returns the bitwidth of a memory element - virtual std::string get_width() = 0; - // returns the number of memory elements - virtual std::string get_depth() = 0; -}; - -// mem_api dummy class, does nothing except for return errors -// to be used when a real mem_api object can't be found -class mem_dummy : public mem_api_base { -public: - mem_dummy() : - mem_api_base("error", "") - {} - std::string get_element(std::string index) { - return "error"; - } - - bool set_element(std::string index, std::string value) { - return false; - } - - std::string get_width() { - return "error"; - } - - std::string get_depth() { - return "error"; - } -}; - -template class mem_api : public mem_api_base { -public: - mem_api(mem_t* new_mem, const char* new_name, const char* new_path) : - mem_api_base(new_name, new_path), - mem_ptr(new_mem) - {} - - string get_element(std::string index) { - int index_int = atoi(index.c_str()); - return mem_ptr->contents[index_int].to_str(); - } - - bool set_element(std::string index, std::string value) { - int index_int = atoi(index.c_str()); - return dat_from_str(value, mem_ptr->contents[index_int]); - } - - std::string get_width() { - return itos(w); - } - - std::string get_depth() { - return itos(d); - } - -protected: - mem_t* mem_ptr; -}; - -class mod_api_t { -public: - mod_api_t(): - teefile(NULL) - {} - - void init(mod_t* new_module) { - module = new_module; - init_mapping_table(); - } - - void set_teefile(FILE* new_teefile) { - teefile = new_teefile; - } - - mod_t* get_module() { - return module; - } - - // API basic functions - std::string get_host_name() {return "C++ Emulator API";} - std::string get_api_version() {return "0";} - std::string get_api_support() {return "PeekPoke Introspection";} - - // External access functions & helpers - std::vector< std::string > tokenize(std::string str) { - std::vector< std::string > res; - int i = 0; - int c = ' '; - while ( i < str.size() ) { - while (isspace(c)) { - if (i >= str.size()) return res; - c = str[i++]; - } - std::string s; - while (!isspace(c) && i < str.size()) { - s.push_back(c); - c = str[i++]; - } - if (i >= str.size()) s.push_back(c); - if (s.size() > 0) - res.push_back(s); - } - return res; - } - - // helper to verify command length, returning false and printing an error - // to stderr if the length isn't in the specified range - bool check_command_length(std::vector& tokenized_command, - int min_args, int max_args=-1) { - if (tokenized_command.size() - 1 < min_args) { - std::cerr << tokenized_command[0] << " expects at least " << min_args - << " args, got " << tokenized_command.size() - 1 - << std::endl; - return false; - } else if (max_args >= 0 && tokenized_command.size() - 1 > max_args) { - std::cerr << tokenized_command[0] << " expects at most " << max_args - << " args, got " << tokenized_command.size() - 1 - << std::endl; - return false; - } - return true; - } - - // Evaluates an API command, returning the reply as a string (without - // the trailing newline). - // Errors return "error", printing a more detailed description to stderr. - // TODO: find a way to pass errors in-line, so transport layers other than - // stdin/stdout (like TCP/IP) are possible while also communicating errors. - std::string eval_command(std::string command) { - std::vector tokens = tokenize(command); - if (tokens.size() == 0) { - std::cerr << "Empty command: '" << command << "'" << std::endl; - return "error"; - } - if (tokens[0] == "get_host_name") { - // IN: get_host_name - // OUT: API host's name (arbitrary string) - if (!check_command_length(tokens, 0, 0)) { return "error"; } - return get_host_name(); - } else if (tokens[0] == "get_api_version") { - // BETA FUNCTION: semantics subject to change, use with caution - // IN: get_api_version - // OUT: API version supported by this host - if (!check_command_length(tokens, 0, 0)) { return "error"; } - return get_api_version(); - } else if (tokens[0] == "get_api_support") { - // BETA FUNCTION: semantics subject to change, use with caution - // IN: get_api_support - // OUT: list of supported API features - if (!check_command_length(tokens, 0, 0)) { return "error"; } - return get_api_support(); - } else if (tokens[0] == "clock") { - // BETA FUNCTION: semantics subject to change, use with caution - // IN: clock - // OUT: actual number of cycles stepped - if (!check_command_length(tokens, 1, 1)) { return "error"; } - int cycles = atoi(tokens[1].c_str()); - module->propagate_changes(); - for (int i=0; iclock(dat_t<1>(0)); - } - return itos(cycles); - } else if (tokens[0] == "tick") { - // BETA FUNCTION: semantics subject to change, use with caution - // IN: tick - // OUT: ok (on success) - // Update registers without propagation - // updating registers. - module->clock_hi(dat_t<1>(0)); - return "ok"; - } else if (tokens[0] == "propagate") { - // BETA FUNCTION: semantics subject to change, use with caution - // IN: propagate - // OUT: ok (on success) - // This function propagates the combinational logic, without - // updating registers. - module->propagate_changes(); - return "ok"; - } else if (tokens[0] == "step") { - // IN: step - // OUT: actual number of cycles stepped - if (!check_command_length(tokens, 1, 1)) { return "error"; } - int n = atoi(tokens[1].c_str()); - module->propagate_changes(); - int ret = module->step(false, n); - // Do we have print output to report? - int nBytes = module->has_output(); - if (nBytes > 0) { - cout << "PRINT" << " " << nBytes << " " << module->drain_output(); - } - return itos(ret); - } else if (tokens[0] == "set_clocks") { - // BETA FUNCTION: semantics subject to change, use with caution - // IN: set_clocks - // OUT: ??? - // I'm not really sure what this is supposed to do, but it was - // in the old command API, so it's here now - std::vector< int > periods; - for (int i = 1; i < tokens.size(); i++) { - int period = atoi(tokens[i].c_str()); - periods.push_back(period); - } - module->setClocks(periods); - return "ok"; - - } else if (tokens[0] == "reset") { - // IN: reset - // OUT: actual number of cycles in reset - if (!check_command_length(tokens, 0, 1)) { return "error"; } - int cycles = 1; - if (tokens.size() >= 2) { - cycles = atoi(tokens[1].c_str()); - } - for (int i=0; iclock_lo(dat_t<1>(1)); - module->clock_hi(dat_t<1>(1)); - } - module->clock_lo(dat_t<1>(0)); - return itos(cycles); - } else if (tokens[0] == "peek") { - // LEGACY FUNCTION: do not use in new code - // IN: peek | peek - // OUT: value - if (!check_command_length(tokens, 1, 2)) { return "error"; } - cerr << "peek is deprecated, use wire_peek or mem_peek" << std::endl; - module->propagate_changes(); - if (tokens.size() == 2) { - return get_dat_by_name(tokens[1])->get_value(); - } else if (tokens.size() == 3) { - return get_mem_by_name(tokens[1])->get_element(tokens[2]); - } - } else if (tokens[0] == "poke") { - // LEGACY FUNCTION: do not use in new code - // IN: poke | poke - // OUT: true (on success), false (on failure) - if (!check_command_length(tokens, 2, 3)) { return ""; } - cerr << "poke is deprecated, use wire_poke or mem_poke" << std::endl; - bool success = false; - if (tokens.size() == 3) { - success = get_dat_by_name(tokens[1])->set_value(tokens[2]); - } else if (tokens.size() == 4) { - success = get_mem_by_name(tokens[1])->set_element(tokens[2], tokens[3]); - } - std::string result; - if (success) { - result = "true"; - module->mark_stale(); - } else { - result = "false"; - } - return result; - } else if (tokens[0] == "wire_peek") { - // IN: wire_peek - // OUT: value - if (!check_command_length(tokens, 1, 1)) { return "error"; } - module->propagate_changes(); - return get_dat_by_name(tokens[1])->get_value(); - } else if (tokens[0] == "wire_poke") { - // IN: wire_poke - // OUT: ok (on success) - if (!check_command_length(tokens, 2, 2)) { return "error"; } - bool success = get_dat_by_name(tokens[1])->set_value(tokens[2]); - std::string result; - if (success) { - result = "ok"; - module->mark_stale(); - } else { - result = "error"; - } - return result; - } else if (tokens[0] == "mem_peek") { - // IN: mem_peek - // OUT: value - if (!check_command_length(tokens, 2, 2)) { return "error"; } - module->propagate_changes(); - return get_mem_by_name(tokens[1])->get_element(tokens[2]); - } else if (tokens[0] == "mem_poke") { - // IN: mem_poke - // OUT: ok (on success) - if (!check_command_length(tokens, 3, 3)) { return "error"; } - bool success = get_mem_by_name(tokens[1])->set_element(tokens[2], tokens[3]); - std::string result; - if (success) { - result = "ok"; - module->mark_stale(); - } else { - result = "error"; - } - return result; - return success ? "ok" : "error"; - } else if (tokens[0] == "trace") { - // IN: trace n + - // OUT: values - // TODO: ADD MEM PEEK SUPPORT - stringstream ss; - if (!check_command_length(tokens, 2)) { return "bad"; } - int n = atoi(tokens[1].c_str()); - for (int t = 0; t < n; t++) { - for (int i = 2; i < tokens.size(); i++) - ss << " " << get_dat_by_name(tokens[i])->get_value(); - int ret = module->step(false, 1); - // if (!ret) - // return "error"; - } - return ss.str(); - } else if (tokens[0] == "list_wires") { - // IN: list_wires - // OUT: list of wires - if (!check_command_length(tokens, 0, 0)) { return "error"; } - std::string out = ""; - for (std::map::iterator it = dat_table.begin(); it != dat_table.end(); it++) { - out = out + it->second->get_pathname() + " "; - } - if (out.size() >= 1) { - return out.substr(0, out.size() - 1); - } else { - return ""; - } - } else if (tokens[0] == "list_mems") { - // IN: list_mems - // OUT: list of memories - if (!check_command_length(tokens, 0, 0)) { return "error"; } - std::string out = ""; - for (std::map::iterator it = mem_table.begin(); it != mem_table.end(); it++) { - out = out + it->second->get_pathname() + " "; - } - if (out.size() >= 1) { - return out.substr(0, out.size() - 1); - } else { - return ""; - } - } else if (tokens[0] == "wire_width") { - // IN: wire_width - // OUT: bitwidth of wire - if (!check_command_length(tokens, 1, 1)) { return "error"; } - return get_dat_by_name(tokens[1])->get_width(); - } else if (tokens[0] == "mem_width") { - // IN: mem_width - // OUT: bitwidth of memory element - if (!check_command_length(tokens, 1, 1)) { return "error"; } - return get_mem_by_name(tokens[1])->get_width(); - } else if (tokens[0] == "mem_depth") { - // IN: mem_depth - // OUT: elements in memory - if (!check_command_length(tokens, 1, 1)) { return "error"; } - return get_mem_by_name(tokens[1])->get_depth(); - } else if (tokens[0] == "referenced_snapshot_save") { - // BETA FUNCTION: semantics subject to change, use with caution - // IN: referenced_snapshot_save - // OUT: Reference name (an arbitrary string) for saved snapshot - // of current state, should be equivalent to the input. - // Caution: the state may not be self-consistent (i.e. clk_lo - // does not need to have been applied before this, and calls to - // clk_lo immediately after restoring may change the state). - if (!check_command_length(tokens, 1, 1)) { return "error"; } - module->propagate_changes(); - mod_t *snapshot = module->clone(); - snapshot_table[tokens[1]] = snapshot; - return tokens[1]; - } else if (tokens[0] == "referenced_snapshot_restore") { - // BETA FUNCTION: semantics subject to change, use with caution - // IN: referenced_snapshot_restore - // OUT: ok (on success) - if (!check_command_length(tokens, 1, 1)) { return "error"; } - mod_t *snapshot = get_snapshot_by_reference(tokens[1]); - if (snapshot == NULL) { return "error"; } - bool success = module->set_circuit_from(snapshot); - std::string result; - if (success) { - result = "ok"; - module->mark_stale(); - } else { - result = "error"; - } - return result; - } else { - std::cerr << "Unknown command: '" << tokens[0] << "'" << std::endl; - } - return "error"; - } - - void read_eval_print_loop() { - while (true) { - std::string str_in; - do { - std::getline(cin, str_in); - } while (cin.fail() && errno == EINTR); - - if (!cin.good()) { - break; - } - - if (teefile != NULL) { - fprintf(teefile, "%s\n", str_in.c_str()); - fflush(teefile); - } - if (str_in == "quit") { - break; - } else { - cout << eval_command(str_in) << std::endl; - } - } - } - -protected: - FILE* teefile; - mod_t* module; - - // Mapping table functions - virtual void init_mapping_table() = 0; - - dat_api_base* get_dat_by_name(std::string name) { - if (dat_table.find(name.c_str()) != dat_table.end()) { - return dat_table[name.c_str()]; - } else { - std::cerr << "Unable to find dat '" << name << "'" << std::endl; - return &this_dat_dummy; - } - } - mem_api_base* get_mem_by_name(std::string name) { - if (mem_table.find(name.c_str()) != mem_table.end()) { - return mem_table[name.c_str()]; - } else { - std::cerr << "Unable to find mem '" << name << "'" << std::endl; - return &this_mem_dummy; - } - } - - mod_t* get_snapshot_by_reference(std::string name) { - if (snapshot_table.find(name) != snapshot_table.end()) { - return snapshot_table[name]; - } else { - std::cerr << "Unable to find snapshot reference '" << name << "'" << std::endl; - return NULL; - } - } - - class string_comparator { - public: - bool operator()(const char* x, const char* y) const { - return strcmp(x, y) < 0; - } - }; - - std::map dat_table; - std::map mem_table; - // TODO: replace the dummy with explicit NULL checks - this is simple - // but a bit inelegant - dat_dummy this_dat_dummy; - mem_dummy this_mem_dummy; - - // Snapshot functions - std::map snapshot_table; -}; - -#pragma GCC diagnostic pop - -#endif diff --git a/src/main/resources/emulator_mod.h b/src/main/resources/emulator_mod.h deleted file mode 100644 index 0c4ac2be..00000000 --- a/src/main/resources/emulator_mod.h +++ /dev/null @@ -1,1801 +0,0 @@ -// Header for Chisel emulator module -// defines the mod_t class as well as bit operation functions - -#ifndef __IS_EMULATOR_MOD__ -#define __IS_EMULATOR_MOD__ - -#pragma GCC diagnostic push -#ifdef __clang__ -#pragma GCC diagnostic ignored "-Wunknown-pragmas" -#else -#pragma GCC diagnostic ignored "-Wpragmas" -#endif // __clang__ -#pragma GCC diagnostic ignored "-Wunused-parameter" -#pragma GCC diagnostic ignored "-Wsign-compare" -#pragma GCC diagnostic ignored "-Wparentheses" -#pragma GCC diagnostic ignored "-Wreturn-type" -#pragma GCC diagnostic ignored "-Wchar-subscripts" -#pragma GCC diagnostic ignored "-Wtype-limits" -#pragma GCC diagnostic ignored "-Wunused-function" -#pragma GCC diagnostic ignored "-Wunused-variable" -#pragma GCC diagnostic ignored "-Wreorder" -#pragma GCC diagnostic ignored "-Wsometimes-uninitialized" -#pragma GCC diagnostic ignored "-pedantic" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -using namespace std; - -typedef uint64_t val_t; -typedef int64_t sval_t; -typedef uint32_t half_val_t; -#if defined(__GNUC__) && defined(__SIZEOF_INT128__) -#define __HAVE_DUB_VAL_T__ -typedef unsigned __int128 dub_val_t; -#endif - -union flo2int_t { - float f; - val_t i; -}; - -inline float toFloat (val_t x) { - flo2int_t f2i; - f2i.i = x; - return f2i.f; -} - -inline val_t fromFloat (float x) { - flo2int_t f2i; - f2i.f = x; - return f2i.i; -} - -union dbl2int_t { - double f; - val_t i; -}; - -inline double toDouble (val_t x) { - dbl2int_t f2i; - f2i.i = x; - return f2i.f; -} - -inline val_t fromDouble (double x) { - dbl2int_t f2i; - f2i.f = x; - return f2i.i; -} - -#define TERNARY(c, t, f) ((f) ^ (((f) ^ (t)) & -(c))) - -#if defined(__GNUC__) && defined(__x86_64__) -#define TERNARY_1(c, t, f) ({ \ - val_t __res; \ - if (!__builtin_constant_p(c)) { \ - __res = (f); \ - val_t __t = (t); \ - uint8_t __c = (c); \ - asm ("testb $1, %1; cmovne %2, %0" : "+r"(__res) : "rm"(__c), "rm"(__t) : "cc"); \ - } else __res = TERNARY(c, t, f); \ - __res; }) -#else -#define TERNARY_1(c, t, f) TERNARY(c, t, f) -#endif - -#define MASK(v, c) ((v) & -(val_t)(c)) -#ifndef MIN -#define MIN(a, b) TERNARY((a) < (b), (a), (b)) -#endif -#ifndef MAX -#define MAX(a, b) TERNARY((a) > (b), (a), (b)) -#endif -#define CLAMP(a, min, max) MAX(MIN(a, max), min) - -template struct CeilLog { - static uint32_t const v = CeilLog<(x >> 1), shifted + 1, sticky | (x & 1)>::v; -}; - -template struct CeilLog<0, shifted, sticky> { - static uint32_t const v = -1; -}; - -template struct CeilLog<1, shifted, sticky> { - static uint32_t const v = sticky ? shifted + 1 : shifted; -}; - -#define val_n_bits() (sizeof(val_t)*8) -#define val_n_half_bits() (val_n_bits()/2) -#define val_all_ones() val_all_ones_or_zeroes(1) -#define val_all_ones_or_zeroes(bit) (val_t(0) - val_t(bit)) -#define val_n_words(n_bits) (1+((n_bits)-1)/val_n_bits()) -#define val_n_half_words(n_bits) (1+((n_bits)-1)/val_n_half_bits()) -#define val_top_bit(v) (val_t(v) >> (val_n_bits()-1)) -#define val_n_full_words(n_bits) ((n_bits)/val_n_bits()) -#define val_n_word_bits(n_bits) ((n_bits) % val_n_bits()) -inline val_t val_n_nibs( void ) { return val_n_bits()>>2; } -inline val_t val_half_mask( void ) { return (((val_t)1)<<(val_n_half_bits()))-1; } -inline val_t val_lo_half( val_t n_bits ) { return n_bits & val_half_mask(); } -inline val_t val_hi_half( val_t n_bits ) { return n_bits >> val_n_half_bits(); } -inline val_t val_n_rem_word_bits( val_t n_bits ) { return val_n_bits() - val_n_word_bits(n_bits); } -//inline val_t dub_val_lo_half( dub_val_t bits ) { return (val_t)bits; } -//inline val_t dub_val_hi_half( dub_val_t bits ) { return (val_t)(bits >> val_n_bits()); } - - -inline void val_to_half_vals ( val_t *fvals, half_val_t *hvals, int nf ) { - for (int i = 0; i < nf; i++) { - hvals[i*2] = val_lo_half(fvals[i]); - hvals[i*2+1] = val_hi_half(fvals[i]); - } -} -inline void half_val_to_vals ( half_val_t *hvals, val_t *vals, int nf ) { - for (int i = 0; i < nf; i++) - vals[i] = ((val_t)hvals[i*2+1] << val_n_half_bits()) | hvals[i*2]; -} - -template class dat_t; -template class datz_t; - -template int datz_eq(dat_t d1, datz_t d2); - -template inline dat_t DAT(val_t value) { - dat_t res(value); - return res; } - -template inline dat_t DAT(val_t val1, val_t val0) { - dat_t res; res.values[0] = val0; res.values[1] = val1; return res; -} - -const static char hex_digs[] = - {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; - -static void add_n (val_t d[], val_t s0[], val_t s1[], int nw, int nb) { - val_t carry = 0; - for (int i = 0; i < nw; i++) { - d[i] = s0[i] + s1[i] + carry; - carry = ((s0[i] + s1[i]) < s0[i]) || (d[i] < carry); - } -} - -static void neg_n (val_t d[], val_t s0[], int nw, int nb) { - val_t borrow = 0; - for (int i = 0; i < nw; i++) { - d[i] = -s0[i] - borrow; - borrow = s0[i] || d[i]; - } -} - -static void sub_n (val_t d[], val_t s0[], val_t s1[], int nw, int nb) { - val_t borrow = 0; - for (int i = 0; i < nw; i++) { - d[i] = s0[i] - s1[i] - borrow; - borrow = (s0[i] < (s0[i] - s1[i])) || (s0[i] - s1[i]) < d[i]; - } -} - -static void mul_n (val_t d[], val_t s0[], val_t s1[], int nb0, int nb1) { -// Adapted from Hacker's Delight, from Knuth -#if BYTE_ORDER != LITTLE_ENDIAN -# error mul_n assumes a little-endian architecture -#endif - int nbd = nb0 + nb1; - for (int i = 0; i < val_n_words(nbd); i++) - d[i] = 0; - - half_val_t* w = reinterpret_cast(d); - half_val_t* u = reinterpret_cast(s0); - half_val_t* v = reinterpret_cast(s1); - int m = val_n_half_words(nb0), n = val_n_half_words(nb1), p = val_n_half_words(nbd); - - for (int j = 0; j < n; j++) { - val_t k = 0; - for (int i = 0; i < MIN(m, p-j); i++) { - val_t t = (val_t)u[i]*v[j] + w[i+j] + k; - w[i+j] = t; - k = t >> val_n_half_bits(); - } - if (j+m < p) - w[j+m] = k; - } -} - -static void rsha_n (val_t d[], val_t s0[], int amount, int nw, int w) { - - int n_shift_bits = amount % val_n_bits(); - int n_shift_words = amount / val_n_bits(); - int n_rev_shift_bits = val_n_bits() - n_shift_bits; - int is_zero_carry = n_shift_bits == 0; - int msb = s0[nw-1] >> (w - nw*val_n_bits() - 1); - val_t carry = 0; - - if (msb == 0) - for (int i = 0; i < n_shift_words; i++) { - d[nw-i-1] = 0; - } - - for (int i = nw-1; i >= n_shift_words; i--) { - val_t val = s0[i]; - d[i-n_shift_words] = val >> n_shift_bits | carry; - carry = is_zero_carry ? 0 : val << n_rev_shift_bits; - } - - if (msb == 0) { - return; - } - - int boundary = (w - amount); - - for (int i = nw-1; i >= 0; i--) { - int idx = i*val_n_bits(); - if (idx > boundary) { - d[i] = val_all_ones(); - } 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)); - return; - } - } -} - -static void rsh_n (val_t d[], val_t s0[], int amount, int nw) { - val_t carry = 0; - int n_shift_bits = amount % val_n_bits(); - int n_shift_words = amount / val_n_bits(); - int n_rev_shift_bits = val_n_bits() - n_shift_bits; - int is_zero_carry = n_shift_bits == 0; - for (int i = 0; i < n_shift_words; i++) - d[nw-i-1] = 0; - for (int i = nw-1; i >= n_shift_words; i--) { - val_t val = s0[i]; - d[i-n_shift_words] = val >> n_shift_bits | carry; - carry = is_zero_carry ? 0 : val << n_rev_shift_bits; - } -} - -static void lsh_n (val_t d[], val_t s0[], int amount, int nwd, int nws) { - val_t carry = 0; - int n_shift_bits = amount % val_n_bits(); - int n_shift_words = amount / val_n_bits(); - int n_rev_shift_bits = val_n_bits() - n_shift_bits; - int is_zero_carry = n_shift_bits == 0; - for (int i = 0; i < nwd; i++) - d[i] = 0; - for (int i = 0; i < (nws-n_shift_words); i++) { - val_t val = s0[i]; - d[i+n_shift_words] = val << n_shift_bits | carry; - carry = is_zero_carry ? 0 : val >> n_rev_shift_bits; - } -} - -static inline val_t mask_val(int n) { - val_t res = val_all_ones() >> (val_n_bits()-n); - return res; -} - -static inline void mask_n (val_t d[], int nw, int nb) { - int n_full_words = val_n_full_words(nb); - int n_word_bits = val_n_word_bits(nb); - for (int i = 0; i < n_full_words; i++) - d[i] = val_all_ones(); - for (int i = n_full_words; i < nw; i++) - d[i] = 0; - if (n_word_bits > 0) - d[n_full_words] = mask_val(n_word_bits); -} - -static inline val_t log2_1 (val_t v) { -#ifdef __GNUC__ - return TERNARY(v != 0, val_n_bits() - 1 - __builtin_clzll(v), 0); -#else - val_t r; - val_t shift; - r = (v > 0xFFFFFFFF) << 5; v >>= r; - shift = (v > 0xFFFF ) << 4; v >>= shift; r |= shift; - shift = (v > 0xFF ) << 3; v >>= shift; r |= shift; - shift = (v > 0xF ) << 2; v >>= shift; r |= shift; - shift = (v > 0x3 ) << 1; v >>= shift; r |= shift; - r |= (v >> 1); - return r; -#endif -} - -static inline val_t reverse_1 (val_t v) { - v = ((v >> 1) & 0x5555555555555555) | ((v & 0x5555555555555555) << 1); - v = ((v >> 2) & 0x3333333333333333) | ((v & 0x3333333333333333) << 2); - v = ((v >> 4) & 0x0F0F0F0F0F0F0F0F) | ((v & 0x0F0F0F0F0F0F0F0F) << 4); - v = ((v >> 8) & 0x00FF00FF00FF00FF) | ((v & 0x00FF00FF00FF00FF) << 8); - v = ((v >> 16) & 0x0000FFFF0000FFFF) | ((v & 0x0000FFFF0000FFFF) << 16); - v = ( v >> 32 ) | ( v << 32); - return v; -} - -static inline val_t priority_encode_1 (val_t v) { -#ifdef __GNUC__ - return TERNARY(v != 0, __builtin_ctzll(v), 0); -#else - if (v == 0) - return 0; - val_t r; - val_t shift; - r = !(v & 0xFFFFFFFF) << 5; v >>= r; - shift = !(v & 0xFFFF ) << 4; v >>= shift; r |= shift; - shift = !(v & 0xFF ) << 3; v >>= shift; r |= shift; - shift = !(v & 0xF ) << 2; v >>= shift; r |= shift; - shift = !(v & 0x3 ) << 1; v >>= shift; r |= shift; - shift = !(v & 0x1 ) << 0; v >>= shift; r |= shift; - return r; -#endif -} - -#define ispow2(x) (((x) & ((x)-1)) == 0) -static inline val_t nextpow2_1(val_t x) { - x--; - x |= x >> 1; - x |= x >> 2; - x |= x >> 4; - x |= x >> 8; - x |= x >> 16; - x |= x >> 32; - x++; - return x; -} - -/* -#define __FLOAT_WORD_ORDER LITTLE_ENDIAN - -static inline uint32_t log2_1_32 (uint32_t v) { - union { uint32_t u[2]; double d; } t; // temp - - t.u[__FLOAT_WORD_ORDER==LITTLE_ENDIAN] = 0x43300000; - t.u[__FLOAT_WORD_ORDER!=LITTLE_ENDIAN] = v; - t.d -= 4503599627370496.0; - return (t.u[__FLOAT_WORD_ORDER==LITTLE_ENDIAN] >> 20) - 0x3FF; -} - -static inline val_t log2_1 (val_t v) { - uint32_t r_lo = (uint32_t)v; - uint32_t r_hi = (uint32_t)(v >> 32); - return (((val_t)log2_1_32(r_hi)) << 32)|((val_t)log2_1_32(r_lo)); -} -*/ - -/* -static inline val_t log2_1 (val_t v) { - v |= (v >> 1); - v |= (v >> 2); - v |= (v >> 4); - v |= (v >> 8); - v |= (v >> 16); - v |= (v >> 32); - return ones64(v) - 1; -} -*/ - -/* -static inline val_t log2_1 (val_t v) { - val_t res = 0; - while (v >>= 1) - res++; - return res; -} -*/ - -static inline val_t log2_n (val_t s0[], int nw) { - val_t off = (nw-1)*val_n_bits(); - for (int i = nw-1; i >= 0; i--) { - val_t s0i = s0[i]; - if (s0i > 0) { - val_t res = log2_1(s0i); - return res + off; - } - off -= val_n_bits(); - } - return 0; -} - -template -struct bit_word_funs { - static void fill (val_t d[], val_t s0) { - for (int i = 0; i < nw; i++) - d[i] = s0; - } - static void fill_nb (val_t d[], val_t s0, int nb) { - mask_n(d, nw, nb); - for (int i = 0; i < nw; i++) - d[i] = d[i] & s0; - // printf("FILL-NB N\n"); - } - static void copy (val_t d[], val_t s0[], int sww) { - if (sww > nw) { - for (int i = 0; i < nw; i++) { - // printf("A I %d\n", i); fflush(stdout); - d[i] = s0[i]; - } - } else { - for (int i = 0; i < sww; i++) { - // printf("B I %d\n", i); fflush(stdout); - d[i] = s0[i]; - } - for (int i = sww; i < nw; i++) { - // printf("C I %d\n", i); fflush(stdout); - d[i] = 0; - } - } - } - static void mask (val_t d[], int nb) { - mask_n(d, nw, nb); - } - static void add (val_t d[], val_t s0[], val_t s1[], int nb) { - add_n(d, s0, s1, nw, nb); - } - static void neg (val_t d[], val_t s0[], int nb) { - neg_n(d, s0, nw, nb); - } - static void sub (val_t d[], val_t s0[], val_t s1[], int nb) { - sub_n(d, s0, s1, nw, nb); - } - static void mul (val_t d[], val_t s0[], val_t s1[], int nb0, int nb1) { - mul_n(d, s0, s1, nb0, nb1); - } - static void bit_xor (val_t d[], val_t s0[], val_t s1[]) { - for (int i = 0; i < nw; i++) - d[i] = s0[i] ^ s1[i]; - } - static void bit_and (val_t d[], val_t s0[], val_t s1[]) { - for (int i = 0; i < nw; i++) - d[i] = s0[i] & s1[i]; - } - static void bit_or (val_t d[], val_t s0[], val_t s1[]) { - for (int i = 0; i < nw; i++) - d[i] = s0[i] | s1[i]; - } - static void bit_neg (val_t d[], val_t s0[], int nb) { - val_t msk[nw]; - mask_n(msk, nw, nb); - for (int i = 0; i < nw; i++) - d[i] = ~s0[i] & msk[i]; - } - static bool ltu (val_t s0[], val_t s1[]) { - val_t diff[nw]; - sub(diff, s0, s1, nw*val_n_bits()); - return val_top_bit(diff[nw-1]); - } - static bool lt (val_t s0[], val_t s1[], int w) { - int msb_0 = (s0[1] >> (w - (nw-1)*val_n_bits() - 1)) & 0x1; - int msb_1 = (s1[1] >> (w - (nw-1)*val_n_bits() - 1)) & 0x1; - if (msb_0 != msb_1) { - return msb_0; - } else { - val_t diff[nw]; - sub(diff, s0, s1, nw*val_n_bits()); - return val_top_bit(diff[nw-1]); - } - } - static bool lteu (val_t s0[], val_t s1[]) { - val_t diff[nw]; - sub(diff, s1, s0, nw*val_n_bits()); - return !val_top_bit(diff[nw-1]); - } - static bool lte (val_t s0[], val_t s1[], int w) { - int msb_0 = (s0[1] >> (w - (nw-1)*val_n_bits() - 1)) & 0x1; - int msb_1 = (s1[1] >> (w - (nw-1)*val_n_bits() - 1)) & 0x1; - if (msb_0 != msb_1) { - return msb_0; - } else { - val_t diff[nw]; - sub(diff, s1, s0, nw*val_n_bits()); - return !val_top_bit(diff[nw-1]); - } - } - static bool eq (val_t s0[], val_t s1[]) { - for (int i = 0; i < nw; i++) - if (s0[i] != s1[i]) - return false; - return true; - } - static bool neq (val_t s0[], val_t s1[]) { - return !eq(s0, s1); - } - static void rsha (val_t d[], val_t s0[], int amount, int w) { - rsha_n(d, s0, amount, nw, w); - } - static void rsh (val_t d[], val_t s0[], int amount) { - rsh_n(d, s0, amount, nw); - } - static void lsh (val_t d[], val_t s0[], int amount) { - lsh_n(d, s0, amount, nw, nw); - } - static void extract (val_t d[], val_t s0[], int e, int s, int nb) { - // TODO: FINISH THIS - const int bw = e-s+1; - val_t msk[nw]; - mask_n(msk, nw, nb); - if (s == 0) { - // printf("EXT E %d S %d NW %d NB %d: ", e, s, nw, nb); - for (int i = 0; i < nw; i++) { - d[i] = s0[i] & msk[i]; - // printf("%d:%llx ", i, d[i]); - } - } else { - rsh_n(d, s0, s, nw); - // printf("EXT E %d S %d NW %d NB %d: ", e, s, nw, nb); - for (int i = 0; i < nw; i++) { - // printf("I%d:R%llx:M%llx:", i, d[i], msk[i]); - d[i] = d[i] & msk[i]; - // printf("D%llx ", d[i]); - } - } - // printf("\n"); - } - - static void inject (val_t d[], val_t s0[], int e, int s) { - // Opposite of extract: Assign s0 to a subfield of d. - const int bw = e-s+1; - val_t msk[nw]; - val_t msk_lsh[nw]; - val_t s0_lsh[nw]; - mask_n(msk, nw, bw); - lsh_n(msk_lsh, msk, s, nw, nw); - lsh_n(s0_lsh, s0, s, nw, nw); - for (int i = 0; i < nw; i++) { - d[i] = (d[i] & ~msk_lsh[i]) | (s0_lsh[i] & msk_lsh[i]); - } - } - - static void set (val_t d[], val_t s0[]) { - for (int i = 0; i < nw; i++) - d[i] = s0[i]; - } - static void log2 (val_t d[], val_t s0[]) { - d[0] = log2_n(s0, nw); - } -}; - -template <> -struct bit_word_funs<1> { - static void fill (val_t d[], val_t s0) { - d[0] = s0; - } - static void fill_nb (val_t d[], val_t s0, int nb) { - d[0] = mask_val(nb) & s0; - } - static void copy (val_t d[], val_t s0[], int sww) { - d[0] = s0[0]; - } - static void mask (val_t d[], int nb) { - d[0] = mask_val(nb); - } - static void add (val_t d[], val_t s0[], val_t s1[], int nb) { - d[0] = (s0[0] + s1[0]) & mask_val(nb); - } - static void sub (val_t d[], val_t s0[], val_t s1[], int nb) { - d[0] = (s0[0] - s1[0]) & mask_val(nb); - } - static void neg (val_t d[], val_t s0[], int nb) { - d[0] = (- s0[0]) & mask_val(nb); - } - static void mul (val_t d[], val_t s0[], val_t s1[], int nb0, int nb1) { - d[0] = s0[0] * s1[0]; - } - static bool ltu (val_t s0[], val_t s1[]) { - return (s0[0] < s1[0]); - } - static bool lt (val_t s0[], val_t s1[], int w) { - sval_t a = s0[0] << (val_n_bits() - w); - sval_t b = s1[0] << (val_n_bits() - w); - return (a < b); - } - static bool lteu (val_t s0[], val_t s1[]) { - return (s0[0] <= s1[0]); - } - static bool lte (val_t s0[], val_t s1[], int w) { - sval_t a = s0[0] << (val_n_bits() - w); - sval_t b = s1[0] << (val_n_bits() - w); - return (a <= b); - } - static void bit_neg (val_t d[], val_t s0[], int nb) { - d[0] = ~s0[0] & mask_val(nb); - } - static void bit_xor (val_t d[], val_t s0[], val_t s1[]) { - d[0] = (s0[0] ^ s1[0]); - } - static void bit_and (val_t d[], val_t s0[], val_t s1[]) { - d[0] = (s0[0] & s1[0]); - } - static void bit_or (val_t d[], val_t s0[], val_t s1[]) { - d[0] = (s0[0] | s1[0]); - } - static bool eq (val_t s0[], val_t s1[]) { - return s0[0] == s1[0]; - } - static bool neq (val_t s0[], val_t s1[]) { - return s0[0] != s1[0]; - } - static void lsh (val_t d[], val_t s0[], int amount) { - d[0] = (s0[0] << amount); - } - static void rsh (val_t d[], val_t s0[], int amount) { - d[0] = (s0[0] >> amount); - } - static void rsha (val_t d[], val_t s0[], int amount, int w) { - d[0] = s0[0] << (val_n_bits() - w); - d[0] = (sval_t(d[0]) >> (val_n_bits() - w + amount)) & mask_val(w); - } - static void extract (val_t d[], val_t s0[], int e, int s, int nb) { - const int bw = e-s+1; - d[0] = (s0[0] >> s) & mask_val(bw); - } - - static void inject (val_t d[], val_t s0[], int e, int s) { - // Opposite of extract: Assign s0 to a subfield of d. - const int bw = e-s+1; - val_t msk = mask_val(bw); - d[0] = ((s0[0] & msk) << s) | (d[0] & ~(msk << s)); - } - - static void set (val_t d[], val_t s0[]) { - d[0] = s0[0]; - } - static void log2 (val_t d[], val_t s0[]) { - d[0] = log2_1(s0[0]); - } -}; - -template <> -struct bit_word_funs<2> { - static void fill (val_t d[], val_t s0) { - d[0] = s0; - d[1] = s0; - } - static void fill_nb (val_t d[], val_t s0, int nb) { - d[0] = s0; - d[1] = mask_val(nb - val_n_bits()) & s0; - } - static void copy (val_t d[], val_t s0[], int sww) { - d[0] = s0[0]; - d[1] = sww > 1 ? s0[1] : 0; - } - static void mask (val_t d[], int nb) { - d[0] = val_all_ones(); - d[1] = mask_val(nb - val_n_bits()); - } - static void add (val_t d[], val_t x[], val_t y[], int nb) { - val_t x0 = x[0]; - val_t sum0 = x0 + y[0]; - val_t carry0 = (sum0 < x0); - d[0] = sum0; - val_t sum1 = x[1] + y[1] + carry0; - d[1] = sum1; - } - static void sub (val_t d[], val_t s0[], val_t s1[], int nb) { - val_t d0 = s0[0] - s1[0]; - d[1] = s0[1] - s1[1] - (s0[0] < d0); - d[0] = d0; - } - static void neg (val_t d[], val_t s0[], int nb) { - val_t d0 = -s0[0]; - d[1] = -s0[1] - (s0[0] != 0); - d[0] = d0; - } - static void mul (val_t d[], val_t s0[], val_t s1[], int nb0, int nb1) { -#ifdef __HAVE_DUB_VAL_T__ - dub_val_t a = s0[0], b = s1[0]; - if (nb0 > val_n_bits()) a |= dub_val_t(s0[1]) << val_n_bits(); - if (nb1 > val_n_bits()) b |= dub_val_t(s1[1]) << val_n_bits(); - dub_val_t res = a * b; - d[0] = res; - d[1] = res >> val_n_bits(); -#else - mul_n(d, s0, s1, nb0, nb1); -#endif - } - static bool ltu (val_t s0[], val_t s1[]) { - return ((s0[1] < s1[1]) | (s0[1] == s1[1] & s0[0] < s1[0])); - } - static bool lt (val_t s0[], val_t s1[], int w) { - int msb_0 = (s0[1] >> (w - val_n_bits() - 1)) & 0x1; - int msb_1 = (s1[1] >> (w - val_n_bits() - 1)) & 0x1; - int cond = msb_0 ^ msb_1; - return (cond && msb_0) - || (!cond && ((s0[1] < s1[1]) | (s0[1] == s1[1] & s0[0] < s1[0]))); - } - static bool lteu (val_t s0[], val_t s1[]) { - return ((s0[1] < s1[1]) | (s0[1] == s1[1] & s0[0] <= s1[0])); - } - static bool lte (val_t s0[], val_t s1[], int w) { - int msb_0 = (s0[1] >> (w - val_n_bits() - 1)) & 0x1; - int msb_1 = (s1[1] >> (w - val_n_bits() - 1)) & 0x1; - int cond = msb_0 ^ msb_1; - return (cond && msb_0) - || (!cond && ((s0[1] < s1[1]) | (s0[1] == s1[1] & s0[0] <= s1[0]))); - } - static void bit_xor (val_t d[], val_t s0[], val_t s1[]) { - d[0] = (s0[0] ^ s1[0]); - d[1] = (s0[1] ^ s1[1]); - } - static void bit_and (val_t d[], val_t s0[], val_t s1[]) { - d[0] = (s0[0] & s1[0]); - d[1] = (s0[1] & s1[1]); - } - static void bit_or (val_t d[], val_t s0[], val_t s1[]) { - d[0] = (s0[0] | s1[0]); - d[1] = (s0[1] | s1[1]); - } - static void bit_neg (val_t d[], val_t s0[], int nb) { - d[0] = ~s0[0]; - d[1] = ~s0[1] & mask_val(nb - val_n_bits()); - } - static bool eq (val_t s0[], val_t s1[]) { - return (s0[0] == s1[0]) & (s0[1] == s1[1]); - } - static bool neq (val_t s0[], val_t s1[]) { - return (s0[0] != s1[0]) | (s0[1] != s1[1]); - } - static void extract (val_t d[], val_t s0[], int e, int s, int nb) { - val_t msk[2]; - const int bw = e-s+1; - mask_n(msk, 2, bw); - if (s == 0) { - d[0] = s0[0] & msk[0]; - d[1] = s0[1] & msk[1]; - } else { - rsh(d, s0, s); - d[0] = d[0] & msk[0]; - d[1] = d[1] & msk[1]; - } - } - - static void inject (val_t d[], val_t s0[], int e, int s) { - // Opposite of extract: Assign s0 to a subfield of d. - const int bw = e-s+1; - val_t msk[2]; - val_t msk_lsh[2]; - val_t s0_lsh[2]; - mask_n(msk, 2, bw); - lsh_n(msk_lsh, msk, s, 2, 2); - lsh_n(s0_lsh, s0, s, 2, 2); - d[0] = (d[0] & ~msk_lsh[0]) | (s0_lsh[0] & msk_lsh[0]); - d[1] = (d[1] & ~msk_lsh[1]) | (s0_lsh[1] & msk_lsh[1]); - } - - static void rsha (val_t d[], val_t s0[], int amount, int w) { - sval_t hi = s0[1] << (2*val_n_bits() - w); - if (amount >= val_n_bits()) { - d[0] = hi >> (amount - w + val_n_bits()); - d[1] = hi >> (val_n_bits() - 1); - d[1] = d[1] >> (2*val_n_bits() - w); - } else if (amount == 0) { - d[0] = s0[0]; - d[1] = s0[1]; - } else { - int s = 2*val_n_bits() - w + amount; - d[0] = s0[0] >> amount; - d[0] = d[0] | ((hi >> (2*val_n_bits() - w)) << (val_n_bits() - amount)); - d[1] = hi >> (s >= val_n_bits() ? val_n_bits()-1 : s); - d[1] = d[1] & mask_val(w - val_n_bits()); - } - } - static void rsh (val_t d[], val_t s0[], int amount) { - if (amount >= val_n_bits()) { - d[1] = 0; - d[0] = s0[1] >> (amount - val_n_bits()); - } else if (amount == 0) { - d[0] = s0[0]; - d[1] = s0[1]; - } else { - d[1] = s0[1] >> amount; - d[0] = (s0[1] << (val_n_bits() - amount)) | (s0[0] >> amount); - } - } - static void lsh (val_t d[], val_t s0[], int amount) { - if (amount == 0) - { - d[1] = s0[1]; - d[0] = s0[0]; - } else if (amount >= val_n_bits()) { - d[1] = s0[0] << (amount - val_n_bits()); - d[0] = 0; - } else { - d[1] = (s0[1] << amount) | (s0[0] >> (val_n_bits() - amount)); - d[0] = (s0[0] << amount); - } - } - static void set (val_t d[], val_t s0[]) { - d[0] = s0[0]; - d[1] = s0[1]; - } - static void log2 (val_t d[], val_t s0[]) { - val_t s01 = s0[1]; - if (s01 > 0) - d[0] = log2_1(s01) + val_n_bits(); - else - d[0] = log2_1(s0[0]); - // d[0] = log2_n(s0, 2); - } -}; -template <> -struct bit_word_funs<3> { - static void fill (val_t d[], val_t s0) { - d[0] = s0; - d[1] = s0; - d[2] = s0; - } - static void fill_nb (val_t d[], val_t s0, int nb) { - d[0] = s0; - d[1] = s0; - d[2] = mask_val(nb - 2*val_n_bits()) & s0; - } - static void copy (val_t d[], val_t s0[], int sww) { - d[0] = s0[0]; - d[1] = sww > 1 ? s0[1] : 0; - d[2] = sww > 2 ? s0[2] : 0; - } - static void mask (val_t d[], int nb) { - d[0] = val_all_ones(); - d[1] = val_all_ones(); - d[2] = mask_val(nb - 2*val_n_bits()); - } - static void add (val_t d[], val_t s0[], val_t s1[], int nb) { - add_n(d, s0, s1, 3, nb); - } - static void sub (val_t d[], val_t s0[], val_t s1[], int nb) { - sub_n(d, s0, s1, 3, nb); - } - static void neg (val_t d[], val_t s0[], int nb) { - neg_n(d, s0, 3, nb); - } - static void mul (val_t d[], val_t s0[], val_t s1[], int nb0, int nb1) { - mul_n(d, s0, s1, nb0, nb1); - } - static bool ltu (val_t s0[], val_t s1[]) { - return ((s0[2] < s1[2]) | ((s0[2] == s1[2]) & ((s0[1] < s1[1]) | ((s0[1] == s1[1]) & (s0[0] < s1[0]))))); - } - static bool lt (val_t s0[], val_t s1[], int w) { - int msb_0 = (s0[1] >> (w - 2*val_n_bits() - 1)) & 0x1; - int msb_1 = (s1[1] >> (w - 2*val_n_bits() - 1)) & 0x1; - int cond = msb_0 ^ msb_1; - return (cond && msb_0) - || (!cond && (((s0[2] < s1[2]) | ((s0[2] == s1[2]) & ((s0[1] < s1[1]) | ((s0[1] == s1[1]) & (s0[0] < s1[0]))))))); - } - static bool lteu (val_t s0[], val_t s1[]) { - return ((s0[2] < s1[2]) | ((s0[2] == s1[2]) & ((s0[1] < s1[1]) | ((s0[1] == s1[1]) & (s0[0] <= s1[0]))))); - } - static bool lte (val_t s0[], val_t s1[], int w) { - int msb_0 = (s0[1] >> (w - 2*val_n_bits() - 1)) & 0x1; - int msb_1 = (s1[1] >> (w - 2*val_n_bits() - 1)) & 0x1; - int cond = msb_0 ^ msb_1; - return (cond && msb_0) - || (!cond && ((s0[2] < s1[2]) | ((s0[2] == s1[2]) & ((s0[1] < s1[1]) | ((s0[1] == s1[1]) & (s0[0] <= s1[0])))))); - } - static void bit_xor (val_t d[], val_t s0[], val_t s1[]) { - d[0] = (s0[0] ^ s1[0]); - d[1] = (s0[1] ^ s1[1]); - d[2] = (s0[2] ^ s1[2]); - } - static void bit_and (val_t d[], val_t s0[], val_t s1[]) { - d[0] = (s0[0] & s1[0]); - d[1] = (s0[1] & s1[1]); - d[2] = (s0[2] & s1[2]); - } - static void bit_or (val_t d[], val_t s0[], val_t s1[]) { - d[0] = (s0[0] | s1[0]); - d[1] = (s0[1] | s1[1]); - d[2] = (s0[2] | s1[2]); - } - static void bit_neg (val_t d[], val_t s0[], int nb) { - d[0] = ~s0[0]; - d[1] = ~s0[1]; - d[2] = ~s0[2] & mask_val(nb - 2*val_n_bits()); - } - static bool eq (val_t s0[], val_t s1[]) { - return (s0[0] == s1[0]) & (s0[1] == s1[1]) & (s0[2] == s1[2]); - } - static bool neq (val_t s0[], val_t s1[]) { - return (s0[0] != s1[0]) | (s0[1] != s1[1]) | (s0[2] != s1[2]); - } - static void extract (val_t d[], val_t s0[], int e, int s, int nb) { - val_t msk[3]; - const int bw = e-s+1; - mask_n(msk, 3, bw); - if (s == 0) { - d[0] = s0[0] & msk[0]; - d[1] = s0[1] & msk[1]; - d[2] = s0[2] & msk[2]; - } else { - rsh(d, s0, s); - d[0] = d[0] & msk[0]; - d[1] = d[1] & msk[1]; - d[2] = d[2] & msk[2]; - } - } - - static void inject (val_t d[], val_t s0[], int e, int s) { - const int bw = e-s+1; - val_t msk[3]; - val_t msk_lsh[3]; - val_t s0_lsh[3]; - mask_n(msk, 3, bw); - lsh_n(msk_lsh, msk, s, 3, 3); - lsh_n(s0_lsh, s0, s, 3, 3); - d[0] = (d[0] & ~msk_lsh[0]) | (s0_lsh[0] & msk_lsh[0]); - d[1] = (d[1] & ~msk_lsh[1]) | (s0_lsh[1] & msk_lsh[1]); - d[2] = (d[2] & ~msk_lsh[2]) | (s0_lsh[2] & msk_lsh[2]); - } - - static void rsha (val_t d[], val_t s0[], int amount, int w) { - rsha_n(d, s0, amount, 3, w); - } - static void rsh (val_t d[], val_t s0[], int amount) { - rsh_n(d, s0, amount, 3); - } - static void lsh (val_t d[], val_t s0[], int amount) { - lsh_n(d, s0, amount, 3, 3); - } - static void log2 (val_t d[], val_t s0[]) { - d[0] = log2_n(s0, 3); - } - static void set (val_t d[], val_t s0[]) { - d[0] = s0[0]; - d[1] = s0[1]; - d[2] = s0[2]; - } -}; - -static val_t __rand_val(val_t* seed) { - val_t x = *seed; - *seed = (x << 1) ^ (-(sval_t(x) < 0) & 0x1B); - return x; -} - -template -class dat_t { - public: - const static int n_words = ((w - 1) / 64) + 1; - // const static int n_words = (w >> CeilLog::v) + 1; - val_t values[n_words]; - inline int width ( void ) { return w; } - inline int n_words_of ( void ) { return n_words; } - inline bool to_bool ( void ) { return lo_word() != 0; } - inline val_t lo_word ( void ) { return values[0]; } - inline unsigned long to_ulong ( void ) { return (unsigned long)lo_word(); } - - std::string to_str () { - std::string rres, res; - int nn = (int)ceilf(w / 4.0); - for (int i = 0; i < n_words; i++) { - int n_nibs = nn < val_n_nibs() ? nn : val_n_nibs(); - for (int j = 0; j < n_nibs; j++) { - uint8_t nib = (values[i] >> (j*4))&0xf; - rres.push_back(hex_digs[nib]); - } - nn -= val_n_bits()/4; - } - res.push_back('0'); - res.push_back('x'); - for (int i = 0; i < rres.size(); i++) - res.push_back(rres[rres.size()-i-1]); - return res; - } - void randomize(val_t* seed) { - for (int i = 0; i < n_words; i++) - values[i] = __rand_val(seed); - if (val_n_word_bits(w)) - values[n_words-1] &= mask_val(val_n_word_bits(w)); - } - inline dat_t () { - } - template - inline dat_t (const dat_t& src) { - bit_word_funs::copy(values, (val_t*)src.values, src.n_words); - if (sw != w && val_n_word_bits(w)) - values[n_words-1] &= mask_val(val_n_word_bits(w)); - } - inline dat_t (const dat_t& src) { - bit_word_funs::set(values, (val_t*)src.values); - } - static inline dat_t from_vals(val_t val[n_words]) { - dat_t res; - for (int i = 0; i < n_words; i++) - res.values[i] = val[i]; - return res; - } - inline dat_t (val_t val) { - values[0] = val; - for (int i = 1; i < n_words; i++) - values[i] = 0; - } - template - dat_t mask(dat_t fill, int n) { - dat_t res; - bit_word_funs::mask(res.values, n); - return res; - } - template - dat_t mask(int n) { - dat_t res; - return res.mask(*this, n); - } - template - inline dat_t mask(void) { - dat_t res = mask(n); - return res; - } - val_t operator [] (size_t i) { - return values[i]; - } - dat_t operator + ( dat_t o ) { - dat_t res; - bit_word_funs::add(res.values, values, o.values, w); - return res; - } - dat_t operator - ( dat_t o ) { - dat_t res; - bit_word_funs::sub(res.values, values, o.values, w); - return res; - } - dat_t operator - ( ) { - return ~(*this) + DAT(1); - } - template - dat_t operator * ( dat_t o ) { - dat_t res; - bit_word_funs::mul(res.values, values, o.values, w, w2); - return res; - } - template - dat_t fix_times_fix( dat_t o ) { - if (w+w2 <= val_n_bits()) { - sval_t a = sval_t(values[0] << (val_n_bits()-w)) >> (val_n_bits()-w); - sval_t b = sval_t(o.values[0] << (val_n_bits()-w2)) >> (val_n_bits()-w2); - return dat_t((a * b) & mask_val(w+w2)); - } else { - val_t sgn_a = msb(); - dat_t abs_a = sgn_a ? -(*this) : (*this); - val_t sgn_b = o.msb(); - dat_t abs_b = sgn_b ? -o : o; - dat_t res = abs_a * abs_b; - return (sgn_a ^ sgn_b) ? -res : res; - } - } - dat_t operator / ( dat_t o ) { - dat_t res(0); - if (o == 0) { - res.fill_bit(1); - } else if (n_words == 1) { - res.values[0] = values[0] / o.values[0]; - } else { - dat_t<2*w> p = *this, d = o; - d = d << w; - - for (int i = w-1; i >= 0; i--) { - p = p << 1; - if (p >= d) { - p = p - d; - res.values[i / val_n_bits()] |= val_t(1) << (i % val_n_bits()); - } - } - } - return res; - } - dat_t operator % ( dat_t o ) { - return *this - *this / o * o; - } - dat_t ufix_times_fix( dat_t o ) { - return o.fix_times_ufix(*this); - } - template - dat_t fix_times_ufix( dat_t o ) { - if (w+w2 <= val_n_bits()) { - sval_t a = sval_t(values[0] << (val_n_bits()-w)) >> (val_n_bits()-w); - return dat_t((a * o.values[0]) & mask_val(w+w2)); - } else { - val_t sgn_a = msb(); - dat_t abs_a = sgn_a ? -(*this) : (*this); - dat_t res = abs_a * o; - return sgn_a ? -res : res; - } - } - inline bool operator < ( dat_t o ) { - return bit_word_funs::ltu(values, o.values); - } - inline bool operator <= ( dat_t o ) { - return bit_word_funs::lteu(values, o.values); - } - inline bool operator > ( dat_t o ) { - return o < *this; - } - inline bool operator >= ( dat_t o ) { - return o <= *this; - } - inline bool lt ( dat_t o ) { - return bit_word_funs::lt(values, o.values, w); - } - inline bool lte ( dat_t o ) { - return bit_word_funs::lte(values, o.values, w); - } - inline bool gt ( dat_t o ) { - return o.lt(*this); - } - inline bool gte ( dat_t o ) { - return o.lte(*this); - } - dat_t operator ^ ( dat_t o ) { - dat_t res; - bit_word_funs::bit_xor(res.values, values, o.values); - return res; - } - dat_t operator & ( dat_t o ) { - dat_t res; - bit_word_funs::bit_and(res.values, values, o.values); - return res; - } - dat_t operator | ( dat_t o ) { - dat_t res; - bit_word_funs::bit_or(res.values, values, o.values); - return res; - } - dat_t operator ~ ( void ) { - dat_t res; - bit_word_funs::bit_neg(res.values, values, w); - return res; - } - inline dat_t<1> operator ! ( void ) { - return DAT<1>(!lo_word()); - } - dat_t<1> operator && ( dat_t<1> o ) { - return DAT<1>(lo_word() & o.lo_word()); - } - dat_t<1> operator || ( dat_t<1> o ) { - return DAT<1>(lo_word() | o.lo_word()); - } - bool operator == ( dat_t o ) { - return bit_word_funs::eq(values, o.values); - } - bool operator == ( datz_t o ) { - return o == *this; - } - bool operator != ( dat_t o ) { - return bit_word_funs::neq(values, o.values); - } - dat_t operator << ( int amount ) { - dat_t res; - bit_word_funs::lsh(res.values, values, amount); - if (val_n_word_bits(w)) - res.values[n_words-1] &= mask_val(val_n_word_bits(w)); - return res; - } - inline dat_t operator << ( dat_t o ) { - return *this << o.lo_word(); - } - dat_t operator >> ( int amount ) { - dat_t res; - bit_word_funs::rsh(res.values, values, amount); - return res; - } - inline dat_t operator >> ( dat_t o ) { - return *this >> o.lo_word(); - } - dat_t rsha ( dat_t o) { - dat_t res; - int amount = o.lo_word(); - bit_word_funs::rsha(res.values, values, amount, w); - return res; - } - dat_t& operator = ( dat_t o ) { - bit_word_funs::set(values, o.values); - return *this; - } - dat_t fill_bit( val_t bit ) { - dat_t res; - val_t word = 0L - bit; - bit_word_funs::fill_nb(res.values, word, w); - return res; - } - // TODO: SPEED THIS UP - dat_t fill_byte( val_t byte, int nb, int n ) { - dat_t res; - bit_word_funs::fill(res.values, 0L); - for (size_t i = 0; i < n; i++) - res = (res << nb) | byte; - return res; - } - template - dat_t fill( void ) { - // TODO: GET RID OF IF'S - dat_t res; - if (w == 1) { - return res.fill_bit(lo_word()); - } else { - return res.fill_byte(lo_word(), w, n); - } - } - template - dat_t fill( dat_t n ) { - // TODO: GET RID OF IF'S - dat_t res; - if (w == 1) { - return res.fill_bit(lo_word()&1); - } else { - return res.fill_byte(lo_word(), w, n); - } - } - template - dat_t extract() { - dat_t res; - int i; - for (i = 0; i < val_n_full_words(dw); i++) - res.values[i] = values[i]; - if (val_n_word_bits(dw)) - res.values[i] = values[i] & mask_val(val_n_word_bits(dw)); - return res; - } - template - dat_t extract(val_t e, val_t s) { - dat_t x = (*this >> s); - return x.extract(); - } - template - inline dat_t extract(dat_t e, dat_t s) { - return extract(e.lo_word(), s.lo_word()); - } - - template - dat_t inject(dat_t src, val_t e, val_t s) { - // Modify this.values in place. - dat_t inject_src(src); // Enlarged if needed to match inject_dst - bit_word_funs::inject(values, inject_src.values, e, s); - return *this; - } - - template - inline dat_t inject(dat_t src, dat_t e, dat_t s) { - return inject(src, e.lo_word(), s.lo_word()); - } - - - template - inline dat_t log2() { - dat_t res; - bit_word_funs::log2(res.values, values); - return res; - } - inline val_t bit(val_t b) { - return (values[val_n_full_words(b)] >> val_n_word_bits(b)) & 1; - } - inline val_t msb() { - return values[n_words-1] >> val_n_word_bits(w-1); - } - template - inline dat_t<1> bit(dat_t b) { - return bit(b.lo_word()); - } -}; - -template -std::string dat_to_str(const dat_t& x) { - char s[w]; - s[dat_to_str(s, x)] = 0; - return s; -} - -static __inline__ int n_digits(int w, int base) { - return (int)ceil(log(2)/log(base)*w); -} - -template -int dat_to_str(char* s, dat_t x, int base = 16, char pad = '0') { - int n_digs = n_digits(w, base); - int j = n_digs-1, digit; - - do { - if (ispow2(base)) { - digit = x.lo_word() & (base-1); - x = x >> log2_1(base); - } else { - digit = (x % base).lo_word(); - x = x / base; - } - s[j] = (digit >= 10 ? 'a'-10 : '0') + digit; - } while (--j >= 0 && x != 0); - - for ( ; j >= 0; j--) - s[j] = pad; - - return n_digs; -} - -static __inline__ int dat_to_str(char* s, val_t x, int base = 16, char pad = '0') { - return dat_to_str(s, dat_t(x), base, pad); -} - -template -int fix_to_str(char* s, dat_t x, int base = 16, char pad = '0') { - bool neg = x.msb(); - s[0] = neg; - int len = dat_to_str(s+1, neg ? -x : x, base, pad); - return len+1; -} - -static __inline__ int flo_digits(int m, int e) { - return 2 + n_digits(m, 10) + 2 + n_digits(e, 10); -} - -template -int flo_to_str(char* s, dat_t x, char pad = ' ') { - char buf[1000]; - int n_digs = (w == 32) ? flo_digits(32, 8) : flo_digits(52, 11); - double val = (w == 32) ? toFloat(x.values[0]) : toDouble(x.values[0]); - // sprintf(buf, "%d %d%*e", w, n_digs, n_digs, val); - sprintf(buf, "%*e", n_digs, val); - assert(strlen(buf) <= n_digs); - for (int i = 0; i < n_digs; i++) - s[i] = (i < strlen(buf)) ? buf[i] : pad; - s[n_digs] = 0; - // printf("N-DIGS = %d BUF %lu PAD %lu\n", n_digs, strlen(buf), n_digs-strlen(buf)); - // return strlen(buf); - return n_digs; -} - -template -int dat_as_str(char* s, const dat_t& x) { - int i, j; - for (i = 0, j = (w/8-1)*8; i < w/8; i++, j -= 8) { - char ch = x.values[j/val_n_bits()] >> (j % val_n_bits()); - if (ch == 0) break; - s[i] = ch; - } - for ( ; i < w/8; i++) - s[i] = ' '; - return w/8; -} - -static __inline__ int dat_as_str(char* s, val_t x) { - return dat_as_str(s, dat_t(x)); -} - -#if __cplusplus >= 201103L -static void __attribute__((unused)) dat_format(char* s, const char* fmt) -{ - for (char c; (c = *fmt); fmt++) { - if (c == '%' && *++fmt != '%') - abort(); - *s++ = c; - } -} - -template -static void dat_format(char* s, const char* fmt, T value, Args... args) -{ - while (*fmt) { - if (*fmt == '%') { - switch(fmt[1]) { - case 'e': s += flo_to_str(s, value, ' '); break; - case 'h': s += dat_to_str(s, value, 16, '0'); break; - case 'b': s += dat_to_str(s, value, 2, '0'); break; - case 'd': s += dat_to_str(s, value, 10, ' '); break; - case 's': s += dat_as_str(s, value); break; - case '%': *s++ = '%'; break; - default: abort(); - } - return dat_format(s, fmt + 2, args...); - } else { - *s++ = *fmt++; - } - } - abort(); -} - -template -static dat_t dat_format(const char* fmt, Args... args) -{ -#if BYTE_ORDER != LITTLE_ENDIAN -# error dat_format assumes a little-endian architecture -#endif - char str[w/8+1]; - dat_format(str, fmt, args...); - - dat_t res; - res.values[res.n_words-1] = 0; - for (int i = 0; i < w/8; i++) - ((char*)res.values)[w/8-1-i] = str[i]; - return res; -} - -template -static ssize_t dat_fprintf(FILE *f, const char* fmt, Args... args) -{ - char str[w/8+1]; - dat_format(str, fmt, args...); - return fwrite(str, 1, w/8, f); -} - -template -static ssize_t dat_prints(std::ostream& s, const char* fmt, Args... args) -{ - char str[w/8+1]; - dat_format(str, fmt, args...); - s.write(str, w/8); - ssize_t ret = s.good() ? w/8 : -1; - return ret; -} -#endif /* C++11 */ - -template inline dat_t DAT(dat_t dat) { - dat_t res(dat); - return res; -} - -template inline dat_t LIT(val_t value) { - return DAT(value); -} - -template -inline dat_t mux ( dat_t<1> t, dat_t c, dat_t a ) { - dat_t mask; - bit_word_funs::fill(mask.values, -t.lo_word()); - return a ^ ((a ^ c) & mask); -} - -template -class datz_t : public dat_t { - public: - dat_t mask; - inline bool operator == ( dat_t o ) { - dat_t masked = (o & mask); - return (o & mask) == (dat_t)*this; - } -}; - -template datz_t inline LITZ(val_t value, val_t mask) { - datz_t res; res.mask.values[0] = mask; res.values[0] = value; return res; -} - -template < int w, int w1, int w2 > -inline dat_t cat(dat_t d1, dat_t d2) { - if (w <= val_n_bits() && w1 + w2 == w) - return DAT(d1.values[0] << (w2 & (val_n_bits()-1)) | d2.values[0]); - return DAT((DAT(d1) << w2) | DAT(d2)); -} - -template < int w1 > -inline dat_t<1> reduction_and(dat_t d) { - return DAT<1>(d == ~DAT(0)); -} - -template < int w1 > -inline dat_t<1> reduction_or(dat_t d) { - return DAT<1>(d != DAT(0)); -} - -// I am O(n) where n is number of bits in val_t. Future optimization would be log(n). -template < int w1 > -inline dat_t<1> reduction_xor(dat_t d) { - dat_t<1> res = DAT<1>(0); - val_t word = d.values[0]; - - for (int i = 1; i < d.n_words_of(); i++) - word ^= d.values[i]; - for (int i = 0; i < sizeof(val_t)*8; i++) { - res = res ^ DAT<1>(word & 1); - word = word >> 1; - } - - return res; -} - -template -class mem_t { - public: - dat_t contents[d]; - val_t dummy_seed; - val_t* seedp; - - int width() { - return w; - } - int length() { - return d; - } - - template - dat_t get (dat_t idx) { - return get(idx.lo_word() & (nextpow2_1(d)-1)); - } - dat_t get (val_t idx) { - if (!ispow2(d) && idx >= d) { - dat_t res; - res.randomize(seedp); - return res; - } - return contents[idx]; - } - val_t get (val_t idx, int word) { - if (!ispow2(d) && idx >= d) - return __rand_val(seedp) & (word == val_n_words(w) && val_n_word_bits(w) ? mask_val(w) : -1L); - return contents[idx].values[word]; - } - - template - void put (dat_t idx, dat_t val) { - put(idx.lo_word(), val); - } - void put (val_t idx, dat_t val) { - if (ispow2(d) || idx < d) - contents[idx] = val; - } - val_t put (val_t idx, int word, val_t val) { - if (ispow2(d) || idx < d) - contents[idx].values[word] = val; - } - - void print ( void ) { - for (int j = 0; j < d/4; j++) { - for (int i = 0; i < 4; i++) { - int idx = j*4+i; - printf("|%2d: %16llx| ", idx, contents[idx].lo_word()); - } - printf("\n"); - } - } - mem_t () { - dummy_seed = 1; - seedp = &dummy_seed; - for (int i = 0; i < d; i++) - contents[i] = DAT(0); - } - void randomize(val_t* seed) { - seedp = seed; - for (int i = 0; i < d; i++) - contents[i].randomize(seed); - } - size_t read_hex(const char *hexFileName) { - ifstream ifp(hexFileName); - if (ifp.fail()) { - printf("[error] Unable to open hex data file %s\n", hexFileName); - return -1; - } - std::string hex_line; - dat_t hex_dat; - for (int addr = 0; addr < d && !ifp.eof();) { - getline(ifp, hex_line); - if (dat_from_hex(hex_line, hex_dat) > 0) { - contents[addr++] = hex_dat; - } - } - ifp.close(); - return 0; - } -}; - -static __attribute__((unused)) char hex_to_char[] = "0123456789abcdef"; - -static int char_to_hex[] = { - -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, - -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, - -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,-1,-1,-1,-1,-1,-1, - -1,10,11,12,13,14,15,-1,-1,-1,-1,-1,-1,-1,-1,-1, - -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, - -1,10,11,12,13,14,15,-1,-1,-1,-1,-1,-1,-1,-1,-1, - -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, - -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, - -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, - -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, - -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, - -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, - -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, - -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, - -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1 }; - -// dat_from_hex: Read a hex value from a std::string into a given dat_t variable. -// Author: B. Richards, for parsing data formatted for Verilog $readmemh -// Arguments: -// hex_line A string containing hex numbers with embedded x, _ characters -// res A dat_t object to fill in with a return value -// offset Starting index in hex_line -// Return value: -// Success: returns next character offset -// Fail: 0 -template -size_t dat_from_hex(std::string hex_line, dat_t& res, size_t offset = 0) { - size_t first_digit, last_digit, comment; - - // Scan for the hex data bounds. - comment = hex_line.find_first_of("/", offset); - first_digit = hex_line.find_first_of("0123456789abcdefABCDEF", offset); - if (first_digit == std::string::npos) return 0; - if (comment != std::string::npos && comment < first_digit) return 0; - last_digit = hex_line.find_first_not_of("0123456789abcdefABCDEF_xX", first_digit); - if (last_digit == std::string::npos) { - last_digit = hex_line.length() - 1; - } else { - last_digit--; - } - - // Convert the hex data to a dat_t, from right to left. - int digit_val; - val_t word_accum = 0; - int digit, w_index, bit; - for (digit = last_digit, w_index = 0, bit = 0; digit >= (int)first_digit && w_index < res.n_words; digit--) { - digit_val = char_to_hex[hex_line[digit]]; - if (digit_val >= 0) { - word_accum |= ((val_t)digit_val) << bit; - bit += 4; - if (bit == 64) { - res.values[w_index] = word_accum; - word_accum = 0L; - bit = 0; - w_index++; - } - } - } - if (bit != 0) { - res.values[w_index] = word_accum; - } - // Return a pointer to the character after the converted value. - return last_digit + 1; -} - -#pragma GCC push_options -#pragma GCC optimize ("no-stack-protector") - -template -void dat_dump (FILE* f, const dat_t& val, val_t name) { - size_t pos = 0; - char str[1 + w + 1 + s + 1]; - - str[pos++] = 'b'; - for (int i = 0; i < w; i++) - str[pos + w-i-1] = '0' + ((val.values[i/val_n_bits()] >> (i%val_n_bits())) & 1); - pos += w; - - str[pos++] = ' '; - for (int i = 0; i < s; i++) { - str[pos++] = name; - name >>= 8; - } - str[pos++] = '\n'; - - fwrite(str, 1, sizeof(str), f); -} - -#pragma GCC pop_options - -inline std::string read_tok(FILE* f) { - std::string res; - bool is_skipping = true; - for (;;) { - char c = fgetc(f); - if (feof(f)) - return res; - if (is_skipping) { - if (char_to_hex[c] != -1) { - res.push_back(c); - is_skipping = false; - } - } else { - if (char_to_hex[c] == -1) { - ungetc(c, f); - return res; - } - res.push_back(c); - } - } -} - -template -void dat_dump(FILE* file, const mem_t& val, val_t name) { -} - -template mem_t MEM( void ); - -class mod_t { - public: - mod_t(): - dumpfile(NULL), - is_stale(false), - printStream() - {} - virtual ~mod_t() {} - std::vector< mod_t* > children; - virtual void init ( val_t rand_init=false ) { }; - virtual void clock_lo ( dat_t<1> reset ) { }; - virtual void clock_hi ( dat_t<1> reset ) { }; - virtual int clock ( dat_t<1> reset ) { }; - virtual void setClocks ( std::vector< int >& periods ) { }; - - // Returns a clone of this object's circuit state (both registers and wires). - // Currently, it is undefined what happens to other state (like dumpfile and - // timestep), so use with care. - virtual mod_t* clone() = 0; - // Sets this module's circuit state (registers and wires) from the src mod_t. - // For mod_t subclasses, src must be the same class. - // Returns true on success, and false on failure. Currently, no guarantees - // are made about state consistency on failure, - virtual bool set_circuit_from(mod_t* src) = 0; - - virtual void print ( FILE* f ) { }; - virtual void print ( std::ostream& s ) { }; - virtual void dump ( FILE* f, int t ) { }; - - void set_dumpfile(FILE* f) { - dumpfile = f; - } - - int timestep; - - void dump () { - if (dumpfile != NULL) dump(dumpfile, timestep); - timestep += 1; - } - - int step (bool is_reset, int n) { - int delta = 0; - dat_t<1> reset = LIT<1>(is_reset); - for (int i = 0; i < n; i++) { - if (is_reset) { - clock_lo(reset); - } - // Collect any print output. - print(printStream); - dump(); - delta += clock(reset); - } - return delta; - } - - void mark_stale (void) { - is_stale = true; - } - - void propagate_changes (void) { - if (is_stale) clock_lo(LIT<1>(false)); - is_stale = false; - } - - int has_output(void) { - return printStream.tellp(); - } - - std::string drain_output(void) { - return printStream.str(); - } - - // Since we have an element with a deleted copy constructor - printStream, - // we need to provide our own explicit copy constructor. - mod_t(const mod_t& src) { - children = src.children; - timestep = src.timestep; - is_stale = src.is_stale; - dumpfile = src.dumpfile; - } - - protected: - bool is_stale; - FILE* dumpfile; - std::basic_ostringstream< char > printStream; -}; - -#define ASSERT(cond, msg) { \ - if (!(cond)) \ - throw std::runtime_error("Assertion failed: " msg); \ -} - -#pragma GCC diagnostic pop -#endif diff --git a/src/main/resources/sim_api.h b/src/main/resources/sim_api.h new file mode 100644 index 00000000..9fe6ea1e --- /dev/null +++ b/src/main/resources/sim_api.h @@ -0,0 +1,390 @@ +#ifndef __SIM_API_H +#define __SIM_API_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +enum SIM_CMD { RESET, STEP, UPDATE, POKE, PEEK, FORCE, GETID, GETCHK, SETCLK, FIN }; +const int SIM_CMD_MAX_BYTES = 1024; +const int channel_data_offset_64bw = 4; // Offset from start of channel buffer to actual user data in 64bit words. +static size_t gSystemPageSize; + +template struct sim_data_t { + std::vector resets; + std::vector inputs; + std::vector outputs; + std::vector signals; + std::map signal_map; + std::map clk_map; + // Calculate the size (in bytes) of data stored in a vector. + size_t storage_size(const std::vector vec) { + int nitems = vec.size(); +#ifdef VPI_USER_H + return nitems * sizeof(T); +#else + size_t result = 0; + for (int i = 0; i < nitems; i++) { + result += vec[i]->get_num_words(); + } + return result * sizeof(val_t); +#endif + } +}; + +class channel_t { +public: +#define ROUND_UP(N, S) ((((N) + (S) -1 ) & (~((S) - 1)))) + void init_map() { + static std::string m_prefix("channel_t::init_map - "); + // ensure the data is available (a full page worth). + if (lseek(fd, map_size-1, SEEK_SET) == -1) { + perror((m_prefix + "file: " + full_file_path + " seek to end of page").c_str()); + exit(1); + } + if (write(fd, "", 1) == -1) { + perror((m_prefix + "file: " + full_file_path + " write byte").c_str()); + exit(1); + } + if (fsync(fd) == -1) { + perror((m_prefix + "file: " + full_file_path + " fsync").c_str()); + exit(1); + } + channel = (char*)mmap(NULL, map_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + if (channel == MAP_FAILED) { + perror((m_prefix + "file: " + full_file_path + " mmap").c_str()); + exit(1); + } + } + channel_t(std::string _file_name, size_t _data_size): file_name(_file_name), fd(open(file_name.c_str(), O_RDWR|O_CREAT|O_TRUNC, (mode_t)0600)), + map_size(ROUND_UP(_data_size + channel_data_offset_64bw * 8, gSystemPageSize)) { + static std::string m_prefix("channel_t::channel_t: "); + char * rp = realpath(file_name.c_str(), NULL); + full_file_path = std::string(rp == NULL ? file_name : rp); + if (rp != NULL) { + free(rp); + rp = NULL; + } + if (fd == -1) { + perror((m_prefix + "file: " + full_file_path + " open").c_str()); + exit(1); + } + init_map(); + } + + ~channel_t() { + munmap((void *)channel, map_size); + close(fd); + } + inline void aquire() { + channel[1] = 1; + channel[2] = 1; + while (channel[0] == 1 && channel[2] == 1); + } + inline void release() { channel[1] = 0; } + inline void produce() { channel[3] = 1; } + inline void consume() { channel[3] = 0; } + inline bool ready() { return channel[3] == 0; } + inline bool valid() { return channel[3] == 1; } + inline uint64_t* data() { return (uint64_t*)(channel + channel_data_offset_64bw); } + inline char* str() { return ((char *)channel + channel_data_offset_64bw); } + inline uint64_t& operator[](int i) { return data()[i*sizeof(uint64_t)]; } +private: + // Dekker's alg for sync + // channel[0] -> tester + // channel[1] -> simulator + // channel[2] -> turn + // channel[3] -> flag + // channel[4:] -> data + char volatile * channel; + const std::string file_name; + std::string full_file_path; + const int fd; + const size_t map_size; +}; + +template class sim_api_t { +public: + sim_api_t() { + // This is horrible, but we'd rather not have to generate another .cpp initialization file, + // and have all our clients update their Makefiles (if they don't use ours) to build the simulator. + if (gSystemPageSize == 0) { + gSystemPageSize = sysconf(_SC_PAGESIZE); + } + } + void init_channels() { + pid_t pid = getpid(); + std::ostringstream in_ch_name, out_ch_name, cmd_ch_name; + in_ch_name << std::dec << std::setw(8) << std::setfill('0') << pid << ".in"; + out_ch_name << std::dec << std::setw(8) << std::setfill('0') << pid << ".out"; + cmd_ch_name << std::dec << std::setw(8) << std::setfill('0') << pid << ".cmd"; + size_t input_size = this->sim_data.storage_size(this->sim_data.inputs); + in_channel = new channel_t(in_ch_name.str(), input_size); + size_t output_size = this->sim_data.storage_size(this->sim_data.outputs); + out_channel = new channel_t(out_ch_name.str(), output_size); + cmd_channel = new channel_t(cmd_ch_name.str(), SIM_CMD_MAX_BYTES); + + // Init channels + out_channel->consume(); + in_channel->release(); + out_channel->release(); + cmd_channel->release(); + // Inform the tester that the simulation is ready + char hostName[256]; + const char *hostNamep = NULL; + if (gethostname(hostName, sizeof(hostName) - 1) == 0) { + hostNamep = hostName; + } else { + hostNamep = ""; + } + time_t now; + time(&now); + // NOTE: ctime() generates a trailing '\n'. + std::cerr << "sim start on " << hostNamep << " at " << ctime(&now); + std::cerr << in_ch_name.str() << std::endl; + std::cerr << out_ch_name.str() << std::endl; + std::cerr << cmd_ch_name.str() << std::endl; + } + virtual ~sim_api_t() { + delete in_channel; + delete out_channel; + delete cmd_channel; + } + virtual void tick() { + static bool is_reset = false; + // First, Send output tokens + while(!send_tokens()); + if (is_reset) { + start(); + is_reset = false; + } + + // Next, handle commands from the testers + bool exit = false; + do { + size_t cmd; + while(!recv_cmd(cmd)); + switch ((SIM_CMD) cmd) { + case RESET: + reset(); is_reset = true; exit = true; break; + case STEP: + while(!recv_tokens()); step(); exit = true; break; + case UPDATE: + while(!recv_tokens()); update(); exit = true; break; + case POKE: poke(); break; + case PEEK: peek(); break; + case FORCE: poke(true); break; + case GETID: getid(); break; + case GETCHK: getchk(); break; + case SETCLK: setclk(); break; + case FIN: finish(); exit = true; break; + default: break; + } + } while (!exit); + } + +private: + channel_t *in_channel; + channel_t *out_channel; + channel_t *cmd_channel; + + virtual void reset() = 0; + virtual void start() = 0; + virtual void finish() = 0; + virtual void update() = 0; + virtual void step() = 0; + // Consumes input tokens + virtual void put_value(T& sig, std::string &value, bool force = false) = 0; + virtual size_t put_value(T& sig, uint64_t* data, bool force = false) = 0; + // Generate output tokens + virtual std::string get_value(T& sig) = 0; + virtual size_t get_value(T& sig, uint64_t* data) = 0; + // Find a signal of path + virtual int search(std::string& path) { return -1; } + virtual size_t get_chunk(T& sig) = 0; + + void poke(bool force = false) { + size_t id; + while(!recv_cmd(id)); + T obj = sim_data.signals[id]; + if (!obj) { + std::cerr << "Cannot find the object of id = " << id << std::endl; + finish(); + exit(2); // Not a normal exit. + } + while(!recv_value(obj, force)); + } + + void peek() { + size_t id; + while(!recv_cmd(id)); + T obj = sim_data.signals[id]; + if (!obj) { + std::cerr << "Cannot find the object of id = " << id << std::endl; + finish(); + exit(2); // Not a normal exit. + } + while(!send_value(obj)); + } + + void getid() { + std::string path; + while(!recv_cmd(path)); + std::map::iterator it = sim_data.signal_map.find(path); + if (it != sim_data.signal_map.end()) { + while(!send_resp(it->second)); + } else { + int id = search(path); + if (id < 0) { + // Issue warning message but don't exit here. + std::cerr << "Cannot find the object, " << path << std::endl; + } + while(!send_resp(id)); + } + } + + void getchk() { + size_t id; + while(!recv_cmd(id)); + T obj = sim_data.signals[id]; + if (!obj) { + std::cerr << "Cannot find the object of id = " << id << std::endl; + finish(); + exit(2); // Not a normal exit. + } + size_t chunk = get_chunk(obj); + while(!send_resp(chunk)); + } + + void setclk() { + std::string path; + while(!recv_cmd(path)); + typename std::map::iterator it = sim_data.clk_map.find(path); + if (it == sim_data.clk_map.end()) { + std::cerr << "Cannot find " << path << std::endl; + } + while(!recv_value(it->second)); + } + + bool recv_cmd(size_t& cmd) { + cmd_channel->aquire(); + bool valid = cmd_channel->valid(); + if (valid) { + cmd = (*cmd_channel)[0]; + cmd_channel->consume(); + } + cmd_channel->release(); + return valid; + } + + bool recv_cmd(std::string& path) { + cmd_channel->aquire(); + bool valid = cmd_channel->valid(); + if (valid) { + path = cmd_channel->str(); + cmd_channel->consume(); + } + cmd_channel->release(); + return valid; + } + + bool send_resp(size_t value) { + out_channel->aquire(); + bool ready = out_channel->ready(); + if (ready) { + (*out_channel)[0] = value; + out_channel->produce(); + } + out_channel->release(); + return ready; + } + + bool recv_value(T& obj, bool force = false) { + in_channel->aquire(); + bool valid = in_channel->valid(); + if (valid) { + put_value(obj, in_channel->data(), force); + in_channel->consume(); + } + in_channel->release(); + return valid; + } + + bool send_value(T& obj) { + out_channel->aquire(); + bool ready = out_channel->ready(); + if (ready) { + get_value(obj, out_channel->data()); + out_channel->produce(); + } + out_channel->release(); + return ready; + } + + bool recv_tokens() { + in_channel->aquire(); + bool valid = in_channel->valid(); + if (valid) { + size_t off = 0; + uint64_t *data = in_channel->data(); + for (size_t i = 0 ; i < sim_data.inputs.size() ; i++) { + T& sig = sim_data.inputs[i]; + off += put_value(sig, data+off); + } + in_channel->consume(); + } + in_channel->release(); + return valid; + } + + bool send_tokens() { + out_channel->aquire(); + bool ready = out_channel->ready(); + if (ready) { + size_t off = 0; + uint64_t *data = out_channel->data(); + for (size_t i = 0 ; i < sim_data.outputs.size() ; i++) { + T& sig = sim_data.outputs[i]; + off += get_value(sig, data+off); + } + out_channel->produce(); + } + out_channel->release(); + return ready; + } +protected: + sim_data_t sim_data; + + void read_signal_map(std::string filename) { + std::ifstream file(filename.c_str()); + if (!file) { + std::cerr << "Cannot open " << filename << std::endl; + finish(); + exit(2); // Not a normal exit. + } + std::string line; + size_t id = 0; + while (std::getline(file, line)) { + std::istringstream iss(line); + std::string path; + size_t width, n; + iss >> path >> width >> n; + sim_data.signal_map[path] = id; + id += n; + } + } +}; + +#endif //__SIM_API_H diff --git a/src/main/resources/template.txt b/src/main/resources/template.txt index f05b848b..e6d2bf65 100644 --- a/src/main/resources/template.txt +++ b/src/main/resources/template.txt @@ -11,6 +11,8 @@ inline ostream& operator << (ostream& os, const dat_t& arg){ return os; } +{!ostream_lsh!} + SC_MODULE({!name!}){ {!component_type!}* c; diff --git a/src/main/resources/vpi.cpp b/src/main/resources/vpi.cpp new file mode 100644 index 00000000..16cebde7 --- /dev/null +++ b/src/main/resources/vpi.cpp @@ -0,0 +1,74 @@ +#include "vpi.h" + +vpi_api_t* vpi_api = NULL; + +extern "C" { + +PLI_INT32 init_clks_calltf(PLI_BYTE8 *user_data) { + vpi_api->init_clks(); + return 0; +} + +PLI_INT32 init_rsts_calltf(PLI_BYTE8 *user_data) { + vpi_api->init_rsts(); + return 0; +} + +PLI_INT32 init_ins_calltf(PLI_BYTE8 *user_data) { + vpi_api->init_ins(); + return 0; +} + +PLI_INT32 init_outs_calltf(PLI_BYTE8 *user_data) { + vpi_api->init_outs(); + return 0; +} + +PLI_INT32 init_sigs_calltf(PLI_BYTE8 *user_data) { + vpi_api->init_sigs(); + vpi_api->init_channels(); + return 0; +} + +PLI_INT32 tick_calltf(PLI_BYTE8 *user_data) { + vpi_api->tick(); + return 0; +} + +PLI_INT32 tick_compiletf(PLI_BYTE8 *user_data) { + s_cb_data data_s; + data_s.reason = cbStartOfSimulation; + data_s.cb_rtn = sim_start_cb; + data_s.obj = NULL; + data_s.time = NULL; + data_s.value = NULL; + data_s.user_data = NULL; + vpi_free_object(vpi_register_cb(&data_s)); + + data_s.reason = cbEndOfSimulation; + data_s.cb_rtn = sim_end_cb; + data_s.obj = NULL; + data_s.time = NULL; + data_s.value = NULL; + data_s.user_data = NULL; + vpi_free_object(vpi_register_cb(&data_s)); + return 0; +} + +PLI_INT32 sim_start_cb(p_cb_data cb_data) { + vpi_api = new vpi_api_t; + return 0; +} + +PLI_INT32 sim_end_cb(p_cb_data cb_data) { + delete vpi_api; + vpi_control(vpiFinish, 0); + return 0; +} + +PLI_INT32 tick_cb(p_cb_data cb_data) { + vpi_api->tick(); + return 0; +} + +} diff --git a/src/main/resources/vpi.h b/src/main/resources/vpi.h new file mode 100644 index 00000000..a7ee7654 --- /dev/null +++ b/src/main/resources/vpi.h @@ -0,0 +1,279 @@ +#ifndef __VPI_H +#define __VPI_H + +#include "vpi_user.h" +#include "sim_api.h" +#include + +extern "C" PLI_INT32 tick_cb(p_cb_data cb_data); +extern "C" PLI_INT32 sim_start_cb(p_cb_data cb_data); +extern "C" PLI_INT32 sim_end_cb(p_cb_data cb_data); + +class vpi_api_t: public sim_api_t { +public: + vpi_api_t() { } + ~vpi_api_t() { } + + virtual void tick() { + while(!forces.empty()) { + vpi_put_value(forces.front(), NULL, NULL, vpiReleaseFlag); + forces.pop(); + } + sim_api_t::tick(); + } + + void init_clks() { + vpiHandle syscall_handle = vpi_handle(vpiSysTfCall, NULL); + vpiHandle arg_iter = vpi_iterate(vpiArgument, syscall_handle); + // Cache clocks + while (vpiHandle arg_handle = vpi_scan(arg_iter)) { + std::string name = vpi_get_str(vpiName, arg_handle); + sim_data.clk_map[name.substr(0, name.rfind("_len"))] = arg_handle; + } + } + + void init_rsts() { + vpiHandle syscall_handle = vpi_handle(vpiSysTfCall, NULL); + vpiHandle arg_iter = vpi_iterate(vpiArgument, syscall_handle); + // Cache Resets + while (vpiHandle arg_handle = vpi_scan(arg_iter)) { + sim_data.resets.push_back(arg_handle); + } + } + + void init_ins() { + vpiHandle syscall_handle = vpi_handle(vpiSysTfCall, NULL); + vpiHandle arg_iter = vpi_iterate(vpiArgument, syscall_handle); + // Cache Inputs + while (vpiHandle arg_handle = vpi_scan(arg_iter)) { + sim_data.inputs.push_back(arg_handle); + } + } + + void init_outs() { + vpiHandle syscall_handle = vpi_handle(vpiSysTfCall, NULL); + vpiHandle arg_iter = vpi_iterate(vpiArgument, syscall_handle); + // Cache Outputs + while (vpiHandle arg_handle = vpi_scan(arg_iter)) { + sim_data.outputs.push_back(arg_handle); + } + } + + void init_sigs() { + vpiHandle syscall_handle = vpi_handle(vpiSysTfCall, NULL); + top_handle = vpi_scan(vpi_iterate(vpiArgument, syscall_handle)); + search_signals(); + } + +private: + vpiHandle top_handle; + std::queue forces; + std::map sizes; + std::map chunks; + + void put_value(vpiHandle& sig, std::string& value, bool force=false) { + s_vpi_value value_s; + value_s.format = vpiHexStrVal; + value_s.value.str = (PLI_BYTE8*) value.c_str(); + vpi_put_value(sig, &value_s, NULL, force ? vpiForceFlag : vpiNoDelay); + if (force) forces.push(sig); + } + + size_t put_value(vpiHandle& sig, uint64_t* data, bool force=false) { + size_t chunk = get_chunk(sig); + s_vpi_value value_s; + s_vpi_vecval vecval_s[2*chunk]; + value_s.format = vpiVectorVal; + value_s.value.vector = vecval_s; + for (size_t i = 0 ; i < chunk ; i++) { + value_s.value.vector[2*i].aval = (int)data[i]; + value_s.value.vector[2*i+1].aval = (int)(data[i]>>32); + value_s.value.vector[2*i].bval = 0; + value_s.value.vector[2*i+1].bval = 0; + } + vpi_put_value(sig, &value_s, NULL, force ? vpiForceFlag : vpiNoDelay); + if (force) forces.push(sig); + return chunk; + } + + inline std::string get_value(vpiHandle& sig) { + s_vpi_value value_s; + value_s.format = vpiHexStrVal; + vpi_get_value(sig, &value_s); + return value_s.value.str; + } + + size_t get_value(vpiHandle& sig, uint64_t* data) { + size_t size = get_size(sig); + s_vpi_value value_s; + s_vpi_vecval vecval_s[size]; + value_s.format = vpiVectorVal; + value_s.value.vector = vecval_s; + vpi_get_value(sig, &value_s); + for (size_t i = 0 ; i < size ; i += 2) { + data[i>>1] = (uint64_t)value_s.value.vector[i].aval; + } + for (size_t i = 1 ; i < size ; i += 2) { + data[i>>1] |= (uint64_t)value_s.value.vector[i].aval << 32; + } + return ((size-1)>>1)+1; + } + + inline size_t get_size(vpiHandle &sig) { + return (size_t) (((vpi_get(vpiSize, sig)-1) >> 5) + 1); + } + + inline size_t get_chunk(vpiHandle &sig) { + return (size_t) (((vpi_get(vpiSize, sig)-1) >> 6) + 1); + } + + virtual void reset() { + for (size_t i = 0 ; i < sim_data.resets.size() ; i++) { + s_vpi_value value_s; + value_s.format = vpiHexStrVal; + value_s.value.str = (PLI_BYTE8*) "1"; + vpi_put_value(sim_data.resets[i], &value_s, NULL, vpiNoDelay); + } + } + + virtual void start() { + for (size_t i = 0 ; i < sim_data.resets.size() ; i++) { + s_vpi_value value_s; + value_s.format = vpiHexStrVal; + value_s.value.str = (PLI_BYTE8*) "0"; + vpi_put_value(sim_data.resets[i], &value_s, NULL, vpiNoDelay); + } + } + + virtual void finish() { vpi_control(vpiFinish, 0); } + + virtual void step() { } + + virtual void update() { + s_cb_data data_s; + s_vpi_time time_s; + time_s.type = vpiSimTime; + time_s.low = 0; + time_s.high = 0; + data_s.reason = cbReadWriteSynch; + data_s.cb_rtn = tick_cb; + data_s.obj = NULL; + data_s.time = &time_s; + data_s.value = NULL; + data_s.user_data = NULL; + vpi_free_object(vpi_register_cb(&data_s)); + } + + virtual size_t add_signal(vpiHandle& sig_handle, std::string& wire) { + size_t id = sim_data.signals.size(); + sim_data.signals.push_back(sig_handle); + sim_data.signal_map[wire] = id; + return id; + } + + int search_signals(const char *wire = NULL) { + int id = -1; + std::string wirepath = wire ? wire : ""; + int dotpos = wirepath.rfind("."); + std::string modpath = dotpos > 0 ? wirepath.substr(0, dotpos) : ""; + std::string wirename = dotpos > 0 ? wirepath.substr(dotpos+1) : ""; + int sbrpos = wirename.rfind("["); + std::string arrname = sbrpos > 0 ? wirename.substr(0, sbrpos) : ""; + std::queue modules; + size_t offset = std::string(vpi_get_str(vpiFullName, top_handle)).find(".") + 1; + + // Start from the top module + modules.push(top_handle); + + while (!modules.empty()) { + vpiHandle mod_handle = modules.front(); + modules.pop(); + + std::string modname = std::string(vpi_get_str(vpiFullName, mod_handle)).substr(offset); + // If the module is found + if (!wire || modpath == modname) { + // Iterate its nets + vpiHandle net_iter = vpi_iterate(vpiNet, mod_handle); + while (vpiHandle net_handle = vpi_scan(net_iter)) { + std::string netname = vpi_get_str(vpiName, net_handle); + std::string netpath = modname + "." + netname; + if (!wire && netname[0] != 'T' || wirename == netname) { + size_t netid = add_signal(net_handle, netpath); + if (wire) { id = netid; break; } + } else if (arrname == netname) { + vpiHandle bit_iter = vpi_iterate(vpiBit, net_handle); + while (vpiHandle bit_handle = vpi_scan(bit_iter)) { + std::string bitname = vpi_get_str(vpiName, bit_handle); + std::string bitpath = modname + "." + bitname; + size_t bitid = add_signal(bit_handle, bitpath); + id = wirename == bitname ? bitid : id; + } + } + } + if (id > 0) break; + + // Iterate its regs + vpiHandle reg_iter = vpi_iterate(vpiReg, mod_handle); + while (vpiHandle reg_handle = vpi_scan(reg_iter)) { + std::string regname = vpi_get_str(vpiName, reg_handle); + std::string regpath = modname + "." + regname; + if (!wire || wirename == regname) { + size_t regid = add_signal(reg_handle, regpath); + if (wire) { id = regid; break; } + } else if (arrname == regname) { + vpiHandle bit_iter = vpi_iterate(vpiBit, reg_handle); + while (vpiHandle bit_handle = vpi_scan(bit_iter)) { + std::string bitname = vpi_get_str(vpiName, bit_handle); + std::string bitpath = modname + "." + bitname; + size_t bitid = add_signal(bit_handle, bitpath); + id = regname == bitname ? bitid : id; + } + } + } + if (id > 0) break; + + // Iterate its mems + vpiHandle mem_iter = vpi_iterate(vpiRegArray, mod_handle); + while (vpiHandle mem_handle = vpi_scan(mem_iter)) { + std::string memname = vpi_get_str(vpiName, mem_handle); + if (!wire || arrname == memname) { + vpiHandle elm_iter = vpi_iterate(vpiReg, mem_handle); + while (vpiHandle elm_handle = vpi_scan(elm_iter)) { + std::string elmname = vpi_get_str(vpiName, elm_handle); + std::string elmpath = modname + "." + elmname; + size_t elmid = add_signal(elm_handle, elmpath); + id = (wire && wirename == elmname) ? elmid : id; + } + } + if (id > 0) break; + } + } + + // Find DFF + if (!wire || wirepath == modname) { + vpiHandle udp_iter = vpi_iterate(vpiPrimitive, mod_handle); + while (vpiHandle udp_handle = vpi_scan(udp_iter)) { + if (vpi_get(vpiPrimType, udp_handle) == vpiSeqPrim) { + size_t udpid = add_signal(udp_handle, modname); + if (wire) { id = udpid; break; } + } + } + + } + if (id > 0) break; + + vpiHandle sub_iter = vpi_iterate(vpiModule, mod_handle); + while (vpiHandle sub_handle = vpi_scan(sub_iter)) { + modules.push(sub_handle); + } + } + + return id; + } + + virtual int search(std::string& wire) { + return search_signals(wire.c_str()); + } +}; + +#endif // __VPI_H diff --git a/src/main/resources/vpi.tab b/src/main/resources/vpi.tab new file mode 100644 index 00000000..a3db460e --- /dev/null +++ b/src/main/resources/vpi.tab @@ -0,0 +1,6 @@ +$init_clks call=init_clks_calltf +$init_rsts call=init_rsts_calltf +$init_ins call=init_ins_calltf +$init_outs call=init_outs_calltf +$init_sigs call=init_sigs_calltf +$tick call=tick_calltf check=tick_compiletf acc+=rw,frc:* diff --git a/src/main/resources/vpi_user.cc b/src/main/resources/vpi_user.cc deleted file mode 100644 index f24d8e39..00000000 --- a/src/main/resources/vpi_user.cc +++ /dev/null @@ -1,562 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include - -using namespace std; - -/*========================================================================== - User Functions -=============================================================================*/ -int32_t wire_poke_calltf(char *user_data) { - queue modules; - vpiHandle syscall_handle = vpi_handle(vpiSysTfCall, NULL); - vpiHandle arg_iter = vpi_iterate(vpiArgument, syscall_handle); - // First argument: - s_vpi_value node_s; - node_s.format = vpiStringVal; - vpi_get_value(vpi_scan(arg_iter), &node_s); - // Second argument: - s_vpi_value value_s; - value_s.format = vpiIntVal; - vpi_get_value(vpi_scan(arg_iter), &value_s); - vpi_free_object(arg_iter); - - vpiHandle test_handle = vpi_scan(vpi_iterate(vpiModule, NULL)); - vpiHandle top_handle = vpi_scan(vpi_iterate(vpiModule, test_handle)); - // Construct node paths - string testname = vpi_get_str(vpiDefName, test_handle); - istringstream iss(node_s.value.str); - string nodename; - iss >> nodename; - ostringstream oss; - oss << testname << "." << nodename; - string nodepath = oss.str(); - - // Examine the regs in the testbench - // in order to give the correct input values - string modulepath = vpi_get_str(vpiFullName, top_handle); - string testpath = testname + nodepath.substr(modulepath.length(), nodepath.length() - modulepath.length()); - vpiHandle reg_iter = vpi_iterate(vpiReg, test_handle); - while (vpiHandle reg_handle = vpi_scan(reg_iter)) { - if (testpath == vpi_get_str(vpiFullName, reg_handle)) { - vpi_put_value(reg_handle, &value_s, NULL, vpiNoDelay); - vpi_printf("ok\n"); - return 0; - } - } - - // Start from the top module - modules.push(top_handle); - - bool found = false; - while (!modules.empty()) { - vpiHandle mod_handle = modules.front(); - modules.pop(); - - // Iterate its net - vpiHandle net_iter = vpi_iterate(vpiNet, mod_handle); - while (vpiHandle net_handle = vpi_scan(net_iter)) { - if (nodepath == vpi_get_str(vpiFullName, net_handle)) { - vpi_put_value(net_handle, &value_s, NULL, vpiNoDelay); - found = true; - } - if (found) break; - } - if (found) break; - - // Iterate its reg - vpiHandle reg_iter = vpi_iterate(vpiReg, mod_handle); - while (vpiHandle reg_handle = vpi_scan(reg_iter)) { - if (nodepath == vpi_get_str(vpiFullName, reg_handle)) { - vpi_put_value(reg_handle, &value_s, NULL, vpiNoDelay); - found = true; - } - if (found) break; - } - if (found) break; - - vpiHandle sub_iter = vpi_iterate(vpiModule, mod_handle); - while (vpiHandle sub_handle = vpi_scan(sub_iter)) { - modules.push(sub_handle); - } - } - - if (found) - vpi_printf("ok\n"); - else - vpi_printf("error\n"); - - return 0; -} - -int32_t wire_peek_calltf(char *user_data) { - queue modules; - vpiHandle syscall_handle = vpi_handle(vpiSysTfCall, NULL); - vpiHandle arg_iter = vpi_iterate(vpiArgument, syscall_handle); - // First argument: - s_vpi_value node_s; - node_s.format = vpiStringVal; - vpi_get_value(vpi_scan(arg_iter), &node_s); - vpi_free_object(arg_iter); - - vpiHandle test_handle = vpi_scan(vpi_iterate(vpiModule, NULL)); - vpiHandle top_handle = vpi_scan(vpi_iterate(vpiModule, test_handle)); - // Construct node paths - string testname = vpi_get_str(vpiDefName, test_handle); - istringstream iss(node_s.value.str); - string nodename; - iss >> nodename; - ostringstream oss; - oss << testname << "." << nodename; - string nodepath = oss.str(); - // Start from the top module - modules.push(top_handle); - - s_vpi_value value_s; - value_s.format = vpiHexStrVal; - bool found = false; - while (!modules.empty()) { - vpiHandle mod_handle = modules.front(); - modules.pop(); - - // Iterate its net - vpiHandle net_iter = vpi_iterate(vpiNet, mod_handle); - while (vpiHandle net_handle = vpi_scan(net_iter)) { - if (nodepath == vpi_get_str(vpiFullName, net_handle)) { - vpi_get_value(net_handle, &value_s); - found = true; - } - } - if (found) break; - - // Iterate its reg - vpiHandle reg_iter = vpi_iterate(vpiReg, mod_handle); - while (vpiHandle reg_handle = vpi_scan(reg_iter)) { - if (nodepath == vpi_get_str(vpiFullName, reg_handle)) { - vpi_get_value(reg_handle, &value_s); - found = true; - } - } - if (found) break; - - vpiHandle sub_iter = vpi_iterate(vpiModule, mod_handle); - while (vpiHandle sub_handle = vpi_scan(sub_iter)) { - modules.push(sub_handle); - } - } - - if (found) - vpi_printf("0x%s\n", value_s.value.str); - else - vpi_printf("error\n"); - - return 0; -} - -int32_t mem_poke_calltf(char *user_data) { - queue modules; - vpiHandle syscall_handle = vpi_handle(vpiSysTfCall, NULL); - vpiHandle arg_iter = vpi_iterate(vpiArgument, syscall_handle); - // First argument: - s_vpi_value node_s; - node_s.format = vpiStringVal; - vpi_get_value(vpi_scan(arg_iter), &node_s); - // Second argument: - s_vpi_value index_s; - index_s.format = vpiIntVal; - vpi_get_value(vpi_scan(arg_iter), &index_s); - // Third argument: - s_vpi_value value_s; - value_s.format = vpiIntVal; - vpi_get_value(vpi_scan(arg_iter), &value_s); - - vpiHandle test_handle = vpi_scan(vpi_iterate(vpiModule, NULL)); - vpiHandle top_handle = vpi_scan(vpi_iterate(vpiModule, test_handle)); - // Construct node paths - string testname = vpi_get_str(vpiDefName, test_handle); - istringstream iss(node_s.value.str); - string nodename; - iss >> nodename; - ostringstream oss; - oss << testname << "." << nodename; - string nodepath = oss.str(); - oss << "[" << index_s.value.integer << "]"; - string elmpath = oss.str(); - - // Examine the reg arrays in the testbench - // in order to give the correct input values - string modulepath = vpi_get_str(vpiFullName, top_handle); - string testpath = testname + nodepath.substr(modulepath.length(), nodepath.length() - modulepath.length()); - vpiHandle reg_iter = vpi_iterate(vpiRegArray, test_handle); - while (vpiHandle reg_handle = vpi_scan(reg_iter)) { - if (testpath == vpi_get_str(vpiFullName, reg_handle)) { - vpiHandle elm_iter = vpi_iterate(vpiReg, reg_handle); - while (vpiHandle elm_handle = vpi_scan(elm_iter)) { - if (elmpath == vpi_get_str(vpiFullName, elm_handle)) { - vpi_put_value(elm_handle, &value_s, NULL, vpiNoDelay); - vpi_printf("ok\n"); - return 0; - } - } - } - } - - // Start from the top module - modules.push(top_handle); - - bool found = false; - while (!modules.empty()) { - vpiHandle mod_handle = modules.front(); - modules.pop(); - - // Iterate its net arrays - vpiHandle net_iter = vpi_iterate(vpiNetArray, mod_handle); - while (vpiHandle net_handle = vpi_scan(net_iter)) { - if (nodepath == vpi_get_str(vpiFullName, net_handle)) { - vpiHandle elm_iter = vpi_iterate(vpiNet, net_handle); - while (vpiHandle elm_handle = vpi_scan(elm_iter)) { - if (elmpath == vpi_get_str(vpiFullName, elm_handle)){ - vpi_put_value(elm_handle, &value_s, NULL, vpiNoDelay); - found = true; - } - if (found) break; - } - } - if (found) break; - } - if (found) break; - - // Iterate its reg arrays - vpiHandle reg_iter = vpi_iterate(vpiRegArray, mod_handle); - while (vpiHandle reg_handle = vpi_scan(reg_iter)) { - if (nodepath == vpi_get_str(vpiFullName, reg_handle)) { - vpiHandle elm_iter = vpi_iterate(vpiReg, reg_handle); - while (vpiHandle elm_handle = vpi_scan(elm_iter)) { - if (elmpath == vpi_get_str(vpiFullName, elm_handle)){ - vpi_put_value(elm_handle, &value_s, NULL, vpiNoDelay); - found = true; - } - if (found) break; - } - } - if (found) break; - } - if (found) break; - - vpiHandle sub_iter = vpi_iterate(vpiModule, mod_handle); - while (vpiHandle sub_handle = vpi_scan(sub_iter)) { - modules.push(sub_handle); - } - } - - if (found) - vpi_printf("ok\n"); - else - vpi_printf("error\n"); -} - -int32_t mem_peek_calltf(char *user_data) { - queue modules; - vpiHandle syscall_handle = vpi_handle(vpiSysTfCall, NULL); - vpiHandle arg_iter = vpi_iterate(vpiArgument, syscall_handle); - // First argument: - s_vpi_value node_s; - node_s.format = vpiStringVal; - vpi_get_value(vpi_scan(arg_iter), &node_s); - // Second argument: - s_vpi_value index_s; - index_s.format = vpiIntVal; - vpi_get_value(vpi_scan(arg_iter), &index_s); - - vpiHandle test_handle = vpi_scan(vpi_iterate(vpiModule, NULL)); - vpiHandle top_handle = vpi_scan(vpi_iterate(vpiModule, test_handle)); - // Construct node paths - string testname = vpi_get_str(vpiDefName, test_handle); - istringstream iss(node_s.value.str); - string nodename; - iss >> nodename; - ostringstream oss; - oss << testname << "." << nodename; - string nodepath = oss.str(); - oss << "[" << index_s.value.integer << "]"; - string elmpath = oss.str(); - // Start from the top module - modules.push(top_handle); - - s_vpi_value value_s; - value_s.format = vpiHexStrVal; - bool found = false; - while (!modules.empty()) { - vpiHandle mod_handle = modules.front(); - modules.pop(); - - // Iterate its net arrays - vpiHandle net_iter = vpi_iterate(vpiNetArray, mod_handle); - while (vpiHandle net_handle = vpi_scan(net_iter)) { - if (nodepath == vpi_get_str(vpiFullName, net_handle)) { - vpiHandle elm_iter = vpi_iterate(vpiNet, net_handle); - while (vpiHandle elm_handle = vpi_scan(elm_iter)) { - if (elmpath == vpi_get_str(vpiFullName, elm_handle)){ - vpi_get_value(elm_handle, &value_s); - found = true; - } - if (found) break; - } - } - if (found) break; - } - if (found) break; - - // Iterate its reg arrays - vpiHandle reg_iter = vpi_iterate(vpiRegArray, mod_handle); - while (vpiHandle reg_handle = vpi_scan(reg_iter)) { - if (nodepath == vpi_get_str(vpiFullName, reg_handle)) { - vpiHandle elm_iter = vpi_iterate(vpiReg, reg_handle); - while (vpiHandle elm_handle = vpi_scan(elm_iter)) { - if (elmpath == vpi_get_str(vpiFullName, elm_handle)){ - vpi_get_value(elm_handle, &value_s); - found = true; - } - if (found) break; - } - } - if (found) break; - } - if (found) break; - - vpiHandle sub_iter = vpi_iterate(vpiModule, mod_handle); - while (vpiHandle sub_handle = vpi_scan(sub_iter)) { - modules.push(sub_handle); - } - } - - if (found) - vpi_printf("0x%s\n", value_s.value.str); - else - vpi_printf("error\n"); -} - -/*========================================================================== - Compile Time Functions -=============================================================================*/ - -int32_t wire_poke_compiletf (char *user_data) { - vpiHandle syscall_handle = vpi_handle(vpiSysTfCall, NULL); - vpiHandle arg_iter = vpi_iterate(vpiArgument, syscall_handle), arg_handle; - bool error = false; - - if (arg_iter == NULL) { - vpi_printf("ERROR: $wire_poke requires at least two argument(nodename, hex_value)\n"); - vpi_control(vpiFinish, 1); /* abort simulation */ - return 0; - } - - arg_handle = vpi_scan(arg_iter); - if (vpi_get(vpiType, arg_handle) != vpiReg && vpi_get(vpiType, arg_handle) != vpiStringConst) { - vpi_printf("ERROR: $wire_poke requires the first argument as a string(nodename)\n"); - error = true; - } - - arg_handle = vpi_scan(arg_iter); - if (vpi_get(vpiType, arg_handle) != vpiReg && vpi_get(vpiType, arg_handle) != vpiHexConst) { - vpi_printf("ERROR: $wire_poke requires the second argument as a hex number(value)\n"); - error = true; - } - - if (vpi_scan(arg_iter) != NULL) { - vpi_printf("ERROR: $wire_poke requires only two arguments(nodename, hex_value))\n"); - error = true; - } - - if (error) { - vpi_control(vpiFinish, 1); /* abort simulation */ - return 0; - } - return 0; -} - -int32_t wire_peek_compiletf (char *user_data) { - vpiHandle syscall_handle = vpi_handle(vpiSysTfCall, NULL); - vpiHandle arg_iter = vpi_iterate(vpiArgument, syscall_handle), arg_handle; - bool error = false; - - if (arg_iter == NULL) { - vpi_printf("ERROR: $wire_peek requires at least one argument(nodename)\n"); - vpi_control(vpiFinish, 1); /* abort simulation */ - return 0; - } - - arg_handle = vpi_scan(arg_iter); - if (vpi_get(vpiType, arg_handle) != vpiReg && vpi_get(vpiType, arg_handle) != vpiStringConst) { - vpi_printf("ERROR: $wire_peek requires the first argument as a string(nodename)\n"); - error = true; - } - - if (vpi_scan(arg_iter) != NULL) { - vpi_printf("ERROR: $wire_peek requires only one arguments(nodename))\n"); - error = true; - } - - if (error) { - vpi_control(vpiFinish, 1); /* abort simulation */ - return 0; - } - return 0; -} - -int32_t mem_poke_compiletf (char *user_data) { - vpiHandle syscall_handle = vpi_handle(vpiSysTfCall, NULL); - vpiHandle arg_iter = vpi_iterate(vpiArgument, syscall_handle), arg_handle; - bool error = false; - - if (arg_iter == NULL) { - vpi_printf("ERROR: $mem_poke requires at least three argument(nodename, offset, hex_value)\n"); - vpi_control(vpiFinish, 1); /* abort simulation */ - return 0; - } - - arg_handle = vpi_scan(arg_iter); - if (vpi_get(vpiType, arg_handle) != vpiReg && vpi_get(vpiType, arg_handle) != vpiStringConst) { - vpi_printf("ERROR: $mem_poke requires the first argument as a string(nodename)\n"); - error = true; - } - - arg_handle = vpi_scan(arg_iter); - if (vpi_get(vpiType, arg_handle) != vpiIntegerVar && vpi_get(vpiType, arg_handle) != vpiDecConst) { - vpi_printf("ERROR: $mem_poke requires the second argument as a integer(offset)\n"); - error = true; - } - - arg_handle = vpi_scan(arg_iter); - if (vpi_get(vpiType, arg_handle) != vpiReg && vpi_get(vpiType, arg_handle) != vpiHexConst) { - vpi_printf("ERROR: $mem_poke requires the third argument as a hex string(value)\n"); - error = true; - } - - if (vpi_scan(arg_iter) != NULL) { - vpi_printf("ERROR: $mem_poke requires only three arguments(nodename, offset, hex_value))\n"); - error = true; - } - - if (error) { - vpi_control(vpiFinish, 1); /* abort simulation */ - return 0; - } - return 0; -} - -int32_t mem_peek_compiletf (char *user_data) { - vpiHandle syscall_handle = vpi_handle(vpiSysTfCall, NULL); - vpiHandle arg_iter = vpi_iterate(vpiArgument, syscall_handle), arg_handle; - bool error = false; - - if (arg_iter == NULL) { - vpi_printf("ERROR: $mem_peek requires at least two argument(nodename, offset, hex_value)\n"); - vpi_control(vpiFinish, 1); /* abort simulation */ - return 0; - } - - arg_handle = vpi_scan(arg_iter); - if (vpi_get(vpiType, arg_handle) != vpiReg && vpi_get(vpiType, arg_handle) != vpiStringConst) { - vpi_printf("ERROR: $mem_peek requires the first argument as a string(nodename)\n"); - error = true; - } - - arg_handle = vpi_scan(arg_iter); - if (vpi_get(vpiType, arg_handle) != vpiIntegerVar && vpi_get(vpiType, arg_handle) != vpiDecConst) { - vpi_printf("ERROR: $mem_peek requires the second argument as a integer(offset)\n"); - error = true; - } - - if (vpi_scan(arg_iter) != NULL) { - vpi_printf("ERROR: $mem_peek requires only two arguments(nodename, offset))\n"); - error = true; - } - - if (error) { - vpi_control(vpiFinish, 1); /* abort simulation */ - return 0; - } - return 0; -} - - -/*========================================================================== - Registration Functions -=============================================================================*/ - -void wire_poke_registration() { - s_vpi_systf_data tf_data; - - tf_data.type = vpiSysTask; - tf_data.tfname = "$wire_poke"; - tf_data.sizetf = NULL; - tf_data.calltf = wire_poke_calltf; - tf_data.compiletf = wire_poke_compiletf; - tf_data.user_data = NULL; - - vpi_register_systf(&tf_data); - - return; -} - -void wire_peek_registration() { - s_vpi_systf_data tf_data; - - tf_data.type = vpiSysTask; - tf_data.tfname = "$wire_peek"; - tf_data.sizetf = NULL; - tf_data.calltf = wire_peek_calltf; - tf_data.compiletf = wire_peek_compiletf; - tf_data.user_data = NULL; - - vpi_register_systf(&tf_data); - - return; -} - -void mem_poke_registration() { - s_vpi_systf_data tf_data; - - tf_data.type = vpiSysTask; - tf_data.tfname = "$mem_poke"; - tf_data.sizetf = NULL; - tf_data.calltf = mem_poke_calltf; - tf_data.compiletf = mem_poke_compiletf; - tf_data.user_data = NULL; - - vpi_register_systf(&tf_data); - - return; -} - -void mem_peek_registration() { - s_vpi_systf_data tf_data; - - tf_data.type = vpiSysTask; - tf_data.tfname = "$mem_peek"; - tf_data.sizetf = NULL; - tf_data.calltf = mem_peek_calltf; - tf_data.compiletf = mem_peek_compiletf; - tf_data.user_data = NULL; - - vpi_register_systf(&tf_data); - - return; -} - -/*========================================================================== - Start-up Array -=============================================================================*/ -void (*vlog_startup_routines[]) () = { - wire_poke_registration, - wire_peek_registration, - mem_poke_registration, - mem_peek_registration, - 0 -}; diff --git a/src/main/scala/AdvTester.scala b/src/main/scala/AdvTester.scala index f56318f7..8e51d7c7 100644 --- a/src/main/scala/AdvTester.scala +++ b/src/main/scala/AdvTester.scala @@ -1,5 +1,5 @@ /* - Copyright (c) 2011, 2012, 2013, 2014 The Regents of the University of + Copyright (c) 2011 - 2016 The Regents of the University of California (Regents). All Rights Reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: @@ -34,13 +34,39 @@ */ package Chisel.AdvTester // May eventually add this to the base Chisel package import Chisel._ -import scala.reflect.ClassTag import scala.collection.mutable.ArrayBuffer -class AdvTester[+T <: Module](val dut: T) extends Tester[T](dut, false) { - val defaultMaxCycles = 1024 - var cycles = 0 - var pass = true +trait AdvTests extends Tests { + def cycles: Long + def wire_poke(port: Bits, target: Boolean): Unit + def wire_poke(port: Bits, target: Int): Unit + def wire_poke(port: Bits, target: Long): Unit + def wire_poke(port: Bits, target: BigInt): Unit + def wire_poke(port: Dbl, target: Double): Unit + def wire_poke(port: Aggregate, target: Array[BigInt]): Unit + def reg_poke(port: Bits, target: BigInt): Unit + def reg_poke(port: Aggregate, target: Array[BigInt]): Unit + def takestep(work: => Unit = {}): Unit + def takesteps(n: Int)(work: =>Unit = {}): Unit + def until(pred: =>Boolean, maxCycles: Long = 0L)(work: =>Unit): Boolean + def eventually(pred: =>Boolean, maxCycles: Long = 0L): Boolean + def do_until(work: =>Unit)(pred: =>Boolean, maxCycles: Long = 0L): Boolean +} + +object AdvTester { + implicit def strToOption(s: String) = if (s.isEmpty) None else Option(s) +} + +class AdvTester[+T <: Module](val dut: T, isTrace: Boolean = false, _base: Int = 16, + testCmd: Option[String] = Driver.testCommand, dumpFile: Option[String] = None) + extends Tester[T](dut, isTrace, _base, testCmd, dumpFile) { + val defaultMaxCycles = 1024L + var _cycles = 0L + def cycles = _cycles + override def incTime(n: Int) { + _cycles += n + super.incTime(n) + } // List of scala objects that need to be processed along with the test benches, like sinks and sources val preprocessors = new ArrayBuffer[Processable]() @@ -52,16 +78,23 @@ class AdvTester[+T <: Module](val dut: T) extends Tester[T](dut, false) { // This section of code lets testers easily emulate have registers right before dut inputs // This testing style conforms with the general ASPIRE testbench style // Also, to ensure difference enforced, poke 'deprecated' and replaced with wire_poke + def wire_poke(port: Bits, target: Boolean) = { super.poke(port, int(target)) } + def wire_poke(port: Bits, target: Int) = { super.poke(port, int(target)) } + def wire_poke(port: Bits, target: Long) = { super.poke(port, int(target)) } def wire_poke(port: Bits, target: BigInt) = { super.poke(port, target) } + def wire_poke(port: Flo, target: Float) = { super.poke(port, target) } + def wire_poke(port: Dbl, target: Double) = { super.poke(port, target) } def wire_poke(port: Aggregate, target: Array[BigInt]) = { super.poke(port, target) } - override def poke(port: Bits, target: BigInt) = require(false, "poke hidden for AdvTester, use wire_poke or reg_poke") - override def poke(port: Aggregate, target: Array[BigInt]) = require(false, "poke hidden for AdvTester, use wire_poke or reg_poke") + override def poke(port: Bits, target: BigInt) = + require(false, "poke hidden for AdvTester, use wire_poke or reg_poke") + override def poke(port: Aggregate, target: Array[BigInt]) = + require(false, "poke hidden for AdvTester, use wire_poke or reg_poke") - val registered_bits_updates = new scala.collection.mutable.HashMap[Bits,BigInt]() - val registered_aggr_updates = new scala.collection.mutable.HashMap[Aggregate,Array[BigInt]]() + private val registered_bits_updates = new scala.collection.mutable.HashMap[Bits,BigInt]() + private val registered_aggr_updates = new scala.collection.mutable.HashMap[Aggregate,Array[BigInt]]() - def do_registered_updates() = { + private def do_registered_updates() = { registered_bits_updates.foreach( kv => wire_poke(kv._1,kv._2) ) registered_aggr_updates.foreach( kv => wire_poke(kv._1,kv._2) ) @@ -77,12 +110,18 @@ class AdvTester[+T <: Module](val dut: T) extends Tester[T](dut, false) { // This function replaces step in the advanced tester and makes sure all tester features are clocked in the appropriate order def takestep(work: => Unit = {}): Unit = { - cycles += 1 - step(1) - do_registered_updates() - preprocessors.foreach(_.process()) // e.g. sinks - work - postprocessors.foreach(_.process()) + try { + step(1) + do_registered_updates() + preprocessors.foreach(_.process()) // e.g. sinks + work + postprocessors.foreach(_.process()) + } catch { + case e: java.lang.AssertionError => + assert(false, e.toString) // catch assert + case e: java.lang.IllegalArgumentException => + assert(false, e.toString) // catch require + } } def takesteps(n: Int)(work: =>Unit = {}): Unit = { require(n>0, "Number of steps taken must be positive integer.") @@ -90,8 +129,8 @@ class AdvTester[+T <: Module](val dut: T) extends Tester[T](dut, false) { } // Functions to step depending on predicates - def until(pred: =>Boolean, maxCycles: Int = defaultMaxCycles)(work: =>Unit): Boolean = { - var timeout_cycles = 0 + def until(pred: =>Boolean, maxCycles: Long = defaultMaxCycles)(work: =>Unit): Boolean = { + var timeout_cycles = 0L while(!pred && (timeout_cycles < maxCycles)) { takestep(work) timeout_cycles += 1 @@ -100,19 +139,20 @@ class AdvTester[+T <: Module](val dut: T) extends Tester[T](dut, false) { "until timed out after %d cycles".format(timeout_cycles)) pred } - def eventually(pred: =>Boolean, maxCycles: Int = defaultMaxCycles) = {until(pred, maxCycles){}} - def do_until(work: =>Unit)(pred: =>Boolean, maxCycles: Int = defaultMaxCycles): Boolean = { + def eventually(pred: =>Boolean, maxCycles: Long = defaultMaxCycles) = {until(pred, maxCycles){}} + def do_until(work: =>Unit)(pred: =>Boolean, maxCycles: Long = defaultMaxCycles): Boolean = { takestep(work) until(pred, maxCycles){work} } def assert(expr: Boolean, errMsg:String = "") = { - pass &= expr - if(!expr && errMsg != "") { println("ASSERT FAILED: " + errMsg) } + if (!expr && !errMsg.isEmpty) { + addEvent(new DumpEvent(s"ASSERT FAILED: ${errMsg}")) + fail + } expr } - class DecoupledSink[T <: Data, R]( socket: DecoupledIO[T], cvt: T=>R ) extends Processable { var max_count = -1 @@ -135,7 +175,8 @@ class AdvTester[+T <: Module](val dut: T) extends Tester[T](dut, false) { preprocessors += this } object DecoupledSink { - def apply[T<:Bits](socket: DecoupledIO[T]) = new DecoupledSink(socket, (socket_bits: T) => peek(socket_bits)) + def apply[T<:Bits](socket: DecoupledIO[T]) = + new DecoupledSink(socket, (socket_bits: T) => peek(socket_bits)) } class ValidSink[T <: Data, R]( socket: ValidIO[T], cvt: T=>R ) extends Processable @@ -153,7 +194,8 @@ class AdvTester[+T <: Module](val dut: T) extends Tester[T](dut, false) { preprocessors += this } object ValidSink { - def apply[T<:Bits](socket: ValidIO[T]) = new ValidSink(socket, (socket_bits: T) => peek(socket_bits)) + def apply[T<:Bits](socket: ValidIO[T]) = + new ValidSink(socket, (socket_bits: T) => peek(socket_bits)) } class DecoupledSource[T <: Data, R]( socket: DecoupledIO[T], post: (T,R)=>Unit ) extends Processable @@ -183,7 +225,8 @@ class AdvTester[+T <: Module](val dut: T) extends Tester[T](dut, false) { postprocessors += this } object DecoupledSource { - def apply[T<:Bits](socket: DecoupledIO[T]) = new DecoupledSource(socket, (socket_bits: T, in: BigInt) => reg_poke(socket_bits, in)) + def apply[T<:Bits](socket: DecoupledIO[T]) = + new DecoupledSource(socket, (socket_bits: T, in: BigInt) => reg_poke(socket_bits, in)) } class ValidSource[T <: Data, R]( socket: ValidIO[T], post: (T,R)=>Unit ) extends Processable @@ -210,9 +253,9 @@ class AdvTester[+T <: Module](val dut: T) extends Tester[T](dut, false) { postprocessors += this } object ValidSource { - def apply[T<:Bits](socket: ValidIO[T]) = new ValidSource(socket, (socket_bits: T, in: BigInt) => reg_poke(socket_bits, in)) + def apply[T<:Bits](socket: ValidIO[T]) = + new ValidSource(socket, (socket_bits: T, in: BigInt) => reg_poke(socket_bits, in)) } - } trait Processable { diff --git a/src/main/scala/Aggregate.scala b/src/main/scala/Aggregate.scala index 6f4984c9..2baebc23 100644 --- a/src/main/scala/Aggregate.scala +++ b/src/main/scala/Aggregate.scala @@ -1,5 +1,5 @@ /* - Copyright (c) 2011, 2012, 2013, 2014 The Regents of the University of + Copyright (c) 2011 - 2016 The Regents of the University of California (Regents). All Rights Reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: @@ -30,13 +30,11 @@ package Chisel -import Node._ -import ChiselError._ - abstract class Aggregate extends Data { - override def getWidth: Int = this.flatten.map(_._2.getWidth).fold(0)(_+_) + override def getWidth: Int = this.flatten.map(_._2.getWidth).fold(0)(_ + _) // Aggregate classes do not generally 'live' in the graph so width inference // will not touch these nodes and thus must get their width by looking // into the container + override def isWired: Boolean = this.flatten.forall(_._2.isWired) + override def setIsWired(value: Boolean): Unit = this.flatten.map(_._2.setIsWired(value)) } - diff --git a/src/main/scala/Assert.scala b/src/main/scala/Assert.scala index 3f1aec9a..7ef860bf 100644 --- a/src/main/scala/Assert.scala +++ b/src/main/scala/Assert.scala @@ -1,5 +1,5 @@ /* - Copyright (c) 2011, 2012, 2013, 2014 The Regents of the University of + Copyright (c) 2011 - 2016 The Regents of the University of California (Regents). All Rights Reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: @@ -31,29 +31,27 @@ package Chisel import scala.collection.mutable.HashMap -import scala.collection.mutable.ArrayBuffer -import Node._ -import ChiselError._ class Assert(condIn: Bool, resetIn: Bool, val message: String) extends Delay { inputs += condIn || resetIn inputs += resetIn def cond: Node = inputs(0) + def cond_=(x: Bool) { inputs(0) = x } def reset: Node = inputs(1) } class BitsInObject(x: Node) extends UInt { inputs += x - inferWidth = widthOf(0) + inferWidth = Node.widthOf(0) override lazy val isInObject: Boolean = true } -class PrintfBase(formatIn: String, argsIn: Seq[Node]) extends Node { +class PrintfBase(formatIn: String, argsIn: Seq[Node]) extends Delay { inputs ++= argsIn.map(a => new BitsInObject(a)) - def args: ArrayBuffer[Node] = inputs + def args = inputs override lazy val isInObject: Boolean = true def decIntSize(x: Int) = math.ceil(math.log(2)/math.log(10)*x).toInt - def decFloSize(m: Int, e: Int) = (2+decIntSize(m)+2+decIntSize(e)) + def decFloSize(m: Int, e: Int) = (2 + decIntSize(m) + 2 + decIntSize(e)) private var formats = "" private val lengths = new HashMap[Char, (Int => Int)] @@ -92,22 +90,15 @@ class PrintfBase(formatIn: String, argsIn: Seq[Node]) extends Node { } def argWidth: (=> Node) => Width = { (x) => { - if (x != null) { - var unknown = false - val argLength = formats.zip(inputs).map{case (a,b) => { - lengths(a)({ val w = b.widthW;if (w.isKnown) w.needWidth() else {unknown = true; 0}}) - }}.sum - if (unknown) - Width() - else - Width(8*(format.length - 2*formats.length + argLength)) - } else { - Width() - } + var unknown = false + val argLength = formats.zip(inputs).map{case (a,b) => { + lengths(a)({ val w = b.widthW;if (w.isKnown) w.needWidth() else {unknown = true; 0}}) + }}.sum + if (unknown) Width() + else Width(8*(format.length - 2*formats.length + argLength)) }} inferWidth = argWidth - override def isReg: Boolean = true override lazy val isInVCD: Boolean = false } @@ -115,7 +106,12 @@ class Sprintf(formatIn: String, argsIn: Seq[Node]) extends PrintfBase(formatIn, class Printf(condIn: Bool, formatIn: String, argsIn: Seq[Node]) extends PrintfBase(formatIn, argsIn) { inputs += condIn - override def args: ArrayBuffer[Node] = inputs.init + override def args = inputs.init // : ArrayBuffer[Node] = inputs.init def cond: Node = inputs.last - def assignClock(clk: Clock): Unit = { clock = clk } + def cond_=(x: Bool) { inputs(inputs.size-1) = x } +} + +// Chisel3 compatibility +object stop { + def apply(): Unit = Module.current.assert(Bool(false), "stop") } diff --git a/src/main/scala/Backend.scala b/src/main/scala/Backend.scala index 60979c4e..9619eb62 100644 --- a/src/main/scala/Backend.scala +++ b/src/main/scala/Backend.scala @@ -1,5 +1,5 @@ /* - Copyright (c) 2011, 2012, 2013, 2014 The Regents of the University of + Copyright (c) 2011 - 2016 The Regents of the University of California (Regents). All Rights Reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: @@ -29,73 +29,107 @@ */ package Chisel -import Node._ -import Reg._ -import ChiselError._ -import scala.collection.mutable.ArrayBuffer -import scala.collection.mutable.{Queue=>ScalaQueue} -import scala.collection.mutable.Stack -import scala.collection.mutable.{HashSet, HashMap, LinkedHashMap} -import java.lang.reflect.Modifier._ -import java.io.File -import java.io.InputStream -import java.io.OutputStream -import java.io.PrintStream - -object Backend { - var moduleNamePrefix = "" -} +import scala.collection.mutable.{ArrayBuffer, HashSet, HashMap, LinkedHashMap, Stack, Queue=>ScalaQueue} +import sys.process.stringSeqToProcess trait FileSystemUtilities { /** Ensures a directory *dir* exists on the filesystem. */ - def ensureDir(dir: String): String = { - val d = dir + (if (dir == "" || dir(dir.length-1) == '/') "" else "/") - new File(d).mkdirs() - d + def ensureDir(dir: String) = { + val file = new java.io.File(dir) + if (!file.exists) file.mkdirs + dir } - def createOutputFile(name: String): java.io.FileWriter = { + def createOutputFile(name: String) = { val baseDir = ensureDir(Driver.targetDir) - new java.io.FileWriter(baseDir + name) + new java.io.FileWriter(s"${baseDir}/${name}") + } + + def copyToTarget(filename: String) = { + val resourceStream = getClass().getResourceAsStream(s"/${filename}") + if( resourceStream != null ) { + val classFile = createOutputFile(filename) + while(resourceStream.available > 0) { + classFile.write(resourceStream.read()) + } + classFile.close() + resourceStream.close() + } else { + println(s"WARNING: Unable to copy '$filename'" ) + } + } + + import scala.util.Properties.envOrElse + protected val CC = envOrElse("CC", "g++" ) + protected val CXX = envOrElse("CXX", "g++" ) + protected val CCFLAGS = envOrElse("CCFLAGS", "") + protected val CXXFLAGS = envOrElse("CXXFLAGS", "") + protected val CPPFLAGS = envOrElse("CPPFLAGS", "") + protected val LDFLAGS = envOrElse("LDFLAGS", "") + protected val chiselENV = envOrElse("CHISEL", "") + + def run(cmd: String) = { + val bashCmd = Seq("bash", "-c", cmd) + val c = bashCmd.! + ChiselError.info(cmd + " RET " + c) + c == 0 + } + + def cc(dir: String, name: String, flags: String = "", isCC: Boolean = false) { + val compiler = if (isCC) CC else CXX + val cmd = List(compiler, "-c", "-o", s"${dir}/${name}.o", flags, s"${dir}/${name}.cpp").mkString(" ") + if (!run(cmd)) throwException("failed to compile " + name + ".cpp") + } + + def link(dir: String, target: String, objects: Seq[String], isCC: Boolean = false, isLib: Boolean = false) { + val compiler = if (isCC) CC else CXX + val shared = if (isLib) "-shared" else "" + val ac = (List(compiler, LDFLAGS, shared, "-o", s"${dir}/${target}") ++ + (objects map (obj => s"${dir}/${obj}"))).mkString(" ") + if (!run(ac)) throwException("failed to link " + objects.mkString(", ")) } } -abstract class Backend extends FileSystemUtilities{ +class Backend extends FileSystemUtilities{ /* Set of keywords which cannot be used as node and component names. */ - val keywords: Set[String] + val keywords = VerilogBackend.keywords val nameSpace = HashSet[String]() /* Set of Ops that this backend doesn't natively support and thus must be lowered to simpler Ops. */ val needsLowering = Set[String]() + def topMod = Driver.topComponent getOrElse (throwException("no top component")) + /* Whether or not this backend decomposes along Module boundaries. */ def isEmittingComponents: Boolean = false - def depthString(depth: Int): String = { - var res = ""; - for (i <- 0 until depth) - res += " "; - res + private val uniqueSet = HashSet[String]() + + /** Assert that 'uniqueStr' is unique for this backend */ + private[Chisel] def assertUnique(uniqueStr : String, msg : String) { + // Multiple empty strings are allowed + if (uniqueStr != "") { + if (uniqueSet(uniqueStr)) + ChiselError.warning("[BUG] Internal error: " + msg) + else + uniqueSet += uniqueStr + } } def extractClassName(comp: Module): String = { val cname = comp.getClass().getName().replace("$", "_") val dotPos = cname.lastIndexOf('.'); - Backend.moduleNamePrefix + ( + Driver.moduleNamePrefix + ( if (dotPos >= 0) cname.substring(dotPos + 1) else cname); } - protected def genIndent(x: Int): String = { - if(x == 0) "" else " " + genIndent(x-1); - } - def sortComponents { def levelChildren(root: Module, traversal: Int) { root.level = 0 root.traversal = traversal for (child <- root.children) { - levelChildren(child, traversal+1) - root.level = math.max(root.level, child.level+1) + levelChildren(child, traversal + 1) + root.level = math.max(root.level, child.level + 1) } } @@ -107,28 +141,26 @@ abstract class Backend extends FileSystemUtilities{ result } - levelChildren(Driver.topComponent, 0) + levelChildren(topMod, 0) Driver.sortedComps.clear - Driver.sortedComps ++= gatherChildren(Driver.topComponent).sortWith( + Driver.sortedComps ++= gatherChildren(topMod).sortWith( (x, y) => (x.level < y.level || (x.level == y.level && x.traversal < y.traversal))) } - def markComponents { - Driver.components foreach (_.markComponent) - } + def markComponents { Driver.sortedComps foreach (_.markComponent) } + + def verifyComponents { Driver.sortedComps foreach (_.verify) } def verifyAllMuxes { - Driver.bfs { _ match { + Driver.bfs { case p: proc => p.verifyMuxes case _ => - } } + } } /* Returns a string derived from _name_ that can be used as a valid identifier for the targeted backend. */ - def asValidName( name: String ): String = { - if (keywords.contains(name)) name + "_" else name; - } + def asValidName( name: String ): String = if (keywords(name)) name + "_" else name def nameAll() { // Helper classes to get unique names for everything @@ -144,7 +176,8 @@ abstract class Backend extends FileSystemUtilities{ } yield new_cand).head // only use the first one } else candidate } - def reserveName(name: String): Unit = assert(name == getUniqueName(name)) + // Ignore attempts to reserve an empty ("") name - pr499, issue 459 + def reserveName(name: String): Unit = if (name != "") assert(name == getUniqueName(name), "name " + name + " cannot be reserved") def getUniqueName(candidate: String): String = { val unique_name = ensureUnique(candidate) namespace += unique_name.toLowerCase @@ -155,7 +188,7 @@ abstract class Backend extends FileSystemUtilities{ private[this] val namespaces_cache = LinkedHashMap[Module,NameSpace]() def apply(target: Module): NameSpace = namespaces_cache.getOrElseUpdate(target, new NameSpace) } - + val childrenOfParent = Driver.sortedComps.groupBy(_.parent) // Now, go through each module and assign unique names for(comp <- Driver.sortedComps) { @@ -164,18 +197,19 @@ abstract class Backend extends FileSystemUtilities{ if(comp.name.isEmpty) comp.name = extractClassName(comp) // ensure this component has a name val children = childrenOfParent.getOrElse(comp, Seq.empty) - assert(children.filter(_.name.isEmpty).isEmpty, "Chisel Internal Error: Unnamed Children") + assert(children.filter(_.name.isEmpty).isEmpty, ChiselError.error("Internal Error: Unnamed Children")) // since sortedComps, all children should have names due to check above - + // ensure all nodes in the design has SOME name - comp dfs { _ match { - case reg: Reg if reg.name == "" => + comp dfs { + case reg: Reg if reg.name.isEmpty => reg setName "R" + reg.component.nextIndex - - case node: Node if !node.isTypeNode && node.name == "" => + case mem: Mem[_] if mem.name.isEmpty => + mem setName "T" + mem.component.nextIndex + case node: Node if !node.isTypeNode && node.name.isEmpty && node.compOpt != None => node.name = "T" + node.component.nextIndex case _ => - } } + } // Now, ensure everything has a UNIQUE name // First, reserve all the IO names @@ -184,37 +218,43 @@ abstract class Backend extends FileSystemUtilities{ // Second, give module instances high priority for names children.foreach(c => c.name = namespace.getUniqueName(c.name)) // Then, check all other nodes in the design - comp dfs { _ match { + comp dfs { case reg: Reg => reg setName namespace.getUniqueName(reg.name) + case mem: Mem[_] => + mem setName namespace.getUniqueName(mem.name) case node: Node if !node.isTypeNode && !node.isLit && !node.isIo => { // the isLit check should not be necessary // the isIo check is also strange and happens because parents see child io in the DFS node.name = namespace.getUniqueName(node.name) } case _ => - } } + } + } + } + /** Ensures each node such that it has a unique name across the whole + hierarchy by prefixing its name by a component path (except for "reset" + and all nodes in *c*). */ + def renameNodes(nodes: Seq[Node], sep: String = "_") = nodes foreach { + case _: Literal => + case m if m.named => m.compOpt match { + case Some(p) if (p != topMod || m.name != "reset" || m.name != Driver.implicitReset.name) => + m.name = m.component.getPathName(sep) + sep + sep + m.name + case _ => } + case _ => } - def fullyQualifiedName( m: Node ): String = { - m match { - case l: Literal => l.toString; - case any => - if (m.name != "" - && m != Driver.topComponent.defaultResetPin && m.component != null) { - /* Only modify name if it is not the reset signal - or not in top component */ - if(m.name != "reset" && m.component != Driver.topComponent) { - m.component.getPathName + "__" + m.name; - } else { - m.name - } - } else { - m.name - } + def fullyQualifiedName( m: Node ): String = m match { + case l: Literal => l.toString; + case _ if m.name != "" && m.name != "reset" => m.compOpt match { + case Some(p) if p != topMod => + /* Only modify name if it is not the reset signal or not in top component */ + m.component.getPathName + "__" + m.name + case _ => m.name } + case _ => m.name } def emitTmp(node: Node): String = @@ -266,26 +306,26 @@ abstract class Backend extends FileSystemUtilities{ def collectNodesIntoComp(mod: Module) { Driver.sortedComps foreach (_.nodes.clear) - Driver.dfs { node => - val curComp = node match { - case io: Bits if io.isIo && io.dir == INPUT => - node.component.parent - case _ => - node.component - } - assert(node.component != null, "NULL NODE COMPONENT " + node.name) - if (!node.isTypeNode) node.component.nodes += node - for (input <- node.inputs ; if !input.isTypeNode) { - if (!(input.component == null || input.component == node.component) && - !input.isLit && !isBitsIo(input, OUTPUT) && !isBitsIo(node, INPUT) && + Driver.dfs { node => node.compOpt match { + case None => throwException("NULL NODE COMPONENT " + node.name) + case Some(p) => + val curComp = node match { + case io: Bits if io.isIo && io.dir == INPUT => p.parent + case _ => p + } + if (!node.isTypeNode) p.nodes += node + node.inputs filterNot (_.isTypeNode) foreach (input => input.compOpt match { + case None => input.compOpt = Some(curComp) + case Some(q) => if (p != q && !input.isLit && + !isBitsIo(input, OUTPUT) && !isBitsIo(node, INPUT) && // ok if parent referring to any child nodes // not symmetric and only applies to direct children // READ BACK INPUT -- TODO: TIGHTEN THIS UP !isBitsIo(input, INPUT)) { - ChiselErrors += new ChiselError(() => { - "Illegal cross module reference between " + node + " and " + input }, node.line) - } - if (input.component == null) input.component = curComp + ChiselError.error(new ChiselError(() => { + "Illegal cross module reference between " + node + " and " + input }, node.line)) + } + }) } } } @@ -293,29 +333,28 @@ abstract class Backend extends FileSystemUtilities{ def checkModuleResolution { // check module resolution val comps = HashMap[Node, Module]() + val compSet = Driver.components.toSet Driver.dfs { node => val nextComp = node match { case io: Bits if io.isIo && io.dir == OUTPUT => io.component case io: Bits if io.isIo && io.dir == INPUT => io.component.parent case _ => comps getOrElse (node, null) } - for (input <- node.inputs ; if !(input == null)) { - input match { - case _: Literal => // Skip the below check for Literals, which can safely be static - //tmp fix, what happens if multiple componenets reference static nodes? - case _ if input.component == null || !(Driver.components contains input.component) => + node.inputs foreach { + case _: Literal => // Skip the below check for Literals, which can safely be static + //tmp fix, what happens if multiple componenets reference static nodes? + case input: Node => input.compOpt match { + case Some(p) if compSet(p) => + case _ => assert(input.component == nextComp, /* If Backend.collectNodesIntoComp does not resolve the component field for all components, we will most likely end-up here. */ - assert(input.component == nextComp, - (if (input.name != null && !input.name.isEmpty) input.name else "?") + - "[" + input.getClass.getName + "] has no match between component " + - (if (input.component == null ) "(null)" else input.component) + - " and '" + nextComp + "' input of " + - (if (node.name != null && !node.name.isEmpty) node.name else "?")) - case _ => + ChiselError.error("Internal Error: " + (if (!input.name.isEmpty) input.name else "?") + + "[" + input.getClass.getName + "] has no match between component " + + ((input.compOpt map (_.toString)) getOrElse "(null)") + + " and '" + nextComp + "' input of " + (if (!node.name.isEmpty) node.name else "?"))) } - comps(input) = nextComp } + comps ++= node.inputs map (_ -> nextComp) } } @@ -330,57 +369,52 @@ abstract class Backend extends FileSystemUtilities{ } } - def pruneUnconnectedIOs(m: Module) { - val inputs = m.wires.filter(_._2.dir == INPUT) - val outputs = m.wires.filter(_._2.dir == OUTPUT) - - for ((name, i) <- inputs) { - if (i.inputs.length == 0 && m != Driver.topComponent) - if (i.consumers.size > 0) { + def pruneUnconnectedIOs = for (m <- Driver.sortedComps) { + val (inputs, outputs) = m.wires.unzip._2 partition (_.dir == INPUT) + if (m != topMod) { + for (i <- inputs if i.inputs.isEmpty) { + if (i.consumers.isEmpty) { if (Driver.warnInputs) - ChiselError.warning({"UNCONNECTED INPUT " + emitRef(i) + " in COMPONENT " + i.component + - " has consumers"}) - i.driveRand = true + ChiselError.warning("FLOATING INPUT " + emitRef(i) + " in COMPONENT " + i.component) + i.prune = true } else { if (Driver.warnInputs) - ChiselError.warning({"FLOATING INPUT " + emitRef(i) + " in COMPONENT " + i.component}) - i.prune = true + ChiselError.warning("UNCONNECTED INPUT " + emitRef(i) + " in COMPONENT " + + i.component + " has consumers") + i.driveRand = true } + } } - - for ((name, o) <- outputs) { - if (o.inputs.length == 0 && !o.component.isInstanceOf[BlackBox]) { - if (o.consumers.size > 0) { + m match { + case _: BlackBox => + case _ => for (o <- outputs if o.inputs.isEmpty) { + if (o.consumers.isEmpty) { if (Driver.warnOutputs) - ChiselError.warning({"UNCONNECTED OUTPUT " + emitRef(o) + " in component " + o.component + - " has consumers on line " + o.consumers.head.line}) - o.driveRand = true + ChiselError.warning("FLOATING OUTPUT " + emitRef(o) + " in component " + o.component) + o.prune = true } else { if (Driver.warnOutputs) - ChiselError.warning({"FLOATING OUTPUT " + emitRef(o) + " in component " + o.component}) - o.prune = true + ChiselError.warning("UNCONNECTED OUTPUT " + emitRef(o) + " in component " + + o.component + " has consumers") + o.driveRand = true } } } } def checkPorts { - def prettyPrint(n: Node, c: Module) { - val dir = if (n.asInstanceOf[Bits].dir == INPUT) "Input" else "Output" + for { + c <- Driver.sortedComps + if c != topMod + n <- c.wires.unzip._2 + if n.inputs.isEmpty + } { val portName = n.name val compName = c.name val compInstName = c.moduleName - ChiselError.warning(dir + " port " + portName + ChiselError.warning(n.dir + " port " + portName + " is unconnected in module " + compInstName + " " + compName) } - - for (c <- Driver.components ; if c != Driver.topComponent) { - for ((n,i) <- c.wires) { - if (i.inputs.length == 0) { - prettyPrint(i, c) - } - } - } } def emitDef(node: Node): String = "" @@ -388,10 +422,10 @@ abstract class Backend extends FileSystemUtilities{ // go through every Module and set its clock and reset field def assignClockAndResetToModules { for (module <- Driver.sortedComps.reverse) { - if (module.clock == null) - module.clock = module.parent.clock + if (module._clock == None) + module._clock = module.parent._clock if (!module.hasExplicitReset) - module.reset_= + module._reset = module.parent._reset } } @@ -404,94 +438,76 @@ abstract class Backend extends FileSystemUtilities{ // component's clock's reset def addClocksAndResets { Driver.bfs { - _ match { - case x: Delay => - val clock = if (x.clock == null) x.component.clock else x.clock - val reset = - if (x.component.hasExplicitReset) x.component._reset - else if (x.clock != null) x.clock.getReset - else if (x.component.hasExplicitClock) x.component.clock.getReset - else x.component._reset - x.assignReset(x.component.addResetPin(reset)) - x.assignClock(clock) - x.component.addClock(clock) - case x: Printf => - val clock = if (x.clock == null) x.component.clock else x.clock - x.assignClock(clock) - x.component.addClock(clock) - case _ => - } + case x: Delay => + val clock = x.clock getOrElse x.component._clock.get + val reset = + if (x.clock != None) x.clock.get.getReset + else if (x.component.hasExplicitReset) x.component._reset.get + else if (x.component.hasExplicitClock) x.component._clock.get.getReset + else x.component._reset.get + x.assignReset(x.component addResetPin reset) + x.assignClock(clock) + x.component.addClock(clock) + case _ => } } def addDefaultResets { - Driver.components foreach (_.addDefaultReset) + Driver.sortedComps foreach (_.addDefaultReset) } // go through every Module, add all clocks+resets used in it's tree to it's list of clocks+resets def gatherClocksAndResets { - for (parent <- Driver.sortedComps) { - for (child <- parent.children) { - for (clock <- child.clocks) { - parent.addClock(clock) - } - for (reset <- child.resets.keys) { - // create a reset pin in parent if reset does not originate in parent and - // if reset is not an output from one of parent's children - if (reset.component != parent && !parent.children.contains(reset.component)) - parent.addResetPin(reset) - - // special case for implicit reset - if (reset == Driver.implicitReset && parent == Driver.topComponent) - if (!parent.resets.contains(reset)) - parent.resets += (reset -> reset) - } + for (parent <- Driver.sortedComps ; childSet = parent.children.toSet ; child <- parent.children) { + child.clocks foreach (parent addClock _) + for (reset <- child.resets.keys) { + // create a reset pin in parent if reset does not originate in parent and + // if reset is not an output from one of parent's children + if (reset.component != parent && !childSet(reset.component)) + parent addResetPin reset + // special case for implicit reset + if (reset == Driver.implicitReset && parent == topMod) + parent.resets getOrElseUpdate (reset, reset) } } } def connectResets { - for (parent <- Driver.sortedComps) { - for (child <- parent.children) { - for (reset <- child.resets.keys) { - if (child.resets(reset).inputs.length == 0) - if (parent.resets.contains(reset)) - child.resets(reset).inputs += parent.resets(reset) - else - child.resets(reset).inputs += reset - } - } + for { + parent <- Driver.sortedComps + child <- parent.children + reset <- child.resets.keys + pin = child.resets(reset) if pin.inputs.isEmpty + } { + pin := (parent.resets getOrElse (reset, reset)) } } def nameRsts { - for (comp <- Driver.sortedComps) { - for (rst <- comp.resets.keys) { - if (!comp.resets(rst).named) - comp.resets(rst).setName(rst.name) - } + for (comp <- Driver.sortedComps ; rst <- comp.resets.keys ; if !comp.resets(rst).named) { + comp.resets(rst) setName rst.name } } // walk forward from root register assigning consumer clk = root.clock - private def createClkDomain(root: Node, walked: HashSet[Node]) = { - val dfsStack = new Stack[Node] - walked += root; dfsStack.push(root) - val clock = root.clock + private def createClkDomain(root: Reg, walked: HashSet[Node]) = { + val dfsStack = Stack[Node]() + walked += root + dfsStack.push(root) + val clock = root.clock getOrElse (throwException(s"Reg(${root.name} in ${extractClassName(root.component)}) should have its own clock")) while(!dfsStack.isEmpty) { val node = dfsStack.pop - for (consumer <- node.consumers) { - if (!consumer.isInstanceOf[Delay] && !walked.contains(consumer)) { - val c1 = consumer.clock - val c2 = clock - if(!(consumer.clock == null || consumer.clock == clock)) { - ChiselError.warning({consumer.getClass + " " + emitRef(consumer) + " " + emitDef(consumer) + "in module" + - consumer.component + " resolves to clock domain " + - emitRef(c1) + " and " + emitRef(c2) + " traced from " + root.name}) - } else { consumer.clock = clock } - walked += consumer - dfsStack.push(consumer) + node.consumers filterNot walked foreach { + case _: Delay => + case consumer => consumer.clock match { + case Some(clk) if clk != clock => + ChiselError.warning(consumer.getClass + " " + emitRef(consumer) + " " + emitDef(consumer) + + "in module" + consumer.component + " resolves to clock domain " + + emitRef(clk) + " and " + emitRef(clock) + " traced from " + root.name) + case _ => consumer.clock = Some(clock) } + walked += consumer + dfsStack.push(consumer) } } } @@ -511,7 +527,7 @@ abstract class Backend extends FileSystemUtilities{ hasError = true } } - if (hasError) throw new Exception("Could not elaborate code due to uninferred width(s)") + if (hasError) throwException("Could not elaborate code due to uninferred width(s)") } var count = 0 @@ -525,13 +541,8 @@ abstract class Backend extends FileSystemUtilities{ if( updated ) { nbUpdates = nbUpdates + 1 } done = done && !updated } - count += 1 - - if(done){ - verify - return count; - } + if(done){ verify ; return count } } verify count @@ -546,16 +557,21 @@ abstract class Backend extends FileSystemUtilities{ Driver.idfs (_.forceMatchingWidths) } + def convertMaskedWrites(mod: Module) { + Driver.bfs { + case mem: Mem[_] => mem.convertMaskedWrites + case _ => + } + } + def computeMemPorts(mod: Module) { - if (Driver.hasMem) { - Driver.bfs { _ match { - case memacc: MemAccess => memacc.referenced = true - case _ => - } } - Driver.bfs { _ match { - case mem: Mem[_] => mem.computePorts - case _ => - } } + Driver.bfs { + case memacc: MemAccess => memacc.referenced = true + case _ => + } + Driver.bfs { + case mem: Mem[_] => mem.computePorts + case _ => } } @@ -570,10 +586,9 @@ abstract class Backend extends FileSystemUtilities{ ChiselError.error("Real node required here, but 'type' node found - did you neglect to insert a node with a direction?", x.line) } count += 1 - for (i <- 0 until x.inputs.length) - if (x.inputs(i) != null && x.inputs(i).isTypeNode) { - x.inputs(i) = x.inputs(i).getNode - } + for ((input, i) <- x.inputs.zipWithIndex if input.isTypeNode) { + x.inputs(i) = input.getNode + } } count } @@ -584,65 +599,59 @@ abstract class Backend extends FileSystemUtilities{ Driver.bfs { x => for (i <- 0 until x.inputs.length) x.inputs(i) match { case op: Op => - if (needsLowering contains op.op) + if (needsLowering(op.op)) x.inputs(i) = lowerTo.getOrElseUpdate(op, op.lower) case _ => } } - if (!lowerTo.isEmpty) - inferAll(mod) + if (!lowerTo.isEmpty) inferAll(mod) } } def addBindings { + // IMPORTANT INVARIANT FOR THIS FUNCTION + // After every graph manipulation, consumers for each node MUST be kept consistent! for (comp <- Driver.sortedComps) { - /* This code finds an output binding for a node. - We search for a binding only if the io is an output - and the logic's grandfather component is not the same - as the io's component and the logic's component is not - same as output's component unless the logic is an input */ + // For a module input or output, logic needs to be adjusted if + // the consumer is NOT in a direct submodule + // (likely as an input since as output/internal wire is illegal cross-module reference) + // AND + // consumer is either in a different module (including submodule) OR is an input + // (since, in the input case, the connection is really being done in the parent) for ((n, io) <- comp.wires) { + // OUTPUT logic is adjusted by creating a Binding node in parent + // and then having all subsequent logic use that if (io.dir == OUTPUT) { - for (node <- io.consumers; if !(node == null) && io.component != node.component.parent) { - for ((input, i) <- node.inputs.zipWithIndex ; if input eq io) { - node match { - case bits: Bits if bits.dir == INPUT => { - node.inputs(i) = Binding(io, io.component.parent, io.component) - node.inputs(i).consumers += node - } - case _ if io.component != node.component => { - node.inputs(i) = Binding(io, io.component.parent, io.component) - node.inputs(i).consumers += node - } - case _ => + // IMPORTANT: the toSet call makes an immutable copy, allows for manipulation of io.consumers + for (node <- io.consumers.toSet; if io.component != node.component.parent) { + if(node match { + case _ if io.component != node.component => true + case b: Bits if (b.dir == INPUT) && io.component == node.component => true + case _ => false + }) { + for ((input, i) <- node.inputs.zipWithIndex ; if input eq io) { + // note: after this redirection: node.inputs(i) == io + node.inputs(i).consumers -= node + node.inputs(i) = Binding(io, io.component.parent, io.component) + node.inputs(i).consumers += node } } } } - // In this case, we are trying to use the input of a submodule - // as part of the logic outside of the submodule. - // If the logic is outside the submodule, we do not use - // the input name. Instead, we use whatever is driving - // the input. In other words, we do not use the Input name, - // if the component of the logic is the part of Input's - // component. We also do the same when assigning - // to the output if the output is the parent - // of the subcomponent. + // INPUT logic is adjusted by having consumers use that input's producer else if (io.dir == INPUT && !io.inputs.isEmpty) { - for (node <- io.consumers; if !(node == null) && io.component.parent == node.component) { - for ((input, i) <- node.inputs.zipWithIndex ; if input eq io) { - node match { - case bits: Bits if bits.dir == OUTPUT => { - node.inputs(i) = io.inputs(0) - node.inputs(i).consumers -= io - node.inputs(i).consumers += node - } - case _ if !node.isIo => { - node.inputs(i) = io.inputs(0) - node.inputs(i).consumers -= io - node.inputs(i).consumers += node - } - case _ => + // IMPORTANT: the toSet call makes an immutable copy, allows for manipulation of io.consumers + for (node <- io.consumers.toSet; if io.component != node.component.parent) { + if(node match { + case _ if io.component != node.component => true + case b: Bits if (b.dir == INPUT) && io.component == node.component => true + case _ => false + }) { + for ((input, i) <- node.inputs.zipWithIndex ; if input eq io) { + // note: after this redirection: node.inputs(i) == io + node.inputs(i).consumers -= node + node.inputs(i) = io.inputs(0) + node.inputs(i).consumers += node } } } @@ -652,125 +661,104 @@ abstract class Backend extends FileSystemUtilities{ } def nameBindings { - for (comp <- Driver.sortedComps) { - for (bind <- comp.bindings) { - var genName = bind.targetComponent.name + "_" + bind.targetNode.name - if(nameSpace contains genName) genName += ("_" + bind.emitIndex) - bind.name = asValidName(genName) // Not using nameIt to avoid override - bind.named = true - } + for (comp <- Driver.sortedComps ; bind <- comp.bindings) { + var genName = bind.targetComponent.name + "_" + bind.targetNode.name + if (nameSpace(genName)) genName += ("_" + bind.emitIndex) + bind.name = asValidName(genName) // Not using nameIt to avoid override + bind.named = true } } def findCombLoop { // Tarjan's strongly connected components algorithm to find loops - var sccIndex = 0 - val stack = new Stack[Node] - val sccList = new ArrayBuffer[ArrayBuffer[Node]] - - def tarjanSCC(n: Node): Unit = { - if(n.isInstanceOf[Delay]) throw new Exception("trying to DFS on a register") - - n.sccIndex = sccIndex - n.sccLowlink = sccIndex - sccIndex += 1 - stack.push(n) - - for(i <- n.inputs) { - if(!(i == null) && !i.isInstanceOf[Delay] && !i.isReg) { - if(i.sccIndex == -1) { - tarjanSCC(i) - n.sccLowlink = math.min(n.sccLowlink, i.sccLowlink) - } else if(stack.contains(i)) { - n.sccLowlink = math.min(n.sccLowlink, i.sccIndex) - } - } - } + var index = 0 + val stack = Stack[Node]() + val onStack = HashSet[Node]() + val sccs = ArrayBuffer[List[Node]]() + + def tarjanSCC(node: Node): Unit = node match { + case _: Delay => throwException("trying to DFS on a register") + case _ => + + node.sccIndex = Some(index) + node.sccLowlink = Some(index) + index += 1 + stack.push(node) + onStack += node - if(n.sccLowlink == n.sccIndex) { - val scc = new ArrayBuffer[Node] + node.inputs foreach { + case _: Delay => + case input if input.sccIndex == None => + tarjanSCC(input) + node.sccLowlink = Some(math.min(node.sccLowlink getOrElse -1, input.sccLowlink getOrElse -1)) + case input if onStack(input) => + node.sccLowlink = Some(math.min(node.sccLowlink getOrElse -1, input.sccIndex getOrElse -1)) + case _ => + } - var top: Node = null + if (node.sccLowlink == node.sccIndex) { + val scc = ArrayBuffer[Node]() do { - top = stack.pop() - scc += top - } while (!(n == top)) - sccList += scc + scc += stack.pop + onStack -= scc.last + } while (node ne scc.last) + sccs += scc.toList } } - Driver.bfs { node => - if(node.sccIndex == -1 && !node.isInstanceOf[Delay] && !(node.isReg)) { - tarjanSCC(node) - } + Driver.bfs { + case _: Delay => + case node if node.sccIndex == None => tarjanSCC(node) + case _ => } // check for combinational loops - var containsCombPath = false - for (nodelist <- sccList) { - if(nodelist.length > 1) { - containsCombPath = true - ChiselError.error("FOUND COMBINATIONAL PATH!") - for((node, ind) <- nodelist zip nodelist.indices) { - ChiselError.error(" (" + ind + ")", node.line) - } - } - } + sccs filter (_.size > 1) foreach {scc => + ChiselError.error("FOUND COMBINATIONAL PATH!") + scc.zipWithIndex foreach { case (node, i) => + ChiselError.error(s" (${i}: ${node.component.getPathName(".")}.${node.name})", node.line) }} } /** Prints the call stack of Component as seen by the push/pop runtime. */ + protected def genIndent(x: Int): String = (for (i <- 0 until x) yield " ").mkString protected def printStack { - var res = "" - for((i, c) <- Driver.printStackStruct){ - res += (genIndent(i) + c.moduleName + " " + c.name + "\n") - } - ChiselError.info(res) + ChiselError.info(Driver.printStackStruct map { + case (i, c) => "%s%s %s\n".format(genIndent(i), c.moduleName, c.name) + } mkString "") } def flattenAll { // Reset indices for temporary nodes - Driver.components foreach (_.nindex = -1) + Driver.components foreach (_.nindex = None) // Flatten all signals - val comp = Driver.topComponent - for (c <- Driver.components ; if c != comp) { - comp.debugs ++= c.debugs - comp.nodes ++= c.nodes - } + val nodes = Driver.components flatMap (_.nodes) + val debugs = Driver.components flatMap (_.debugs) // Find roots - val roots = ArrayBuffer[Node]() - for (c <- Driver.components) - roots ++= c.debugs - for ((n, io) <- comp.wires) - roots += io - for (b <- Driver.blackboxes) - roots += b.io - for (node <- comp.nodes) { - node match { - case io: Bits if io.dir == OUTPUT && io.consumers.isEmpty => - roots += node - case _: Delay => - roots += node - case _ => - } } + val roots = debugs ++ + (topMod.wires map (_._2)) ++ + (Driver.blackboxes map (_.io)) ++ + (nodes filter { + case io: Bits => io.dir == OUTPUT && io.consumers.isEmpty + case _: Delay => true + case _ => false + }) // visit nodes and find ordering - val stack = Stack[(Int, Node)]() + val stack = Stack[(Node, Option[Int])]((roots.reverse map ((_, Some(0)))):_*) val walked = HashSet[Node]() - for (root <- roots) stack push ((0, root)) while (!stack.isEmpty) { - val (depth, node) = stack.pop - if (depth == -1) Driver.orderedNodes += node - else { - node.depth = math.max(node.depth, depth) - if (!(walked contains node)) { - walked += node - stack push ((-1, node)) - for (i <- node.inputs; if !(i == null)) { - i match { + stack.pop match { + case (node, None) => Driver.orderedNodes += node + case (node, Some(depth)) => { + node.depth = math.max(node.depth, depth) + if (!walked(node)) { + walked += node + stack push ((node, None)) + node.inputs foreach { case _: Delay => - case _ => stack push ((depth + 1, i)) + case i => stack push ((i, Some(depth + 1))) } } } @@ -821,7 +809,7 @@ abstract class Backend extends FileSystemUtilities{ /* Construct the depth-first list of nodes, set them all to unmodified, * and construct their parent list. */ - Driver.idfs { n => { n.modified = false; nodesList += n ; n.inputs.foreach(_.parents += n)} } + Driver.idfs { n => { n.modified = false; nodesList += n ; n.inputs.foreach(_.consumers += n)} } for ( n <- nodesList) { // If this node has any zero-width children, have it deal with them. if (n.inputs exists { c => c.inferWidth(c).needWidth == 0 }) { @@ -835,9 +823,17 @@ abstract class Backend extends FileSystemUtilities{ } def elaborate(c: Module): Unit = { - ChiselError.info("// COMPILING " + c + "(" + c.children.length + ")"); - markComponents + ChiselError.checkpoint() + ChiselError.info("// COMPILING " + c + "(" + c.children.size + ")"); sortComponents + markComponents + + verifyComponents + ChiselError.checkpoint() + + // Ensure all conditional assignments have defauts. + verifyAllMuxes + ChiselError.checkpoint() ChiselError.info("giving names") nameAll @@ -847,6 +843,9 @@ abstract class Backend extends FileSystemUtilities{ execute(c, transforms) ChiselError.checkpoint() + ChiselError.info("convert masked writes of inline mems") + convertMaskedWrites(c) + ChiselError.info("adding clocks and resets") assignClockAndResetToModules addClocksAndResets @@ -857,11 +856,15 @@ abstract class Backend extends FileSystemUtilities{ ChiselError.info("inferring widths") inferAll(c) if (Driver.isSupportW0W) { - ChiselError.info("eliminating W0W") + ChiselError.info("eliminating W0W (pre width check)") W0Wtransform } ChiselError.info("checking widths") forceMatchingWidths + if (Driver.isSupportW0W) { + ChiselError.info("eliminating W0W (post width check)") + W0Wtransform + } ChiselError.info("lowering complex nodes to primitives") lowerNodes(c) ChiselError.info("removing type nodes") @@ -895,17 +898,16 @@ abstract class Backend extends FileSystemUtilities{ nameRsts ChiselError.info("creating clock domains") - val clkDomainWalkedNodes = new HashSet[Node] - for (comp <- Driver.sortedComps) - for (node <- comp.nodes) - if (node.isInstanceOf[Reg]) - createClkDomain(node, clkDomainWalkedNodes) + val clkDomainWalkedNodes = HashSet[Node]() + for (comp <- Driver.sortedComps ; node <- comp.nodes) { + node match { + case r: Reg => createClkDomain(r, clkDomainWalkedNodes) + case _ => + } + } ChiselError.info("pruning unconnected IOs") - for (comp <- Driver.sortedComps) { - // remove unconnected outputs - pruneUnconnectedIOs(comp) - } + pruneUnconnectedIOs if (Driver.isCheckingPorts) { ChiselError.info("checking for unconnected ports") @@ -925,10 +927,17 @@ abstract class Backend extends FileSystemUtilities{ printStack } + if (ChiselError.hasChecks) { + ChiselError.error("COMPATIBILITY ERRORS") + } + ChiselError.checkpoint() + + // generate chisel names + Driver.dfs { _.chiselName } execute(c, analyses) } - def compile(c: Module, flags: String = null): Unit = { } + def compile(c: Module, flags: Option[String] = None): Unit = { } // Allow the backend to decide if this node should be recorded in the "object". def isInObject(n: Node): Boolean = false diff --git a/src/main/scala/Binding.scala b/src/main/scala/Binding.scala index 5980b601..806924dc 100644 --- a/src/main/scala/Binding.scala +++ b/src/main/scala/Binding.scala @@ -1,5 +1,5 @@ /* - Copyright (c) 2011, 2012, 2013, 2014 The Regents of the University of + Copyright (c) 2011 - 2016 The Regents of the University of California (Regents). All Rights Reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: @@ -29,7 +29,6 @@ */ package Chisel -import Node._ // used for component to component connections object Binding { @@ -39,8 +38,8 @@ object Binding { case Some(res) => res case None => { val res = new Binding(m, ioComp) - res.component = c - res.init("", widthOf(0), m) + res.compOpt = Some(c) + res.init("", Node.widthOf(0), m) res.infer c.nodes += res c.bindings += res @@ -52,5 +51,5 @@ object Binding { class Binding(val targetNode: Node, val targetComponent: Module) extends Node { - override def toString: String = "BINDING(" + inputs(0) + ")"; + override def toString: String = "BINDING(" + inputs(0) + ", of " + component + ", called " + name + ")"; } diff --git a/src/main/scala/BitPat.scala b/src/main/scala/BitPat.scala new file mode 100644 index 00000000..f914771e --- /dev/null +++ b/src/main/scala/BitPat.scala @@ -0,0 +1,72 @@ +/* + Copyright (c) 2011 - 2016 The Regents of the University of + California (Regents). All Rights Reserved. Redistribution and use in + source and binary forms, with or without modification, are permitted + provided that the following conditions are met: + + * Redistributions of source code must retain the above + copyright notice, this list of conditions and the following + two paragraphs of disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + two paragraphs of disclaimer in the documentation and/or other materials + provided with the distribution. + * Neither the name of the Regents nor the names of its contributors + may be used to endorse or promote products derived from this + software without specific prior written permission. + + IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, + SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, + ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF + REGENTS HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF + ANY, PROVIDED HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION + TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR + MODIFICATIONS. +*/ + +package Chisel +import Literal._ + +/** A bit pattern object to enable representation of dont cares */ +object BitPat { + /** Get a bit pattern from a string + * @param n a string with format b---- eg) b1?01 + * @note legal characters are 0, 1, ? and must be base 2*/ + def apply(n: String): BitPat = { + require(n(0) == 'b', "BINARY BitPats ONLY") + val (bits, mask, swidth) = parseLit(n.substring(1)) + new BitPat(toLitVal(bits, 2), toLitVal(mask, 2), swidth) + } + + /** Get a bit pattern of don't cares with a specified width */ + def DC(width: Int): BitPat = BitPat("b" + ("?" * width)) + + // BitPat <-> UInt + /** enable conversion of a bit pattern to a UInt */ + implicit def BitPatToUInt(x: BitPat): UInt = { + require(x.mask == (BigInt(1) << x.getWidth)-1) + UInt(x.value, x.getWidth) + } + /** create a bit pattern from a UInt */ + implicit def apply(x: UInt): BitPat = { + require(x.isLit) + BitPat("b" + x.litValue().toString(2)) + } +} + +/** A class to create bit patterns + * Use the [[Chisel.BitPat$ BitPat]] object instead of this class directly */ +class BitPat(val value: BigInt, val mask: BigInt, width: Int) { + def getWidth: Int = width + def === (other: Bits): Bool = UInt(value) === (other & UInt(mask)) + @deprecated("Use =/= rather than != for chisel comparison", "3") + def != (other: Bits): Bool = { + ChiselError.check("Chisel3 compatibility: != is deprecated, use =/= instead", Version("3.0")) + !(this === other) + } + def =/= (other: Bits): Bool = !(this === other) +} diff --git a/src/main/scala/Bits.scala b/src/main/scala/Bits.scala index 202bbad3..ae115351 100644 --- a/src/main/scala/Bits.scala +++ b/src/main/scala/Bits.scala @@ -1,5 +1,5 @@ /* - Copyright (c) 2011, 2012, 2013, 2014 The Regents of the University of + Copyright (c) 2011 - 2016 The Regents of the University of California (Regents). All Rights Reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: @@ -29,72 +29,74 @@ */ package Chisel -import Node._ -import ChiselError._ /* backward compatibility */ object Bits { + /** Deprecated: Do not use */ def apply(x: Int): UInt = UInt(x); + /** Deprecated: Do not use */ def apply(x: Int, width: Int): UInt = UInt(x, width); + /** Deprecated: Do not use */ def apply(x: BigInt): UInt = UInt(x); + /** Deprecated: Do not use */ def apply(x: BigInt, width: Int): UInt = UInt(x, width); + /** Deprecated: Do not use */ def apply(x: String): UInt = UInt(x); + /** Deprecated: Do not use */ def apply(x: String, width: Int): UInt = UInt(x, width); - - def apply(dir: IODirection = null, width: Int = -1): UInt = UInt(dir, width); - + /** Deprecated: Do not use */ + def apply(dir: IODirection = NODIR, width: Int = -1): UInt = UInt(dir, width); + /** Deprecated: Do not use */ def DC(width: Int): UInt = UInt.DC(width) } /** Base class for built-in Chisel types Bits and SInt. */ abstract class Bits extends Data with proc { - var dir: IODirection = null; + // TODO: make private or protected? + var dir: IODirection = NODIR def create(dir: IODirection, width: Int) { - this.dir = dir; + this.dir = dir if(width > -1) { - this.init("", width); + init("", width) } else { - this.init("", widthOf(0)) + init("", Node.widthOf(0)) } } /** assigns this instance as the data type for *node*. */ protected[Chisel] final def asTypeFor(node: Node): this.type = { - this assign node - this.setIsTypeNode - if(!node.isInstanceOf[Literal]) node.nameHolder = this - this + this assign node ; setIsTypeNode ; this } - def fromInt(x: Int): this.type; - - def toSInt(): SInt = chiselCast(this){SInt()}; - - def toUInt(): UInt = chiselCast(this){UInt()}; - + def fromInt(x: Int): this.type override def getNode: Node = if (procAssigned) this else super.getNode // internal, non user exposed connectors private var assigned = false private def checkAssign(src: Node) = { - if (this.dir == INPUT && this.component == Module.current && - this.component.wires.unzip._2.contains(this)) { - ChiselError.error({"assigning to your own input port " + this + " RHS: " + src}); - } - if (this.dir == OUTPUT && this.component != Module.current && - src.component != null && src.component.parent != this.component) { - ChiselError.error({"assigning to a non parent module's output port: " + this + " RHS: " + src}); + dir match { + case INPUT if component == Module.current && (component.wires.unzip._2 contains this) => + ChiselError.error("assigning to your own input port " + this + " RHS: " + src) + case OUTPUT if component != Module.current => src.compOpt match { + case Some(p) if p.parent != component => + ChiselError.error("assigning to a non parent module's output port: " + this + " RHS: " + src) + case _ => + } + case _ if assigned => + ChiselError.error("reassignment to Wire " + this + " with inputs " + inputs(0) + " RHS: " + src) + case _ => } - if (assigned) - ChiselError.error({"reassignment to Wire " + this + " with inputs " + this.inputs(0) + " RHS: " + src}) !assigned } override def assign(src: Node): Unit = { - if (Driver.topComponent != null || checkAssign(src)) { + if (Driver.topComponent != None || checkAssign(src)) { + if (procAssigned) + ChiselError.check("Chisel3 compatibility: Bulk-connection to a node that has been procedurally assigned-to is deprecated.", Version("3.0")) + assigned = true if (!procAssigned) inputs += src else if (defaultMissing) setDefault(src) @@ -102,7 +104,13 @@ abstract class Bits extends Data with proc { } override def procAssign(src: Node): Unit = { - if (Driver.topComponent != null || checkAssign(src)) { + if (assigned) { + // override any previous bulk connection + assigned = false + inputs.clear + } + + if (Driver.topComponent != None || checkAssign(src)) { if (defaultMissing && Module.current.whenCond.canBeUsedAsDefault) setDefault(src) else @@ -110,6 +118,7 @@ abstract class Bits extends Data with proc { } } + // TODO: make protected or private? override def defaultRequired: Boolean = true //code generation stuff @@ -124,177 +133,163 @@ abstract class Bits extends Data with proc { // width_ but it seems to also have some underlying computations associated // to it. var str = ( - "/*" + (if (name != null && !name.isEmpty) name else "?") - + (if (component != null) (" in " + component) else "") + "*/ " - + getClass.getName + "(" - + (if (dir == INPUT) "INPUT, " - else if (dir == OUTPUT) "OUTPUT, " else "") - + "width=" + width_ + "/*" + (if (name != "") name else "?") + + ((compOpt map (" in " + _.toString)) getOrElse "?") + "*/ " + + getClass.getName + "(" + dir + ", " + "width=" + width_ + ", connect to " + inputs.length + " inputs: (") var sep = "" for( i <- inputs ) { - str = (str + sep + (if (i.name != null) i.name else "?") + str = (str + sep + (if (i.name != "") i.name else "?") + "[" + i.getClass.getName + "]" - + " in " + (if (i.component != null) i.component.getClass.getName else "?")) + + " in " + ((i.compOpt map (_.getClass.getName) getOrElse "?"))) sep = ", " } str = str + "))" str } - override def flip(): this.type = { - assert(dir != null, - ChiselError.error("Can't flip something that doesn't have a direction")) - if (dir == INPUT) { - dir = OUTPUT - } else if(dir == OUTPUT) { - dir = INPUT + /** Change INPUT to OUTPUT and OUTPUT to INPUT */ + override def flip: this.type = { + dir match { + case INPUT => dir = OUTPUT + case OUTPUT => dir = INPUT + case NODIR => throwException("Can't flip something that doesn't have a direction") } this } - override def asDirectionless(): this.type = { - dir = null - this - } - - override def asInput(): this.type = { - dir = INPUT - this - } - - override def asOutput(): this.type = { - dir = OUTPUT - this - } - - override def isDirectionless: Boolean = { - return dir == null - } - + /** Set this Bits instantiation to be neither of INPUT or OUTPUT */ + override def asDirectionless: this.type = { dir = NODIR ; this } + /** Set this Bits instatiation to be an INPUT */ + override def asInput: this.type = { dir = INPUT ; this } + /** Set this Bits instatiation to be an OUTPUT */ + override def asOutput: this.type = { dir = OUTPUT ; this } + /** @return this instantiation is neither of INPUT or OUTPUT */ + override def isDirectionless: Boolean = { dir == NODIR } + + /** Connect I/O of modules with the same name + * @param src Node to attempt to connect to this instantiation + */ override def <>(src: Node) { - if (dir == INPUT) { - src match { - case other: Bits => - if (other.dir == OUTPUT) { // input - output connections - if(this.component == other.component && !isTypeNode) {//passthrough - other assign this - } else if (this.component.parent == other.component.parent || isTypeNode) { //producer - consumer - if (!other.inputs.isEmpty || other.component.isInstanceOf[BlackBox]) { // includes when a child is a blackbox - this assign other // only do assignment if output has stuff connected to it - } - } else { - ChiselError.error({"Undefined connections between " + this + " and " + other}) - } - } else if (other.dir == INPUT) { // input <> input conections - if(this.component == other.component.parent) { // parent <> child - other assign this - } else if(this.component.parent == other.component) { //child <> parent - this assign other - } else { - ChiselError.error({"Can't connect Input " + this + " Input " + other}) - } - } else { // io <> wire - if(this.component == other.component) { //internal wire - other assign this - } else if(this.component.parent == other.component) { //external wire - this assign other - } else { - ChiselError.error({"Connecting Input " + this + " to " + other}) - } + checkCompatibility(src) + val p = component + val q = src.component + src match { + case other: Bits => (dir, other.dir) match { + // input <> output connections + case (INPUT, OUTPUT) if p == q && !isTypeNode => other assign this //passthrough + case (INPUT, OUTPUT) if p.parent == q.parent || isTypeNode => q match { //producer - consumer + // includes when a child is a blackbox + case _: BlackBox => this assign other + // only do assignment if output has stuff connected to it + case _ if !other.inputs.isEmpty => this assign other + case _ => } - case default => - ChiselError.error({"Connecting Input " + this + " to IO without direction " + default}) - } - } else if (dir == OUTPUT) { - src match { - case other: Bits => - if (other.dir == INPUT) { // input - output connections - if (this.component == other.component && !isTypeNode) { //passthrough - this assign other; - } else if (this.component.parent == other.component.parent || isTypeNode) { //producer - consumer - if (!this.inputs.isEmpty || this.component.isInstanceOf[BlackBox]) { // includes when a child is a black box - other assign this; // only do connection if I have stuff connected to me - } - } else { - ChiselError.error({"Undefined connection between " + this + " and " + other}) - } - } else if (other.dir == OUTPUT) { // output <> output connections - if(this.component == other.component.parent) { // parent <> child - if (!other.inputs.isEmpty || other.component.isInstanceOf[BlackBox]) { // includes when a child is a black box - this assign other // only do connection if child is assigning to that output - } - } else if (this.component.parent == other.component) { // child <> parent - if (!this.inputs.isEmpty || this.component.isInstanceOf[BlackBox]) { // includes when a child is a black box - other assign this // only do connection if child (me) is assinging that output - } - } else if (this.isTypeNode && other.isTypeNode) { //connecting two type nodes together - ChiselError.error("Ambiguous Connection of Two Nodes") - } else if (this.isTypeNode){ // type <> output - other assign this; - } else if (other.isTypeNode){ // output <> type - this assign other; - } else { - ChiselError.error({"Connecting Output " + this + " to Output " + other}) - } - } else { // io <> wire - if(this.component == other.component) { //output <> wire - this assign other - } else if(this.component.parent == other.component) { - ChiselError.error({"Connecting Ouptut " + this + " to an external wire " + other}) - } else { - ChiselError.error({"Connecting Output " + this + " to IO without direction " + other}) - } - } - case default => - ChiselError.error({"Connecting Output " + this + " to an IO withouth direction " + default}) + case (INPUT, OUTPUT) => + ChiselError.error("Undefined connections between " + this + " and " + other) + + // output <> input connections + case (OUTPUT, INPUT) if p == q && !isTypeNode => this assign other //passthrough + case (OUTPUT, INPUT) if p.parent == q.parent || isTypeNode => q match { //producer - consumer + // includes when a child is a black box + case _: BlackBox => other assign this + // only do connection if I have stuff connected to me + case _ if !inputs.isEmpty => other assign this + case _ => + } + case (OUTPUT, INPUT) => + ChiselError.error("Undefined connection between " + this + " and " + other) + + // input <> input conections + case (INPUT, INPUT) if p == q.parent => other assign this // parent <> child + case (INPUT, INPUT) if p.parent == q => this assign other //child <> parent + case (INPUT, INPUT) => + ChiselError.error("Can't connect Input " + this + " Input " + other) + + // output <> output connections + case (OUTPUT, OUTPUT) if p == q.parent => q match { // parent <> child + // includes when a child is a black box + case _: BlackBox => this assign other + // only do connection if child is assigning to that output + case _ if !other.inputs.isEmpty => this assign other + case _ => + } + case (OUTPUT, OUTPUT) if p.parent == q => p match { // child <> parent + // includes when a child is a black box + case _: BlackBox => other assign this + // only do connection if child (me) is assinging that output + case _ if !inputs.isEmpty => other assign this + case _ => + } + case (OUTPUT, OUTPUT) if isTypeNode && other.isTypeNode => //connecting two type nodes together + ChiselError.error("Ambiguous Connection of Two Nodes") + case (OUTPUT, OUTPUT) if isTypeNode => other assign this // type <> output + case (OUTPUT, OUTPUT) if other.isTypeNode => this assign other // output <> type + case (OUTPUT, OUTPUT) => + ChiselError.error("Connecting Output " + this + " to Output " + other) + + // input <> wire + case (INPUT, NODIR) if p == q => other assign this //internal wire + case (INPUT, NODIR) if p.parent == q => this assign other //external wire + case (INPUT, NODIR) => + ChiselError.error("Connecting Input " + this + " to " + other) + + // wire <> input + case (NODIR, INPUT) if p == q => this assign other + case (NODIR, INPUT) if p == q.parent => other assign this + case (NODIR, INPUT) => + ChiselError.error("Undefined connection between wire " + this + " and input " + other) + + // io <> wire + case (OUTPUT, NODIR) if p == q => this assign other + case (OUTPUT, NODIR) if p.parent == q => + ChiselError.error("Connecting Ouptut " + this + " to an external wire " + other) + case (OUTPUT, NODIR) => + ChiselError.error("Connecting Output " + this + " to IO without direction " + other) + + // wire <> output + case (NODIR, OUTPUT) if p == q => other assign this // internal wire + case (NODIR, OUTPUT) if p == q.parent => this assign other // external wire + case (NODIR, OUTPUT) => + ChiselError.error("Undefined connection between wire " + this + " and output " + other) + + // wire <> wire + case (NODIR, NODIR) => this assign other + + case _ => // shouldn't reach here } - } - else { - src match { - case other: Bits => - if (other.dir == INPUT) { // wire <> input - if(this.component == other.component) { - this assign other - } else if(this.component == other.component.parent) { - other assign this - } else { - ChiselError.error({"Undefined connection between wire " + this + " and input " + other}) - } - } else if (other.dir == OUTPUT) { //wire <> output - if(this.component == other.component) { // internal wire - other assign this - } else if(this.component == other.component.parent) { // external wire - this assign other - } else { - ChiselError.error({"Undefined connection between wire " + this + " and output " + other}) - } - } else { - this assign other - } - case default => - ChiselError.error({"Undefined connection between " + this + " and " + default}) + case _ => dir match { + case INPUT => + ChiselError.error("Connecting Input " + this + " to IO without direction " + src) + case OUTPUT => + ChiselError.error("Connecting Output " + this + " to an IO withouth direction " + src) + case NODIR => + ChiselError.error("Undefined connection between " + this + " and " + src) } } } - override def clone: this.type = { - val res = this.getClass.newInstance.asInstanceOf[this.type]; - res.inferWidth = this.inferWidth - res.width_ = this.width_.clone() - res.dir = this.dir; + /** Copy this instantiation of the Chisel Data type with all parameters such as width and I/O direction the same + */ + override def cloneType: this.type = { + val res = getClass.newInstance.asInstanceOf[this.type]; + res.inferWidth = inferWidth + res.width_ = width_.clone() + res.dir = dir; res } + /** Force the width of this nodes input to have the same width this if known + * if input node width is known force width of this node */ override def forceMatchingWidths { if(inputs.length == 1 && inputs(0).widthW != widthW) { // Our single child differs. - val w = this.widthW + val w = widthW val w0 = inputs(0).widthW if (w.isKnown) { inputs(0) = inputs(0).matchWidth(w) } else if (w0.isKnown) { - this.matchWidth(w0) + matchWidth(w0) } } } @@ -325,8 +320,9 @@ abstract class Bits extends Data with proc { } /** Assignment operator */ - override protected def colonEquals(that: Bits): Unit = { - (if (comp != null) comp else this) procAssign that + override protected def colonEquals(that: Bits) { + checkCompatibility(that) + (comp match { case None => this case Some(p) => p}) procAssign that } // bitwise operators @@ -335,40 +331,66 @@ abstract class Bits extends Data with proc { /** Extract a single Bool at index *bit*. */ final def apply(bit: Int): Bool = apply(UInt(bit)) + /** Extract a single bit at position 'bit' as a Bool */ final def apply(bit: UInt): Bool = { val res = Extract(this, bit){Bool()} - res.comp = new Insert(this, bit, 1) + res.comp = Some(new Insert(this, bit, 1)) res } - /** Extract a range of bits */ + /** Extract a range of bits, inclusive from hi to lo + * {{{ myBits = 0x5, myBits(1,0) => 0x3 }}} */ final def apply(hi: Int, lo: Int): UInt = { val res = Extract(this, hi, lo){UInt()} - res.comp = new Insert(this, UInt(lo), hi - lo + 1) + res.comp = Some(new Insert(this, UInt(lo), hi - lo + 1)) res } + /** Extract a range of bits, inclusive from hi to lo */ final def apply(hi: UInt, lo: UInt): UInt = {Extract(this, hi, lo, -1){UInt()}}; + /** Extract a range of bits, inclusive from hi to lo */ final def apply(range: (Int, Int)): UInt = this(range._1, range._2); + /** invert all bits with ~ */ def unary_~(): this.type = newUnaryOp("~"); + /** reduction and, and all bits together */ def andR(): Bool = newLogicalOp(SInt(-1), "===") - def orR(): Bool = newLogicalOp(UInt(0), "!=") + /** reduction or, or all bits together */ + def orR(): Bool = newLogicalOp(UInt(0), "=/=") + /** reduction xor, xor all bits together */ def xorR(): Bool = newReductionOp("^"); - def != (b: Bits): Bool = newLogicalOp(b, "!="); + @deprecated("Use =/= rather than != for chisel comparison", "3") + def != (b: Bits): Bool = { + ChiselError.check("Chisel3 compatibility: != is deprecated, use =/= instead", Version("3.0")) + newLogicalOp(b, "=/="); + } + /** not equal to */ + def =/= (b: Bits): Bool = newLogicalOp(b, "!="); + /** Bitwise and */ def & (b: Bits): this.type = newBinaryOp(b, "&"); + /** Bitwise or */ def | (b: Bits): this.type = newBinaryOp(b, "|"); + /** Bitwise xor */ def ^ (b: Bits): this.type = newBinaryOp(b, "^"); + /** Shift left operation */ def <<(b: UInt): this.type = newBinaryOp(b, "<<") + /** Set bit 'off' in data dat + * @param off which bit to set + * @param dat A UInt in which to set the bit + */ def bitSet(off: UInt, dat: UInt): this.type = { val bit = UInt(1, 1) << off this & ~bit | dat.toSInt & bit } + /** Split up this bits instantiation to a Vec of Bools */ def toBools: Vec[Bool] = Vec.tabulate(this.getWidth)(i => this(i)) + /** Error shown when operation is not defined + * @throws ChiselException if the operation is not defined + */ def error(b: Bits): Bits = { - throw new Exception("+ not defined on " + this.getClass + " and " + b.getClass) + throwException("+ not defined on " + this.getClass + " and " + b.getClass) this } @@ -476,6 +498,15 @@ abstract class Bits extends Data with proc { } } + def === (that: BitPat): Bool = that === this + @deprecated("Use =/= rather than != for chisel comparison", "3") + def != (that: BitPat): Bool = { + ChiselError.check("Chisel3 compatibility: != is deprecated, use =/= instead.", Version("3.0")) + that =/= this + } + def =/= (that: BitPat): Bool = that =/= this + + /** Cat bits together to into a single data object with the width of both combined */ override def ##[T <: Data](right: T): this.type = { right match { case b: Bits => newBinaryOp(b, "##"); @@ -483,17 +514,36 @@ abstract class Bits extends Data with proc { (this.asInstanceOf[Data] ## right).asInstanceOf[this.type]; } } + + // Chisel3 - Check version compatibility (assignments requiring Wire() wrappers) + private def checkCompatibility(src: Node) { + if (Driver.minimumCompatibility > "2") { + // Verify assignment type legality. + val mismatch = (src, this) match { + case (s: SInt, u: UInt) => true + case (u: UInt, s: SInt) => true + case _ => false + } + if (mismatch) { + ChiselError.check("Chisel3 compatibility: Connections between UInt and SInt are illegal.", Version("3.0")) + } + component addAssignment this + } + } } object andR { + /** reduction and, and all bits together */ def apply(x: Bits): Bool = x.andR } object orR { + /** reduction or, or all bits together */ def apply(x: Bits): Bool = x.orR } object xorR { + /** reduction xor, xor all bits together */ def apply(x: Bits): Bool = x.xorR } diff --git a/src/main/scala/BlackBox.scala b/src/main/scala/BlackBox.scala new file mode 100644 index 00000000..34fc100a --- /dev/null +++ b/src/main/scala/BlackBox.scala @@ -0,0 +1,130 @@ +/* + Copyright (c) 2011 - 2016 The Regents of the University of + California (Regents). All Rights Reserved. Redistribution and use in + source and binary forms, with or without modification, are permitted + provided that the following conditions are met: + + * Redistributions of source code must retain the above + copyright notice, this list of conditions and the following + two paragraphs of disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + two paragraphs of disclaimer in the documentation and/or other materials + provided with the distribution. + * Neither the name of the Regents nor the names of its contributors + may be used to endorse or promote products derived from this + software without specific prior written permission. + + IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, + SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, + ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF + REGENTS HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF + ANY, PROVIDED HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION + TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR + MODIFICATIONS. +*/ + +package Chisel + +import scala.collection.mutable.{ArrayBuffer, HashMap} + +/** This class enables the definition of verilog parameters without having to to string building + * @example + * {{{ class MyParams extends VerilogParameters { + * val MY_STR_PARAM = "FOO_BAR" + * val MY_INT_PARAM = 3 + * val MY_BOOL_PARAM = true + * } }}} + * This will generate a string + * {{{ #( + * .MY_STR_PARAM("FOO_BAR"), + * .MY_INT_PARAM(3), + * .MY_BOOL_PARAM(1) + * ) }}} + * Set these parameters with + * {{{ setVerilogParameters(new MyParams) }}} + * inside a [[Chisel.BlackBox BlackBox]] module + * or use {{{ setVerilogParameters(myCustomString) }}} + */ +class VerilogParameters { + /** Get the string of verilog parameters */ + override def toString() : String = { + val myFields = this.getClass().getDeclaredFields() + val paramStr = new ArrayBuffer[String] + paramStr += "# (" + for ( field <- myFields ) { + field.setAccessible(true) + val fieldName = field.toString().split(" ").last.split('.').last + val fieldVal = field.get(this) + val fieldStr = { + if (fieldVal.isInstanceOf[Boolean]) { + if ( fieldVal.asInstanceOf[Boolean] ) "1" else "0" + } else if (fieldVal.isInstanceOf[String]) + "\"" + fieldVal + "\"" + else + fieldVal + } + val verilogStr = " ." + fieldName + "(" + fieldStr + ")" + if ( myFields.last == field ) + paramStr += verilogStr + else + paramStr += verilogStr + "," + } + paramStr += " )" + paramStr.mkString("\n") + } +} + +/** This class allows the connection to Verilog modules outside of chisel after generation + * @example + * {{{ class DSP48E1 extends BlackBox { + * val io = new [[Chisel.Bundle Bundle]] // Create I/O with same as DSP + * val dspParams = new [[Chisel.VerilogParameters VerilogParameters]] // Create Parameters to be specified + * setVerilogParams(dspParams) + * renameClock("clk", "clock") + * renameReset("rst") + * // Implement functionality of DSP to allow simulation verification + * } }}} + */ +abstract class BlackBox extends Module { + Driver.blackboxes += this + private val clockMapping = new HashMap[String, String] + + /** Set the verilog parameters to be this string + * @param string this string must start with "#(" and end with ")" to generate valid verilog */ + def setVerilogParameters(string: String) { + this.asInstanceOf[Module].verilog_parameters = string; + } + + /** Set the verilog parameters directly from a class [[Chisel.VerilogParameters VerilogParameters]] + * @param params a object where all vals defined in the class are interpreted as verilog parameters */ + def setVerilogParameters(params: VerilogParameters) { + this.asInstanceOf[Module].verilog_parameters = params.toString + } + + /** Rename any clock with the output name of "clkName" to "outName" + * @note Only defined for this black box module, to generally rename the clock see [[Chisel.Clock Clock]] */ + def renameClock(clkName: String, outName: String) { + clockMapping.put(clkName, outName) + } + + /** Rename a clk instance to have the output name of "outName" + * @note This maps from the current clk.name */ + def renameClock(clkIn: Clock, outName: String) { + renameClock(clkIn.name, outName) + } + + /** Get the output name of a clock string */ + def mapClock(clkName: String) : String = { + clockMapping.getOrElse(clkName, clkName) + } + + /** This method renames the implicit reset for this module */ + def renameReset(name: String) { + this.reset.setName(name) + } +} diff --git a/src/main/scala/Bool.scala b/src/main/scala/Bool.scala index 557e8ded..e6963ef7 100644 --- a/src/main/scala/Bool.scala +++ b/src/main/scala/Bool.scala @@ -1,5 +1,5 @@ /* - Copyright (c) 2011, 2012, 2013, 2014 The Regents of the University of + Copyright (c) 2011 - 2016 The Regents of the University of California (Regents). All Rights Reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: @@ -33,15 +33,20 @@ package Chisel object Bool { def apply(x: Boolean): Bool = Lit(if(x) 1 else 0, 1){Bool()} - def apply(dir: IODirection = null): Bool = { - val res = new Bool(); - res.dir = dir; + def apply(dir: IODirection = NODIR): Bool = { + val res = new Bool() + res.dir = dir res.init("", 1) res } - /** Factory method to create a don't-care. */ - def DC = Lit("b?", 1){Bool()} + def apply(x: Node): Bool = Bool().fromNode(x) + + /** Factory method to create a don't-care. + * FIXME: This should remain a BitPat(), not a Bool(). + * We don't want to give the impression that BitPat()'s can be used in arbitrary expressions. + */ + def DC = Bool().fromNode(Bits.DC(1)) } class Bool extends UInt { @@ -53,29 +58,33 @@ class Bool extends UInt { Bool(OUTPUT).asTypeFor(n).asInstanceOf[this.type] } + /** Create a Bool from an Int */ override def fromInt(x: Int): this.type = { Bool(x > 0).asInstanceOf[this.type] } + /** Implementation of := operator, assigns value to this Bool */ override protected def colonEquals(src: Bits): Unit = src match { case _: Bool => super.colonEquals(src(0)) case _ => { val gotWidth = src.getWidth() if (gotWidth < 1) { - throw new Exception("unable to automatically convert " + src + " to Bool, convert manually instead"); + throwException("unable to automatically convert " + src + " to Bool, convert manually instead") } else if (gotWidth > 1) { - throw new Exception("multi bit signal " + src + " converted to Bool"); + throwException("multi bit signal " + src + " converted to Bool") } super.colonEquals(src(0)) // We only have one bit in *src*. } } + /** Logical and, is equivalent to bitwise and */ def && (b: Bool): Bool = if (this.isLit) { if (isTrue) b else Bool(false) } else if (b.isLit) b && this else if (this._isComplementOf(b)) Bool(false) else newBinaryOp(b, "&") + /** Logical or, is equivalent to bitwise or */ def || (b: Bool): Bool = if (this.isLit) { if (isTrue) Bool(true) else b } else if (b.isLit) b || this diff --git a/src/main/scala/Bundle.scala b/src/main/scala/Bundle.scala index a99b11c9..47660646 100644 --- a/src/main/scala/Bundle.scala +++ b/src/main/scala/Bundle.scala @@ -1,5 +1,5 @@ /* - Copyright (c) 2011, 2012, 2013, 2014 The Regents of the University of + Copyright (c) 2011 - 2016 The Regents of the University of California (Regents). All Rights Reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: @@ -29,19 +29,13 @@ */ package Chisel -import scala.collection.mutable.ArrayBuffer -import scala.collection.mutable.HashSet -import scala.collection.mutable.LinkedHashMap -import scala.collection.mutable.Stack -import java.lang.reflect.Modifier._ -import Node._; -import ChiselError._ +import scala.collection.mutable.{HashSet, LinkedHashMap} object Bundle { val keywords = Set("elements", "flip", "toString", "flatten", "binding", "asInput", "asOutput", "unary_$tilde", - "unary_$bang", "unary_$minus", "clone", "toUInt", "toBits", - "toBool", "toSInt", "asDirectionless") + "unary_$bang", "unary_$minus", "clone", "cloneType", "toUInt", "toBits", + "toBool", "toSInt", "asDirectionless", "asUInt", "asSInt") def apply[T <: Bundle](b: => T)(implicit p: Parameters): T = { Driver.parStack.push(p.push) @@ -59,11 +53,11 @@ object Bundle { /** Defines a collection of datum of different types into a single coherent whole. */ -class Bundle(val view: Seq[String] = null) extends Aggregate { +class Bundle(val view: Seq[String] = Seq()) extends Aggregate { /** Populates the cache of elements declared in the Bundle. */ - private def calcElements(view: Seq[String]) = { + protected def calcElements(view : Seq[String]) = { val c = getClass - var elts = LinkedHashMap[String, Data]() + var elts = LinkedHashMap[String, Data]() val seen = HashSet[Object]() for (m <- c.getMethods.sortWith( (x, y) => (x.getName < y.getName) @@ -73,28 +67,65 @@ class Bundle(val view: Seq[String] = null) extends Aggregate { val types = m.getParameterTypes val rtype = m.getReturnType - val isInterface = classOf[Data].isAssignableFrom(rtype) + val isInterface = classOf[Data].isAssignableFrom(rtype) || classOf[Option[_]].isAssignableFrom(rtype) // TODO: SPLIT THIS OUT TO TOP LEVEL LIST - if( types.length == 0 && !isStatic(modifiers) && isInterface - && !(name contains '$') - && !(Bundle.keywords contains name) - && (view == null || (view contains name)) ) { - val obj = m invoke this - if(!(seen contains obj)) { - obj match { - case d: Data => elts(name) = d - case any => + if( types.length == 0 && !java.lang.reflect.Modifier.isStatic(modifiers) + && isInterface && !(name contains '$') && !(Bundle.keywords contains name) + && (view.isEmpty || (view contains name)) && checkPort(m, name)) { + // Fetch the actual object + m invoke this match { + case d: Data => if(!(seen contains d)) { + elts(name) = d; seen += d } - seen += obj + case Some(o) => o match { + case d: Data => { + if (elts contains name) + ChiselError.warning("Already saw " + name + " (" + d + ") in Bundle " + this) + if (!seen(d)) { + elts(name) = d; seen += d + } + } + case _ => + } + case _ => } } } + // Chisel3 - compatibility - use cloneType instead of clone + if (Driver.minimumCompatibility > "2") { + val methodNames = c.getDeclaredMethods.map(_.getName()) + if (methodNames.contains("clone") && !methodNames.contains("cloneType")) { + // Use the line number for the bunde definition (if we have it). + val errorLine = if (line != null) { + line + } else { + val stack = Thread.currentThread().getStackTrace + ChiselError.findFirstUserLine(stack) getOrElse stack(0) + } + ChiselError.check("method \"clone\" is deprecated. Please use \"cloneType\"", Version("3,0"), errline = errorLine) + } + } elts } + protected def checkPort(obj : Any, name : String) : Boolean = true + lazy val elements = calcElements(view) + /** Connect all data nodes in the map as inputs for this bundle using the names in the map */ + def fromMap(elemmap: Map[String, Data]): this.type = { + // only well defined for 'flat' bundles, for now + val result = this.cloneType + elemmap.foreach({case (subfield: String, source: Data) => { + result.elements.get(subfield) match { + case Some(sink: Data) => sink := source + case None => ChiselError.error(s"In fromMap, Map attempts to index subfield ${subfield}, which does not exist in ${result.getClass.getName}") + } + }}) + result.asInstanceOf[this.type] + } + override def toString: String = { var res = "BUNDLE(" var sep = "" @@ -106,10 +137,9 @@ class Bundle(val view: Seq[String] = null) extends Aggregate { res } + /** Name the bundle, do not use directly, use [[Chisel.Node.setName setName]] instead */ override def nameIt (path: String, isNamingIo: Boolean) { - if( !named - && (name.isEmpty - || (!path.isEmpty && name != path)) ) { + if( !named && (name.isEmpty || (!path.isEmpty && name != path)) ) { name = path val prefix = if (name.length > 0) name + "_" else "" for ((n, i) <- elements) { @@ -120,6 +150,7 @@ class Bundle(val view: Seq[String] = null) extends Aggregate { } } + /** Create a new Bundle with all the elements of both */ def +(other: Bundle): Bundle = { val res = new Bundle res.elements ++= elements @@ -127,6 +158,7 @@ class Bundle(val view: Seq[String] = null) extends Aggregate { res } + /** Change all INPUT to OUTPUT and visa versa for all elements in this Bundle */ override def flip(): this.type = { elements foreach (_._2.flip) this @@ -136,47 +168,41 @@ class Bundle(val view: Seq[String] = null) extends Aggregate { elements foreach (_._2.removeTypeNodes) } - def contains(name: String): Boolean = elements contains name + /** Check if an element exists with that name */ + def contains(name: String): Boolean = elements contains name override def apply(name: String): Data = elements(name) + /** Connect all elements contained in this to node 'src' + * @note The elements are checked for compatibility based on their name + * If elements are in src that are not in this Bundle no warning will be produced + * @example + * {{{ // pass through all wires in this modules io to the sub module which have the same name + * // Note: ignores any extra defined in io + * mySubModule.io <> io }}} + */ override def <>(src: Node): Unit = { - if (comp == null) { - src match { - case other: Bundle => { - for ((n, i) <- elements) { - if (other contains n){ - i <> other(n) - } else { - ChiselError.warning("UNABLE TO FIND " + n + " IN " + other.component) - } - } - } - case default => - ChiselError.warning("TRYING TO CONNECT BUNDLE TO NON BUNDLE " + default) - } - } else { - src match { - case other: Bundle => { - comp assign other - } - case default => - ChiselError.warning("CONNECTING INCORRECT TYPES INTO WIRE OR REG") + (comp, src) match { + case (None, other: Bundle) => for ((n, i) <- elements) { + if (other contains n) i <> other(n) + else ChiselError.warning("UNABLE TO FIND " + n + " IN " + other.component) } + case (None, _) => ChiselError.warning("TRYING TO CONNECT BUNDLE TO NON BUNDLE " + src) + case (Some(p), other: Bundle) => p assign other + case (Some(p), _) => ChiselError.warning("CONNECTING INCORRECT TYPES INTO WIRE OR REG") } } override protected def colonEquals(src: Bundle): Unit = { - if (isTypeNode && comp != null) { - comp procAssign src.toNode - } else { - for ((n, i) <- elements ; if src contains n) i := src(n) + comp match { + case Some(p) if isTypeNode => p procAssign src.toNode + case _ => for ((n, i) <- elements if src contains n) i := src(n) } } override def flatten: Array[(String, Bits)] = { - val sortedElems = elements.toArray sortWith (_._2._id < _._2._id) - (sortedElems foldLeft Array[(String, Bits)]()){(res, x) => + val sortedElems = elements.toArray sortWith (_._2._id < _._2._id) + (sortedElems foldLeft Array[(String, Bits)]()){(res, x) => val (n, i) = x res ++ (if (i.name != "") i.flatten else i match { case b: Bits => Array((n, b)) @@ -186,26 +212,11 @@ class Bundle(val view: Seq[String] = null) extends Aggregate { } override def getWidth: Int = (elements foldLeft 0)(_ + _._2.getWidth) - - override def asDirectionless(): this.type = { - elements.foreach(_._2.asDirectionless) - this - } - - override def asInput(): this.type = { - elements.foreach(_._2.asInput) - this - } - - override def asOutput(): this.type = { - elements.foreach(_._2.asOutput) - this - } - + override def asDirectionless: this.type = { elements.foreach(_._2.asDirectionless) ; this } + override def asInput: this.type = { elements.foreach(_._2.asInput) ; this } + override def asOutput: this.type = { elements.foreach(_._2.asOutput) ;this } override def isDirectionless: Boolean = elements.forall(_._2.isDirectionless) - - override def setIsTypeNode { - isTypeNode = true - elements foreach (_._2.setIsTypeNode) - } + override def setIsTypeNode { isTypeNode = true ; elements foreach (_._2.setIsTypeNode) } + // Chisel3 - type-only nodes (no data - initialization or assignment) - used for verifying Wire() wrapping + override def isTypeOnly: Boolean = { elements.forall(_._2.isTypeOnly) } } diff --git a/src/main/scala/CSE.scala b/src/main/scala/CSE.scala index 5f8a415b..abec72c8 100644 --- a/src/main/scala/CSE.scala +++ b/src/main/scala/CSE.scala @@ -1,5 +1,5 @@ /* - Copyright (c) 2011, 2012, 2013, 2014 The Regents of the University of + Copyright (c) 2011 - 2016 The Regents of the University of California (Regents). All Rights Reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: @@ -82,11 +82,7 @@ object CSE { } def inputsEqual(x: Node, y: Node): Boolean = { - if (x.widthW != y.widthW || x.inputs.length != y.inputs.length) - return false - for (i <- 0 until x.inputs.length) - if (!(x.inputs(i) == y.inputs(i))) - return false - true + if (x.widthW != y.widthW || x.inputs.length != y.inputs.length) false + else (x.inputs zip y.inputs) forall {case (a, b) => a == b} } } diff --git a/src/main/scala/Cat.scala b/src/main/scala/Cat.scala index 6e11ea16..0bae3ee3 100644 --- a/src/main/scala/Cat.scala +++ b/src/main/scala/Cat.scala @@ -1,5 +1,5 @@ /* - Copyright (c) 2011, 2012, 2013, 2014 The Regents of the University of + Copyright (c) 2011 - 2016 The Regents of the University of California (Regents). All Rights Reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: @@ -29,17 +29,34 @@ */ package Chisel -import Node._ object Cat { + /** Combine data elements together + * @param mod Data to combine with + * @param mods any number of other Data elements to be combined in order + * @return A UInt which is all of the bits combined together + */ def apply[T <: Data](mod: T, mods: T*): UInt = apply(mod :: mods.toList) + /** Combine data elements together + * @param mods any number of other Data elements to be combined in order + * @return A UInt which is all of the bits combined together + */ def apply[T <: Data](mods: Seq[T]): UInt = UInt(OUTPUT).fromNode(Concatenate(mods)) } object Concatenate { + /** Combine nodes together + * @param mod Data to combine with + * @param mods any number of other Data elements to be combined in order + * @return A Node which is all of the bits combined together + */ def apply(mod: Node, mods: Node*): Node = apply(mod :: mods.toList) - def apply(mods: Seq[Node]): Node = doCat(mods.filter(_ != null)) + /** Combine nodes together + * @param mods any number of other Data elements to be combined in order + * @return A Node which is all of the bits combined together + */ + def apply(mods: Seq[Node]): Node = doCat(mods) private def doCat(mods: Seq[Node]): Node = if (mods.tail.isEmpty) mods.head else BinaryOp(doCat(mods.slice(0, mods.length/2)), doCat(mods.slice(mods.length/2, mods.length)), "##") diff --git a/src/main/scala/ChiselError.scala b/src/main/scala/ChiselError.scala index 231a0692..82054754 100644 --- a/src/main/scala/ChiselError.scala +++ b/src/main/scala/ChiselError.scala @@ -1,5 +1,5 @@ /* - Copyright (c) 2011, 2012, 2013, 2014 The Regents of the University of + Copyright (c) 2011 - 2016 The Regents of the University of California (Regents). All Rights Reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: @@ -29,15 +29,29 @@ */ package Chisel -import scala.collection.mutable.ArrayBuffer +import scala.collection.mutable.LinkedHashSet +// Disable println warnings. It's what we do. +// scalastyle:off regex /** This Singleton implements a log4j compatible interface. It is used through out the Chisel package to report errors and warnings detected at runtime. */ object ChiselError { - var hasErrors: Boolean = false; - val ChiselErrors = new ArrayBuffer[ChiselError]; + val errorLevel = 0 + val warningLevel = 1 + val compatibilityFailureLevel = 2 + + var hasErrors: Boolean = false + private val ChiselErrors = LinkedHashSet[ChiselError]() + + def contains(chiselError: ChiselError): Boolean = ChiselErrors(chiselError) + + def isEmpty: Boolean = ChiselErrors.isEmpty + + def getErrorList: List[ChiselError] = ChiselErrors.toList + + def getCheckList: List[ChiselError] = ChiselErrors.filter(_.isCheck).toList def clear() { ChiselErrors.clear() @@ -45,9 +59,14 @@ object ChiselError { } /** emit an error message */ - def error(mf: => String, line: StackTraceElement) { + def error(chiselError: ChiselError) { hasErrors = true - ChiselErrors += new ChiselError(() => mf, line) + ChiselErrors += chiselError + } + + def error(mf: => String, line: StackTraceElement) { + val chiselError = new ChiselError(() => mf, line) + error(chiselError) } def error(m: String) { @@ -60,11 +79,33 @@ object ChiselError { def info(m: String): Unit = println(tag("info", Console.MAGENTA) + " [%2.3f] ".format(Driver.elapsedTime/1e3) + m) + def warning(m: => String, errline: StackTraceElement) { + if (Driver.wError) { + error(m, errline) + } else { + ChiselErrors += new ChiselError(() => m, errline, warningLevel) + } + } /** emit a warning message */ def warning(m: => String) { val stack = Thread.currentThread().getStackTrace - ChiselErrors += new ChiselError(() => m, - findFirstUserLine(stack) getOrElse stack(0), 1) + warning(m, findFirstUserLine(stack) getOrElse stack(0)) + } + + /** enqueue a check message */ + def check(m: => String, version: Version) { + val stack = Thread.currentThread().getStackTrace + check(m, version, findFirstUserLine(stack) getOrElse stack(0)) + } + + def check(m: => String, version: Version, errline: StackTraceElement) { + if (version <= Driver.minimumCompatibility) { + ChiselErrors += new ChiselError(() => m, errline, compatibilityFailureLevel) + } + } + + def hasChecks: Boolean = { + ChiselErrors.exists(_.isCheck) } def findFirstUserLine(stack: Array[StackTraceElement]): Option[StackTraceElement] = { @@ -90,7 +131,7 @@ object ChiselError { seenChiselMain = true } (className.subSequence(0, dotPos) != "Chisel") && !className.contains("scala") && - !className.contains("java") && !className.contains("$$") + !className.contains("java") && !className.contains("$$") && !className.startsWith("sun.") } else if (seenChiselMain) { // If we're above ChiselMain, we must be in "user" code. true @@ -104,10 +145,17 @@ object ChiselError { } val idx = stack.indexWhere(isUserCode) if(idx < 0) { - println("COULDN'T FIND LINE NUMBER (" + stack(1) + ")") + // println("COULDN'T FIND LINE NUMBER (" + stack(1) + ")") None } else { - Some(idx) + // There may be an anonymous method in this class which we skipped + // since it has "$$" in its name. If we find such a method lower + // down on the stack, return its index. + val userStackElement = stack(idx) + val userClassName = userStackElement.getClassName() + val userFileName = userStackElement.getFileName() + val lowestIdx = stack.indexWhere(ste => ste.getClassName().startsWith(userClassName) && ste.getFileName() == userFileName) + Some(lowestIdx) } } @@ -116,17 +164,13 @@ object ChiselError { val stack = Thread.currentThread().getStackTrace val idx = ChiselError.findFirstUserInd(stack) idx match { - case None => {} + case None => case Some(x) => for (i <- 0 to x) println(stack(i)) } } /** Prints error messages generated by Chisel at runtime. */ - def report() { - if (!ChiselErrors.isEmpty) { - for(err <- ChiselErrors) err.print; - } - } + def report() { getErrorList foreach (_.print) } /** Throws an exception if there has been any error recorded before this point. */ @@ -134,13 +178,18 @@ object ChiselError { if(hasErrors) { throw new IllegalStateException( Console.UNDERLINED + "CODE HAS " + - Console.UNDERLINED + Console.BOLD + ChiselErrors.filter(_.isError).length + Console.RESET + + Console.UNDERLINED + Console.BOLD + ChiselErrors.filter(_.isError).size + Console.RESET + Console.UNDERLINED + " " + Console.UNDERLINED + Console.RED + "ERRORS" + Console.RESET + Console.UNDERLINED + " and " + - Console.UNDERLINED + Console.BOLD + ChiselErrors.filter(_.isWarning).length + Console.RESET + + Console.UNDERLINED + Console.BOLD + ChiselErrors.filter(_.isWarning).size + Console.RESET + + Console.UNDERLINED + " " + + Console.UNDERLINED + Console.YELLOW + "WARNINGS" + Console.RESET + + Console.UNDERLINED + " and " + + Console.UNDERLINED + Console.BOLD + ChiselErrors.filter(_.isCheck).size + Console.RESET + Console.UNDERLINED + " " + - Console.UNDERLINED + Console.YELLOW + "WARNINGS" + Console.RESET) + Console.UNDERLINED + Console.YELLOW + "CHECKS" + Console.RESET + ) } } @@ -149,20 +198,24 @@ object ChiselError { } class ChiselError(val errmsgFun: () => String, val errline: StackTraceElement, -val errlevel: Int = 0) { +val errlevel: Int = ChiselError.errorLevel) { val level = errlevel val line = errline val msgFun = errmsgFun - def isError = (level == 0) - def isWarning = (level == 1) + def isError: Boolean = (level == ChiselError.errorLevel) + def isWarning : Boolean = (level == ChiselError.warningLevel) + def isCheck : Boolean = (level == ChiselError.compatibilityFailureLevel) def print() { /* Following conventions for error formatting */ - val levelstr = - if (isError) ChiselError.tag("error", Console.RED) - else ChiselError.tag("warn", Console.YELLOW) + val levelstr = level match { + case ChiselError.errorLevel => ChiselError.tag("error", Console.RED) + case ChiselError.warningLevel => ChiselError.tag("warn", Console.YELLOW) + case ChiselError.compatibilityFailureLevel => ChiselError.tag("check", Console.RED) + } + if( line != null ) { println(levelstr + " " + line.getFileName + ":" + line.getLineNumber + ": " + msgFun() + diff --git a/src/main/scala/ChiselUtil.scala b/src/main/scala/ChiselUtil.scala index a734aaab..f6c274e1 100644 --- a/src/main/scala/ChiselUtil.scala +++ b/src/main/scala/ChiselUtil.scala @@ -1,5 +1,5 @@ /* - Copyright (c) 2011, 2012, 2013, 2014 The Regents of the University of + Copyright (c) 2011 - 2016 The Regents of the University of California (Regents). All Rights Reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: @@ -29,39 +29,50 @@ */ package Chisel -import Node._ -import scala.math._ -import Literal._ - -object log2Up -{ - def apply(in: Int): Int = if(in == 1) 1 else ceil(log(in)/log(2)).toInt +import scala.math.{ceil, floor, log} +import scala.collection.mutable.ArrayBuffer + +/** Compute the log2 rounded up with min value of 1 */ +object log2Up { + def apply(in: BigInt): Int = { + require(in >= 0) + 1 max (in-1).bitLength + } + def apply(in: Int): Int = apply(BigInt(in)) } -object log2Ceil -{ - def apply(in: Int): Int = ceil(log(in)/log(2)).toInt +/** Compute the log2 rounded up */ +object log2Ceil { + def apply(in: BigInt): Int = { + require(in > 0) + (in-1).bitLength + } + def apply(in: Int): Int = apply(BigInt(in)) } - -object log2Down -{ - def apply(x : Int): Int = if (x == 1) 1 else floor(log(x)/log(2.0)).toInt +/** Compute the log2 rounded down with min value of 1 */ +object log2Down { + def apply(in: BigInt): Int = log2Up(in) - (if (isPow2(in)) 0 else 1) + def apply(in: Int): Int = apply(BigInt(in)) } -object log2Floor -{ - def apply(x : Int): Int = floor(log(x)/log(2.0)).toInt +/** Compute the log2 rounded down */ +object log2Floor { + def apply(in: BigInt): Int = log2Ceil(in) - (if (isPow2(in)) 0 else 1) + def apply(in: Int): Int = apply(BigInt(in)) } - -object isPow2 -{ - def apply(in: Int): Boolean = in > 0 && ((in & (in-1)) == 0) +/** Check if an Integer is a power of 2 */ +object isPow2 { + def apply(in: BigInt): Boolean = in > 0 && ((in & (in-1)) == 0) + def apply(in: Int): Boolean = apply(BigInt(in)) } +/** Fold Right with a function */ object foldR { + /** @param x a sequence of values + * @param f a function to perform the fold right with */ def apply[T <: Bits](x: Seq[T])(f: (T, T) => T): T = if (x.length == 1) x(0) else f(x(0), foldR(x.slice(1, x.length))(f)) } @@ -80,6 +91,7 @@ object LFSR16 } /** Returns the number of bits set (i.e value is 1) in the input signal. + * @example {{{ PopCount(UInt(29)) === UInt(4) }}} */ object PopCount { @@ -95,7 +107,7 @@ object PopCount def apply(in: Bits): UInt = apply((0 until in.getWidth).map(in(_))) } -/** Litte/big bit endian convertion: reverse the order of the bits in a UInt. +/** Litte/big bit endian conversion: reverse the order of the bits in a UInt. */ object Reverse { @@ -121,14 +133,19 @@ object Reverse def apply(in: UInt): UInt = doit(in, in.getWidth) } - +/** A register with an Enable signal */ object RegEnable { + /** @param updateData input data into the register + * @param enable when high or true put updateData in a register */ def apply[T <: Data](updateData: T, enable: Bool) = { val r = Reg(updateData) when (enable) { r := updateData } r } + /** @param updateData input data into the register + * @param resetData the initial or reset value for the register + * @param enable when high or true put updateData in a register */ def apply[T <: Data](updateData: T, resetData: T, enable: Bool) = { val r = RegInit(resetData) when (enable) { r := updateData } @@ -140,20 +157,53 @@ object RegEnable */ object ShiftRegister { - def apply[T <: Data](in: T, n: Int, en: Bool = Bool(true)): T = + /** @param in input to delay + * @param n number of cycles to delay */ + def apply[T <: Data](in: T, n: Int) : T = apply(in, n, Bool(true)) + /** @param in input data to delay + * @param n number of cycles to delay + * @param en enable the shift */ + def apply[T <: Data](in: T, n: Int, en: Bool) : T = { // The order of tests reflects the expected use cases. if (n == 1) { RegEnable(in, en) } else if (n != 0) { - RegNext(apply(in, n-1, en)) + if ( n < 0 ) { + ChiselError.error("Cannot have negative number of cycles for shift register") + in + } else + RegNext(apply(in, n-1, en)) + } else { + in + } + } + + /** @param in input to delay + * @param init reset value to use + * @param n number of cycles to delay */ + def apply[T <: Data](in: T, init: T, n: Int) : T = apply(in, init, n, Bool(true)) + /** @param in input to delay + * @param init reset value to use + * @param n number of cycles to delay + * @param en enable the shift */ + def apply[T <: Data](in: T, init: T, n: Int, en: Bool) : T = + { + // The order of tests reflects the expected use cases. + if (n == 1) { + RegEnable(in, init, en) + } else if (n != 0) { + RegNext(apply(in, init, n-1, en), init) } else { in } } } -/** Returns the one hot encoding of the input UInt. +/** @return the one hot encoding of the input UInt + * @example + * {{{ val myOH = UIntToOH(UInt(5), 8) -> 0x20 + * val myOH2 = UIntToOH(UInt(0), 8) -> 0x01 }}} */ object UIntToOH { @@ -167,7 +217,7 @@ object UIntToOH */ object Mux1H { - def apply[T <: Data](sel: Iterable[Bool], in: Iterable[T]): T = { + def apply[T <: Data](sel: Seq[Bool], in: Seq[T]): T = { if (in.tail.isEmpty) in.head else { val masked = (sel, in).zipped map ((s, i) => Mux(s, i.toBits, Bits(0))) @@ -175,78 +225,114 @@ object Mux1H } } def apply[T <: Data](in: Iterable[(Bool, T)]): T = { - val (sel, data) = in.unzip + val (sel, data) = in.toSeq.unzip apply(sel, data) } - def apply[T <: Data](sel: Bits, in: Iterable[T]): T = + def apply[T <: Data](sel: Bits, in: Seq[T]): T = apply((0 until in.size).map(sel(_)), in) def apply(sel: Bits, in: Bits): Bool = (sel & in).orR } +/** An I/O Bundle containing data and a signal determining if it is valid + * @constructor A bundle containing the Bool(OUTPUT) 'valid' and 'bits' OUTPUT of type T + * @note can be constucted using the object [[Chisel.Valid$ Valid]] + * @example + * {{{ myIO = Valid[UInt](UInt(width=4)) + * myIO.valid := Bool(true) + * myIO.bits := UInt(5) }}}*/ class ValidIO[+T <: Data](gen: T) extends Bundle { + /** A valid OUTPUT signal */ val valid = Bool(OUTPUT) - val bits = gen.clone.asOutput + /** A OUTPUT signal created using gen */ + val bits = gen.cloneType.asOutput + /** @return when the data is consumed + * @note defined as the valid signal */ def fire(dummy: Int = 0): Bool = valid - override def clone: this.type = new ValidIO(gen).asInstanceOf[this.type] + /** clone this I/O */ + override def cloneType: this.type = new ValidIO(gen).asInstanceOf[this.type] } -/** Adds a valid protocol to any interface. The standard used is - that the consumer uses the flipped interface. -*/ +/** Adds a valid protocol to any interface + * By default this creates a [[Chisel.ValidIO ValidIO]] class with valid and bits set to OUTPUT + * @note can be set to INPUT using the function [[Chisel.Bundle.flip flip]] + * @example + * {{{ myIO = Valid(UInt(width=4)) + * myIO.valid := Bool(true) + * myIO.bits := UInt(5) }}}*/ object Valid { def apply[T <: Data](gen: T): ValidIO[T] = new ValidIO(gen) } +/** An I/O Bundle with simple handshaking using valid and ready signals for data 'bits' + * @note can be created using [[Chisel.Decoupled$ Decoupled]] + * @example + * {{{ val io = Decoupled(UInt(width=4)) + * io.valid := io.ready + * io.bits := UInt(5) }}} */ class DecoupledIO[+T <: Data](gen: T) extends Bundle { + /** [[Chisel.INPUT INPUT]] signal to indicate data is ready */ val ready = Bool(INPUT) + /** [[Chisel.OUTPUT OUTPUT]] signal to indicate data is valid */ val valid = Bool(OUTPUT) - val bits = gen.clone.asOutput + /** [[Chisel.OUTPUT OUTPUT]] data of type T */ + val bits = gen.cloneType.asOutput + /** Indicate when data has been consumed + * @note defined as ready && valid */ def fire(dummy: Int = 0): Bool = ready && valid - override def clone: this.type = new DecoupledIO(gen).asInstanceOf[this.type] + override def cloneType: this.type = new DecoupledIO(gen).asInstanceOf[this.type] } -/** Adds a ready-valid handshaking protocol to any interface. - The standard used is that the consumer uses the flipped - interface. +/** Adds a ready-valid handshaking protocol to any interface + * @note the I/O can be 'flipped' so the data is INPUT instead using the function [[Chisel.Bundle.flip flip]] */ object Decoupled { def apply[T <: Data](gen: T): DecoupledIO[T] = new DecoupledIO(gen) } +/** An I/O bundle for enqueuing data with valid/ready handshaking + * @example + * {{{ val io = new EnqIO(UInt(width=5)) + * when (myCond) { io.enq(UInt(3)) } }}}*/ class EnqIO[T <: Data](gen: T) extends DecoupledIO(gen) { + // Perhaps should return ready rather than dat? + /** enqueue data 'dat' by setting valid and bits */ def enq(dat: T): T = { valid := Bool(true); bits := dat; dat } - valid := Bool(false); - for (io <- bits.flatten.map(x => x._2)) - io := UInt(0) - override def clone: this.type = { new EnqIO(gen).asInstanceOf[this.type]; } + def init() { + valid := Bool(false); + for (io <- bits.flatten.map(x => x._2)) + io := UInt(0) + } + init() + override def cloneType: this.type = new EnqIO(gen).asInstanceOf[this.type] } +/** An I/O bundle for dequeuing data with valid/ready handshaking*/ class DeqIO[T <: Data](gen: T) extends DecoupledIO(gen) { flip() - ready := Bool(false); + def init() { + ready := Bool(false); + } + init() + /* Strange that this requires a Boolean argument + * Change to deq() : (T, Bool) = { ready := Bool(true); (bits, valid) } + */ def deq(b: Boolean = false): T = { ready := Bool(true); bits } - override def clone: this.type = { new DeqIO(gen).asInstanceOf[this.type]; } + override def cloneType: this.type = new DeqIO(gen).asInstanceOf[this.type] } - -class DecoupledIOC[+T <: Data](gen: T) extends Bundle -{ - val ready = Bool(INPUT) - val valid = Bool(OUTPUT) - val bits = gen.clone.asOutput -} - - +/** An I/O bundle for the Arbiter */ class ArbiterIO[T <: Data](gen: T, n: Int) extends Bundle { - val in = Vec.fill(n){ Decoupled(gen) }.flip + val in = Vec(n, Decoupled(gen) ).flip val out = Decoupled(gen) val chosen = UInt(OUTPUT, log2Up(n)) + override def cloneType: this.type = new ArbiterIO(gen, n).asInstanceOf[this.type] } +/** Arbiter Control determining which producer has access */ object ArbiterCtrl { def apply(request: Seq[Bool]): Seq[Bool] = { @@ -254,13 +340,13 @@ object ArbiterCtrl } } -abstract class LockingArbiterLike[T <: Data](gen: T, n: Int, count: Int, needsLock: Option[T => Bool] = None) extends Module { +abstract class LockingArbiterLike[T <: Data](gen: T, n: Int, count: Int, needsLock: Option[T => Bool] = None, needsHold: Boolean = false) extends Module { require(isPow2(count)) def grant: Seq[Bool] val io = new ArbiterIO(gen, n) - val locked = if(count > 1) Reg(init=Bool(false)) else Bool(false) - val lockIdx = if(count > 1) Reg(init=UInt(n-1)) else UInt(n-1) - val chosen = UInt(width = log2Up(n)) + val locked = if(count > 1 || needsHold) Reg(init=Bool(false)) else Bool(false) + val lockIdx = if(count > 1 || needsHold) Reg(init=UInt(n-1)) else UInt(n-1) + val chosen = Wire(UInt(width = log2Up(n))) for ((g, i) <- grant.zipWithIndex) io.in(i).ready := Mux(locked, lockIdx === UInt(i), g) && io.out.ready @@ -268,25 +354,48 @@ abstract class LockingArbiterLike[T <: Data](gen: T, n: Int, count: Int, needsLo io.out.bits := io.in(chosen).bits io.chosen := chosen - if(count > 1){ + if(count == 1 && needsHold) { + when(io.out.valid) { + locked := !io.out.ready + when(!locked) { + lockIdx := chosen + } + } + } + + if(count > 1) { val cnt = Reg(init=UInt(0, width = log2Up(count))) val cnt_next = cnt + UInt(1) - when(io.out.fire()) { - when(needsLock.map(_(io.out.bits)).getOrElse(Bool(true))) { - cnt := cnt_next + when(io.out.valid) { + if(needsHold) { // lock the chosen port if need hold when(!locked) { - locked := Bool(true) - lockIdx := Vec(io.in.map{ in => in.fire()}).indexWhere{i: Bool => i} + lockIdx := chosen + locked := !io.out.ready } } - when(cnt_next === UInt(0)) { - locked := Bool(false) + when(io.out.ready) { + when(needsLock.map(_(io.out.bits)).getOrElse(Bool(true))) { + cnt := cnt_next + locked := !(cnt_next === UInt(0)) + when(!locked) { + lockIdx := Vec(io.in.map{ in => in.fire()}).indexWhere{i: Bool => i} + } + }.otherwise { + locked := Bool(false) + } } } } } -class LockingRRArbiter[T <: Data](gen: T, n: Int, count: Int, needsLock: Option[T => Bool] = None) extends LockingArbiterLike[T](gen, n, count, needsLock) { +/** @param gen The type of producers + * @param n The number of producers + * @param count The size of burst + * @param needsLock The lock condition for burst (default is always lock) + * @param needsHold Hold the chosen port until it has fired for count times + */ +class LockingRRArbiter[T <: Data](gen: T, n: Int, count: Int, needsLock: Option[T => Bool] = None, needsHold: Boolean = false) + extends LockingArbiterLike[T](gen, n, count, needsLock, needsHold) { lazy val last_grant = Reg(init=UInt(0, log2Up(n))) override def grant: Seq[Bool] = { val ctrl = ArbiterCtrl((0 until n).map(i => io.in(i).valid && UInt(i) > last_grant) ++ io.in.map(_.valid)) @@ -303,7 +412,14 @@ class LockingRRArbiter[T <: Data](gen: T, n: Int, count: Int, needsLock: Option[ when (io.out.fire()) { last_grant := chosen } } -class LockingArbiter[T <: Data](gen: T, n: Int, count: Int, needsLock: Option[T => Bool] = None) extends LockingArbiterLike[T](gen, n, count, needsLock) { +/** @param gen The type of producers + * @param n The number of producers + * @param count The size of burst + * @param needsLock The lock condition for burst (default is always lock) + * @param needsHold Hold the chosen port until it has fired for count times + */ +class LockingArbiter[T <: Data](gen: T, n: Int, count: Int, needsLock: Option[T => Bool] = None, needsHold: Boolean = false) + extends LockingArbiterLike[T](gen, n, count, needsLock, needsHold) { def grant: Seq[Bool] = ArbiterCtrl(io.in.map(_.valid)) var choose = UInt(n-1) @@ -315,25 +431,29 @@ class LockingArbiter[T <: Data](gen: T, n: Int, count: Int, needsLock: Option[T /** Hardware module that is used to sequence n producers into 1 consumer. Producers are chosen in round robin order. - - Example usage: - val arb = new RRArbiter(2, UInt()) + @example + {{{ val arb = new Module(RRArbiter(2, UInt()) arb.io.in(0) <> producer0.io.out arb.io.in(1) <> producer1.io.out - consumer.io.in <> arb.io.out + consumer.io.in <> arb.io.out }}} + * @param gen The type of producers + * @param n The number of producers + * @param needsHold Hold the chosen port until it has fired */ -class RRArbiter[T <: Data](gen:T, n: Int) extends LockingRRArbiter[T](gen, n, 1) +class RRArbiter[T <: Data](gen:T, n: Int, needsHold: Boolean = false) extends LockingRRArbiter[T](gen, n, 1, None, needsHold) /** Hardware module that is used to sequence n producers into 1 consumer. Priority is given to lower producer - - Example usage: - val arb = Module(new Arbiter(2, UInt())) + @example + {{{ val arb = Module(new Arbiter(2, UInt())) arb.io.in(0) <> producer0.io.out arb.io.in(1) <> producer1.io.out - consumer.io.in <> arb.io.out + consumer.io.in <> arb.io.out }}} + * @param gen The type of producers + * @param n The number of producers + * @param needsHold Hold the chosen port until it has fired */ -class Arbiter[T <: Data](gen: T, n: Int) extends LockingArbiter[T](gen, n, 1) +class Arbiter[T <: Data](gen: T, n: Int, needsHold: Boolean = false) extends LockingArbiter[T](gen, n, 1, None, needsHold) object FillInterleaved @@ -342,8 +462,14 @@ object FillInterleaved def apply(n: Int, in: Seq[Bool]): UInt = Vec(in.map(Fill(n, _))).toBits } +/** A counter module, can also be created using [[Chisel.Counter$ Counter]] + * @param n The maximum value of the counter, does not have to be power of 2 + */ class Counter(val n: Int) { + /** current value of the counter */ val value = if (n == 1) UInt(0) else Reg(init=UInt(0, log2Up(n))) + /** increment the counter + * @return if the counter is at the max value */ def inc(): Bool = { if (n == 1) Bool(true) else { @@ -354,9 +480,19 @@ class Counter(val n: Int) { } } +/** Counter Object for [[Chisel.Counter Counter]] + * @example + * {{{ val countOn = Bool(true) // increment counter every clock cycle + * val myCounter = Counter(8) + * when ( myCounter.inc() ) { + * ... // When counter value is max at 7 do something + * } }}}*/ object Counter { def apply(n: Int): Counter = new Counter(n) + /** Get a counter which takes an input Bool of when to increment + * @return a UInt which is the value of the counter and a Bool indicating when the counter resets + */ def apply(cond: Bool, n: Int): (UInt, Bool) = { val c = new Counter(n) var wrap: Bool = null @@ -365,18 +501,44 @@ object Counter } } +/** An I/O Bundle for Queues + * @tparam T the type of data to queue (such as UInt) + * @param gen The type of data to queue + * @param entries The max number of entries in the queue */ class QueueIO[T <: Data](gen: T, entries: Int) extends Bundle { - val enq = Decoupled(gen.clone).flip - val deq = Decoupled(gen.clone) + /** I/O to enqueue data, is [[Chisel.DecoupledIO]] flipped */ + val enq = Decoupled(gen.cloneType).flip + /** I/O to dequeue data, is [[Chisel.DecoupledIO]]*/ + val deq = Decoupled(gen.cloneType) + /** The current amount of data in the queue */ val count = UInt(OUTPUT, log2Up(entries + 1)) -} - -class Queue[T <: Data](gen: T, val entries: Int, pipe: Boolean = false, flow: Boolean = false, _reset: Bool = null) extends Module(_reset=_reset) + override def cloneType: this.type = new QueueIO(gen, entries).asInstanceOf[this.type] +} + +/** A hardware module implementing a Queue + * @tparam T the type of data to queue + * @param gen The type of data to queue + * @param entries The max number of entries in the queue + * @param pipe True if a single entry queue can run at full throughput (like a pipeline). The ''ready'' signals are combinationally coupled. + * @param flow True if the inputs can be consumed on the same cycle +(the inputs "flow" through the queue immediately). The ''valid'' signals are coupled. + * @param _reset The reset signal to pass to this queue + * + * @example + * {{{ val q = new Queue(UInt(), 16) + * q.io.enq <> producer.io.out + * consumer.io.in <> q.io.deq }}} + */ +class Queue[T <: Data](gen: T, val entries: Int, + pipe: Boolean = false, + flow: Boolean = false, + _reset: Option[Bool] = None) extends Module(_reset=_reset) { + /** The I/O for this queue */ val io = new QueueIO(gen, entries) - val ram = Mem(gen, entries) + val ram = Mem(entries, gen) val enq_ptr = Counter(entries) val deq_ptr = Counter(entries) val maybe_full = Reg(init=Bool(false)) @@ -396,7 +558,7 @@ class Queue[T <: Data](gen: T, val entries: Int, pipe: Boolean = false, flow: Bo when (do_deq) { deq_ptr.inc() } - when (do_enq != do_deq) { + when (do_enq =/= do_deq) { maybe_full := do_enq } @@ -408,7 +570,11 @@ class Queue[T <: Data](gen: T, val entries: Int, pipe: Boolean = false, flow: Bo if (isPow2(entries)) { io.count := Cat(maybe_full && ptr_match, ptr_diff) } else { - io.count := Mux(ptr_match, Mux(maybe_full, UInt(entries), UInt(0)), Mux(deq_ptr.value > enq_ptr.value, UInt(entries) + ptr_diff, ptr_diff)) + io.count := Mux(ptr_match, + Mux(maybe_full, + UInt(entries), UInt(0)), + Mux(deq_ptr.value > enq_ptr.value, + UInt(entries) + ptr_diff, ptr_diff)) } } @@ -416,15 +582,13 @@ class Queue[T <: Data](gen: T, val entries: Int, pipe: Boolean = false, flow: Bo the depth of the queues. The width of the queue is determined from the inputs. - Example usage: - val q = new Queue(UInt(), 16) - q.io.enq <> producer.io.out - consumer.io.in <> q.io.deq + @example + {{{ consumer.io.in := Queue(producer.io.out, 16) }}} */ object Queue { def apply[T <: Data](enq: DecoupledIO[T], entries: Int = 2, pipe: Boolean = false): DecoupledIO[T] = { - val q = Module(new Queue(enq.bits.clone, entries, pipe)) + val q = Module(new Queue(enq.bits.cloneType, entries, pipe)) q.io.enq.valid := enq.valid // not using <> so that override is allowed q.io.enq.bits := enq.bits enq.ready := q.io.enq.ready @@ -432,30 +596,38 @@ object Queue } } +/** Asynchronous Fifo. Used to cross two clock domains. + * + * @param gen the type of data in the fifo + * @param entries the max number of entries in the fifo. The actual +size will be rounded up to the next power of 2 - (size = 1<> UInt(1)) ^ wptr_bin_next val not_full_next = !(wptr_gray_next === Cat(~s2_rptr_gray(asize,asize-1), s2_rptr_gray(asize-2,0))) - val rptr_bin = Reg(init=UInt(0, asize+1), clock=deq_clk) - val rptr_gray = Reg(init=UInt(0, asize+1), clock=deq_clk) + val rptr_bin = Reg(init=UInt(0, asize + 1), clock=deq_clk) + val rptr_gray = Reg(init=UInt(0, asize + 1), clock=deq_clk) val not_empty = Reg(init=Bool(false), clock=deq_clk) val rptr_bin_next = rptr_bin + (io.deq.ready & not_empty) @@ -478,13 +650,22 @@ class AsyncFifo[T<:Data](gen: T, entries: Int, enq_clk: Clock, deq_clk: Clock) e io.enq.ready := not_full io.deq.valid := not_empty - val mem = Mem(gen, entries, clock=enq_clk) + val mem = Mem(1 << asize, gen, clock=enq_clk) when (io.enq.valid && io.enq.ready) { mem(wptr_bin(asize-1,0)) := io.enq.bits } io.deq.bits := mem(rptr_bin(asize-1,0)) } +/** A hardware module that delays data coming down the pipeline + by the number of cycles set by the latency parameter. Functionality + is similar to ShiftRegister but this exposes a Pipe interface. + + @example {{{ + val pipe = new Pipe(UInt()) + pipe.io.enq <> produce.io.out + consumer.io.in <> pipe.io.deq }}} + */ class Pipe[T <: Data](gen: T, latency: Int = 1) extends Module { val io = new Bundle { @@ -495,14 +676,10 @@ class Pipe[T <: Data](gen: T, latency: Int = 1) extends Module io.deq <> Pipe(io.enq, latency) } -/** A hardware module that delays data coming down the pipeline - by the number of cycles set by the latency parameter. Functionality - is similar to ShiftRegister but this exposes a Pipe interface. +/** Similar to a shift register but with handshaking at start - Example usage: - val pipe = new Pipe(UInt()) - pipe.io.enq <> produce.io.out - consumer.io.in <> pipe.io.deq + @example + {{{ consumer.io.in := Pipe(producer.io.out, 2) }}} */ object Pipe { @@ -526,19 +703,19 @@ object Pipe /** Builds a Mux tree under the assumption that multiple select signals can be enabled. Priority is given to the first select signal. - Returns the output of the Mux tree. + @return the output of the Mux tree */ object PriorityMux { - def apply[T <: Bits](in: Iterable[(Bool, T)]): T = { + def apply[T <: Data](in: Seq[(Bool, T)]): T = { if (in.size == 1) { in.head._2 } else { Mux(in.head._1, in.head._2, apply(in.tail)) } } - def apply[T <: Bits](sel: Iterable[Bool], in: Iterable[T]): T = apply(sel zip in) - def apply[T <: Bits](sel: Bits, in: Iterable[T]): T = apply((0 until in.size).map(sel(_)), in) + def apply[T <: Data](sel: Seq[Bool], in: Seq[T]): T = apply(sel zip in) + def apply[T <: Data](sel: Bits, in: Seq[T]): T = apply((0 until in.size).map(sel(_)), in) } /** Returns a bit vector in which only the least-significant 1 bit in @@ -550,9 +727,158 @@ object PriorityEncoderOH val outs = Vec.tabulate(in.size)(i => UInt(BigInt(1) << i, in.size)) PriorityMux(in :+ Bool(true), outs :+ UInt(0, in.size)) } - def apply(in: Seq[Bool]): Vec[Bool] = { + def apply(in: Seq[Bool]): Seq[Bool] = { val enc = encode(in) - Vec.tabulate(in.size)(enc(_)) + Seq.tabulate(in.size)(enc(_)) } def apply(in: Bits): UInt = encode((0 until in.getWidth).map(i => in(i))) } + +/** Chisel3 - Wrap a Chisel data type with a `Wire`. + * + * This sets the isWired state. It will be required for Chisel 3.0 + * The logic is: + * - for each element in a module: + * - is that element assigned to? + * - is that element defined with only a type (no compute logic)? + * If so, the element's definition must be wrapped in a Wire. + */ +object Wire +{ + def apply[T <: Data](t: T = null, init: T = null): T = + apply(Option(t), Option(init)) + + def apply[T <: Data](t: Option[T], init: Option[T]): T = { + t match { + case Some(p) if !p.isTypeOnly => + ChiselError.error("Wire() must not wrap a node with data %s".format(p)) + case _ => + } + val res = (init, t) match { + case (Some(p), _) => + val x = p.cloneType + x := p + x + case (_, Some(p)) => + p.cloneType + case _ => + ChiselError.error("cannot infer type of Init.") + UInt().asInstanceOf[T] + } + res.setIsWired(true) + res.asDirectionless + } +} + +/** DelayBetween works out the number of registers or delays for all possible directional paths between two nodes + */ +object DelayBetween { + + /** This method recursively searchs backwards along the directional graph from visited to end + 12/08/2015 - Duncan: Changed to the standard depth frist search + */ + private def nodePathDepthSearch(visited : List[Node], end : Node, paths : ArrayBuffer[Int]) : ArrayBuffer[Int] = { + val startList : List[Node] = visited.last.inputs.toList + for (node <- startList) { + if (!visited.contains(node)) { + if (node._id == end._id) { + val completePath : List[Node] = visited :+ node + paths += completePath.filter({case _: Delay => true case _ => false}).length + } else { + val nextPath = visited :+ node + paths ++= nodePathDepthSearch(nextPath, end, new ArrayBuffer[Int]) + } + } + } + paths + } + + /** Find all paths between the two nodes using a breadth first search */ + private def nodePathBreadthSearch(start : Node, end : Node) : ArrayBuffer[Int] = { + val que = new scala.collection.mutable.Queue[Node] + val paths = new scala.collection.mutable.Queue[List[Node]] + val completePaths = new ArrayBuffer[Int] + var visited = List(start._id) + que.enqueue(start) + paths.enqueue(List(start)) + while(!que.isEmpty) { + val node = que.dequeue() + val currentPath = paths.dequeue() + if (node._id == end._id) { + completePaths.append(currentPath.filter({case _: Delay => true case _ => false}).length) + visited = visited diff List(node._id) + } else { + node.inputs.foreach(l => if(!visited.contains(l._id)) { + visited :::= List(l._id) + que.enqueue(l) + val nextPath = currentPath :+ l + paths.enqueue(nextPath) + }) + } + } + completePaths + } + + + /** Finds to shortest path between two nodes using a multi-stage depth first search */ + private def nodeShortestPathSearch(startList : List[Node], end : Node) : Int = { + // We what this to operate in two different stages, first is to find either a register or the end + // if the end is found return the value, otherwise start the search again from the registers + var searchNodes = startList + val visited = new ArrayBuffer[Int] + var count = -1 + var found = false + while (!found & !searchNodes.isEmpty) { + count += 1 + val nodesToSearch = new ArrayBuffer[Node] + for (node <- searchNodes) { + if (!visited.contains(node._id) & !found) { + visited.append(node._id) + val delayLevel = nodeFindRegOrEnd(List(node), end, new ArrayBuffer[Node]).toList + found = delayLevel.contains(end) + delayLevel.foreach(n => nodesToSearch.append(n)) + } + } + searchNodes = nodesToSearch.toList + } + if(!found) count = -1 + count + } + + /** Depth First Search to find either the end or a register */ + private def nodeFindRegOrEnd(visited : List[Node], end : Node, nodes : ArrayBuffer[Node]) : ArrayBuffer[Node] = { + visited.last.inputs.toList.map(node => { + if (!visited.contains(node)) { + if (node._id == end._id || (node match {case _: Delay => true case _ => false})) { + nodes += node + } else { + val nextPath = visited :+ node + nodes ++= nodeFindRegOrEnd(nextPath, end, new ArrayBuffer[Node]) + } + } + }) + nodes + } + + + /** Find all delays for paths from a to b + * @param a starting node + * @param b finishing node + * @param breadth used depth first search by default, true if you want to use breadth first search + * @return the all delays between a and b from smallest to largest + */ + def apply(a : Node, b : Node, breadth : Boolean = false) : List[Int] = { + // Do a bfs looking at all inputs of b until a is reached + val res = if (breadth) nodePathBreadthSearch(b, a) else nodePathDepthSearch(List(b), a, new ArrayBuffer[Int]) + res.distinct.sorted.toList + } + + /** Find the Shortest path from a to b + * @param a starting node + * @param b finishing node + * @return the shorted delay between a and b + */ + def findShortest(a : Node, b : Node) : Int = { + nodeShortestPathSearch(List(b), a) + } +} diff --git a/src/main/scala/Clock.scala b/src/main/scala/Clock.scala index e5d91534..9fba2e45 100644 --- a/src/main/scala/Clock.scala +++ b/src/main/scala/Clock.scala @@ -1,5 +1,5 @@ /* - Copyright (c) 2011, 2012, 2013, 2014 The Regents of the University of + Copyright (c) 2011 - 2016 The Regents of the University of California (Regents). All Rights Reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: @@ -30,38 +30,55 @@ package Chisel -import scala.collection.mutable.ArrayBuffer +/** Create a new Clock */ +object Clock { + // TODO: make src and period private like Clock Class? + /** @param reset the reset for this clock + * @param src the source clock for this clock + * @param period the period in ps for this clock, implicitClock has period of 1ps + */ + def apply(reset: Bool = Driver.implicitReset, src: Option[Clock] = None, period: Double = 1.0) = { + new Clock(reset, src, period) + } -class Clock(reset: Bool = Driver.implicitReset) extends Node { - val stateElms = new ArrayBuffer[Node] - Driver.clocks += this - init("", 1) + // For Chisel3 compatibility. + def apply(dir: IODirection): Clock = { + apply() + } + + implicit def toOption(c: Clock) = Option(c) +} - var srcClock: Clock = null - var initStr = "" +/** Create a new clock + * @param reset The reset for this clock + */ +class Clock(reset: Bool = Driver.implicitReset, + private[Chisel] val srcClock: Option[Clock] = None, + private[Chisel] val period: Double = 1.0 /* in ps */) extends Node { - // returns a reset pin connected to reset for the component in scope + init("", 1) + Driver.clocks += this + + /** @return a reset pin connected to reset for the component in scope */ def getReset: Bool = { - if (Driver.compStack.length != 0) { + if (!Driver.compStack.isEmpty) { Driver.compStack.top.addResetPin(reset) } else { reset } } - def * (x: Int): Clock = { - val clock = new Clock(reset) - clock.init("", 1) - clock.srcClock = this - clock.initStr = " * " + x + ";\n" - clock - } + override lazy val isInObject: Boolean = true + override lazy val isInVCD: Boolean = Driver.isVCD + + /** multiply the period of the clock + * Will create another clock with the respective period */ + def * (x: Int) = Clock(reset, Some(this), period * x.toDouble) + /** divide the clock period + * Will create another clock with the respective period */ + def / (x: Int) = Clock(reset, Some(this), period / x.toDouble) - def / (x: Int): Clock = { - val clock = new Clock(reset) - clock.init("", 1) - clock.srcClock = this - clock.initStr = " / " + x + ";\n" - clock + def := (that: Clock): Unit = { + this.getReset := that.getReset } } diff --git a/src/main/scala/Complex.scala b/src/main/scala/Complex.scala index df7c99d7..b0c618fb 100644 --- a/src/main/scala/Complex.scala +++ b/src/main/scala/Complex.scala @@ -1,5 +1,5 @@ /* - Copyright (c) 2011, 2012, 2013, 2014 The Regents of the University of + Copyright (c) 2011 - 2016 The Regents of the University of California (Regents). All Rights Reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: @@ -30,17 +30,51 @@ package Chisel +/** Representation for complex numbers */ object Complex { + /** flag to indicate if using four multiplications or three, default is false + * Four mult calculates: {{{ (a + bi)*(c + di) = (ac - bd) + (ad + bc)i }}} + * Three mult calculates: + * {{{ ac_p_ad = a * (c + d), ad_p_bd = (a + b) * d, bc_m_ac = (b - a) * c + * (ac_p_ad - ad_p_bd) + (ac_p_ad + bc_m_ac)i }}} */ var use_four_mults = false + /** Create a new Complex number: real + imag*i + * @tparam T the type to represent the complex number with, eg) UInt, SInt, Fixed + * @example {{{ val myNum = Complex(UInt(3), UInt(1)) }}} */ def apply[T<:Data with Num[T]](real: T, imag: T) = new Complex(real, imag) } -class Complex[T<:Data with Num[T]](val real: T, val imag: T) extends Bundle { - override def clone() = { - new Complex(real.clone, imag.clone).asInstanceOf[this.type] +/** Compute the conjugate of a complex number using the function [[Chisel.Complex.conj conj]] */ +object conjugate { + /** @example {{{ conjugate(Complex(SInt(3), SInt(1))) => Complex(SInt(3), SInt(-1)) }}}*/ + def apply[T<: Data with Num[T]](x : T) : T = x match { + case x : Complex[_] => x.conj.asInstanceOf[T] + case _ => x + } +} + +/** Complex number representation + * create using the object [[Chisel.Complex$ Complex]] + * @example {{{ val myNum = Complex[Fixed](Fixed(3, 16, 8), Fixed(1, 16, 8)) }}} */ +class Complex[T<:Data with Num[T]](val real: T, val imag: T) extends Bundle with Num[Complex[T]] { + /** Clone a complex instantiation */ + override def cloneType() = { + new Complex(real.cloneType, imag.cloneType).asInstanceOf[this.type] + } + + /** Check that 'name' is a valid component of Complex, ie) real or imag */ + override protected def checkPort(obj : Any, name : String) : Boolean = name match { + case "real" => true + case "imag" => true + case "abs2" => false + case "conj" => false + case "unary_-" => false + case _ => true } + /** A complex multiply, uses 3 multiplies by default + * Change to use four with the [[Chisel.Complex$.use_four_mults use_four_mults]] boolean variable */ def * (r: Complex[T]): Complex[T] = { val a = real; val b = imag; val c = r.real; val d = r.imag; @@ -60,21 +94,62 @@ class Complex[T<:Data with Num[T]](val real: T, val imag: T) extends Bundle { } } - def / (r: Complex[T]): Complex[T] = ??? - + /** Create a new complex number which is the conjugate of this one */ + def conj : Complex[T] = + { + new Complex(real, -imag) + } + def / (r: Complex[T]): Complex[T] = + { + this * r.conj / r.abs2 + } def * (r: T): Complex[T] = { new Complex(real*r, imag*r) } + /** Uses the % operator defined in the types + * Is defined as: + * {{{ (this.real % r.real) + (this.imag % r.imag)i }}}*/ + def % (r : Complex[T]): Complex[T] = + { + // this is bad, but what can we do? + new Complex(real % r.real, imag % r.imag) + } + /** Compare the magnitudes of the complex numbers */ + def < (b : Complex[T]) : Bool = + { + this.abs2 < b.abs2 + } + /** Compare the magnitudes of the complex numbers */ + def <= (b : Complex[T]) : Bool = + { + this.abs2 <= b.abs2 + } + /** Compare the magnitudes of the complex numbers */ + def > (b : Complex[T]) : Bool = + { + this.abs2 > b.abs2 + } + /** Compare the magnitudes of the complex numbers */ + def >= (b : Complex[T]) : Bool = + { + this.abs2 >= b.abs2 + } + /** Compute the magnitude of the complex number: real^2 + imag^2 */ + def abs2 : T = + { + real * real + imag * imag + } def / (r: T): Complex[T] = { new Complex(real/r, imag/r) } - + /** Add a scalar value to both the real and imaginary parts */ def + (r: Complex[T]): Complex[T] = { new Complex(real + r.real, imag + r.imag) } + /** Subtract a scalar value from both the real and imaginary parts */ def - (r: Complex[T]): Complex[T] = { new Complex(real - r.real, imag - r.imag) @@ -85,23 +160,3 @@ class Complex[T<:Data with Num[T]](val real: T, val imag: T) extends Bundle { new Complex(-real, -imag) } } - -class ComplexTest extends Module { - val io = new Bundle { - val in_t = Complex(SInt(width=16),SInt(width=16)).asInput - val in_f = Complex(SInt(width=16),SInt(width=16)).asInput - val cond = Bool(INPUT) - val out = Complex(SInt(width=16),SInt(width=16)).asOutput - - val b_t = UInt(width=1).asInput - val b_f = UInt(width=1).asInput - val b_o = UInt(width=1).asOutput - } - - val myLit = Complex(SInt(1), SInt(1)) - - io.out := Mux(io.cond, io.in_t+io.in_f, io.in_t-io.in_f) + myLit - - io.b_o := Mux(io.cond, io.b_t, Bool(false)) - -} diff --git a/src/main/scala/Cpp.scala b/src/main/scala/Cpp.scala index 5fae67e6..6a7456ed 100644 --- a/src/main/scala/Cpp.scala +++ b/src/main/scala/Cpp.scala @@ -1,5 +1,5 @@ /* - Copyright (c) 2011, 2012, 2013, 2014 The Regents of the University of + Copyright (c) 2011 - 2016 The Regents of the University of California (Regents). All Rights Reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: @@ -29,22 +29,8 @@ */ package Chisel -import scala.collection.mutable.ArrayBuffer -import scala.math._ -import java.io.InputStream -import java.io.OutputStream -import java.io.PrintStream -import java.io.BufferedReader -import java.io.InputStreamReader -import scala.sys.process._ -import sys.process.stringSeqToProcess -import Node._ -import Reg._ -import ChiselError._ -import Literal._ -import scala.collection.mutable.HashSet -import scala.collection.mutable.HashMap -import PartitionIslands._ +import scala.collection.mutable.{ArrayBuffer, HashSet, HashMap} +import java.io.{BufferedReader, InputStreamReader} object CString { def apply(s: String): String = { @@ -63,44 +49,32 @@ object CString { } class CppBackend extends Backend { - val keywords = Set[String]() + import PartitionIslands._ private var hasPrintfs = false - val unoptimizedFiles = HashSet[String]() - val onceOnlyFiles = HashSet[String]() - var cloneFile: String = "" - var maxFiles: Int = 0 - val compileInitializationUnoptimized = Driver.compileInitializationUnoptimized + protected[this] val unoptimizedFiles = HashSet[String]() + protected[this] val onceOnlyFiles = HashSet[String]() + protected[this] var maxFiles: Int = 0 + protected[this] val compileInitializationUnoptimized = Driver.compileInitializationUnoptimized // If we're dealing with multiple files for the purpose of separate // optimization levels indicate we expect to compile multiple files. - val compileMultipleCppFiles = Driver.compileInitializationUnoptimized - // Suppress generation of the monolithic .cpp file if we're compiling - // multiple files. - // NOTE: For testing purposes, we may want to generate this file anyway. - val suppressMonolithicCppFile = compileMultipleCppFiles /* && false */ - // Compile the clone method at -O0 - val cloneCompiledO0 = true + protected[this] val compileMultipleCppFiles = Driver.compileInitializationUnoptimized // Define shadow registers in the circuit object, instead of local registers in the clock hi methods. // This is required if we're generating paritioned combinatorial islands, or we're limiting the size of functions/methods. - val shadowRegisterInObject = Driver.shadowRegisterInObject || Driver.partitionIslands || Driver.lineLimitFunctions > 0 + protected[this] val shadowRegisterInObject = Driver.shadowRegisterInObject || Driver.partitionIslands || Driver.lineLimitFunctions > 0 // If we need to put shadow registers in the object, we also should put multi-word literals there as well. - val multiwordLiteralInObject = shadowRegisterInObject - val multiwordLiterals = HashSet[Literal]() + // Actually, in order for emitLoWordRef() to work for multi-word literals, we need to have them in the object and initialized once. + protected[this] val multiwordLiteralInObject = shadowRegisterInObject || true + protected[this] val multiwordLiterals = HashSet[Literal]() // Should we put unconnected inputs in the object? - val unconnectedInputsInObject = Driver.partitionIslands - val unconnectedInputs = HashSet[Node]() + protected[this] val unconnectedInputsInObject = Driver.partitionIslands + protected[this] val unconnectedInputs = HashSet[Node]() // Sets to manage allocation and generation of shadow registers - val regWritten = HashSet[Node]() - val needShadow = HashSet[Node]() - val allocatedShadow = HashSet[Node]() - - var potentialShadowRegisters = 0 - val allocateOnlyNeededShadowRegisters = Driver.allocateOnlyNeededShadowRegisters - val ignoreShadows = false - val shadowPrefix = if (ignoreShadows) { - "// " - } else { - "" - } + protected[this] val regWritten = HashSet[Node]() + protected[this] val needShadow = HashSet[Node]() + protected[this] val allocatedShadow = HashSet[Node]() + + protected[this] var potentialShadowRegisters = 0 + protected[this] val allocateOnlyNeededShadowRegisters = Driver.allocateOnlyNeededShadowRegisters override def emitTmp(node: Node): String = { require(false) @@ -121,42 +95,69 @@ class CppBackend extends Backend { } } + // Emit the address of a node's values. + def emitValueAddress(node: Node): String = { + "&" + emitLoWordRef(node) + } + // Manage a constant pool. - val coalesceConstants = multiwordLiteralInObject - val constantPool = HashMap[String, Literal]() - def wordMangle(x: Node, w: String): String = x match { + protected[this] val coalesceConstants = multiwordLiteralInObject + protected[this] val constantPool = HashMap[(String, Width), Literal]() + + protected[this] def emitValue(value: BigInt, w: Int = 0): String = { + val hex = value.toString(16) + "0x" + (if (hex.length > bpw/4*w) hex.slice(hex.length-bpw/4*(w + 1), hex.length-bpw/4*w) else 0) + "L" + } + + // Emit the value of a literal, instead of a reference to it. + protected[this] def emitLitVal(n: Node, w: Int): String = { + assert(isLit(n), ChiselError.error("Internal Error: Trying to emitLitVal for non-literal %s".format(n))) + val l = n.asInstanceOf[Literal] + val lit = l.value + val value = if (lit < 0) (BigInt(1) << l.needWidth()) + lit else lit + emitValue(value, w) + } + + protected[this] def wordMangle(x: Node, w: String): String = x match { case l: Literal => if (words(x) == 1) { emitRef(x) } else { - // Are we maintaining a constant pool? - if (coalesceConstants) { - val cn = constantPool.getOrElseUpdate(l.name, l) - s"T${cn.emitIndex}[${w}]" - } else { - s"T${x.emitIndex}[${w}]" - } + val node = // Are we maintaining a constant pool? + if (!coalesceConstants) x + else constantPool.getOrElseUpdate((l.name, l.width_), l) + s"T${node.emitIndex}[${w}]" } case _ => if (x.isInObject) s"${emitRef(x)}.values[${w}]" else if (words(x) == 1) emitRef(x) else s"${emitRef(x)}[${w}]" } - def emitLit(value: BigInt, w: Int = 0): String = { - val hex = value.toString(16) - "0x" + (if (hex.length > bpw/4*w) hex.slice(hex.length-bpw/4*(w + 1), hex.length-bpw/4*w) else 0) + "L" - } - def wordMangle(x: Node, w: Int): String = - if (w >= words(x)) { + + protected[this] def wordMangle(x: Node, w: Int): String = { + val nWords = words(x) + // If we're asking for a word that doesn't exist, return 0. + // FIXME: Shouldn't this generate an error? + if (w >= nWords) { "0L" } else x match { + // If this is a single word literal, we just output its value. case l: Literal => - val lit = l.value - val value = if (lit < 0) (BigInt(1) << x.needWidth()) + lit else lit - emitLit(value, w) - case _ => wordMangle(x, w.toString) + if (nWords == 1) { + emitLitVal(l, w) + } else { + // Otherwise, we'd better have multiwordLiteralInObject so we can return a reference to the specific word. + assert(multiwordLiteralInObject, ChiselError.error("Internal Error: multiword literal reference without object to refer to")) + wordMangle(x, w.toString) + } + case _ => + wordMangle(x, w.toString) } - def isLit(node: Node): Boolean = node.isLit || node.isInstanceOf[Bits] && node.inputs.length == 1 && isLit(node.inputs.head) + } + + protected[this] def isLit(node: Node): Boolean = + node.isLit || node.isInstanceOf[Bits] && node.inputs.length == 1 && isLit(node.inputs.head) + def emitWordRef(node: Node, w: Int): String = { node match { case x: Binding => @@ -169,47 +170,32 @@ class CppBackend extends Backend { } // Returns a list of tuples (type, name) of variables needed by a node - def nodeVars(node: Node): List[(String, String)] = { + protected[this] def nodeVars(node: Node): List[(String, String)] = { node match { - case x: Binding => - List() - case l: Literal => - if (isInObject(l) && words(l) > 1) { - // Are we maintaining a constant pool? - if (coalesceConstants) { - // Is this the node that actually defines the constant? - // If so, output the definition (we must do this only once). - if (constantPool.contains(l.name) && constantPool(l.name) == l) { - List((s" static const val_t", s"T${l.emitIndex}[${words(l)}]")) - } else { - List() - } - } else { - List((s" static const val_t", s"T${l.emitIndex}[${words(l)}]")) - } - } else { + case x: Binding => List() + case l: Literal if isInObject(l) && words(l) > 1 => + // Are we maintaining a constant pool? + // If yes, we'll output it separately. + if (coalesceConstants) { List() + } else { + List((s" static const val_t", s"T${l.emitIndex}[${words(l)}]")) } - case x: Reg => - List((s"dat_t<${node.needWidth()}>", emitRef(node))) ++ { - if (!allocateOnlyNeededShadowRegisters || needShadow.contains(node)) { - // Add an entry for the shadow register in the main object. - if (shadowRegisterInObject) { - List((s"${shadowPrefix} dat_t<${node.needWidth()}>", shadowPrefix + emitRef(node) + s"__shadow")) - } else { - Nil - } - } else { - Nil - } + case l: Literal => List() + case x: Reg => List((s"dat_t<${node.needWidth()}>", emitRef(node))) ++ { + if ((!allocateOnlyNeededShadowRegisters || needShadow.contains(node)) && shadowRegisterInObject) { + // Add an entry for the shadow register in the main object. + List((s" dat_t<${node.needWidth()}>", emitRef(node) + s"__shadow")) + } else { + Nil } + } case m: Mem[_] => List((s"mem_t<${m.needWidth()},${m.n}>", emitRef(m))) case r: ROMData => List((s"mem_t<${r.needWidth()},${r.n}>", emitRef(r))) case c: Clock => - List(("int", emitRef(node)), - ("int", emitRef(node) + "_cnt")) + List(("clk_t", emitRef(c))) case _ => List((s"dat_t<${node.needWidth()}>", emitRef(node))) } @@ -223,7 +209,7 @@ class CppBackend extends Backend { out.toString() } - def emitCircuitAssign(srcPrefix:String, node: Node): String = { + protected[this] def emitCircuitAssign(srcPrefix:String, node: Node): String = { val out = new StringBuilder("") for (varDef <- nodeVars(node)) { out.append(s" ${varDef._2} = ${srcPrefix}${varDef._2};\n") @@ -231,9 +217,9 @@ class CppBackend extends Backend { out.toString() } - val bpw = 64 - def words(node: Node): Int = (node.needWidth() - 1) / bpw + 1 - def fullWords(node: Node): Int = node.needWidth()/bpw + protected[this] val bpw = 64 + protected[this] def words(node: Node): Int = (node.needWidth() - 1) / bpw + 1 + protected[this] def fullWords(node: Node): Int = node.needWidth()/bpw def emitLoWordRef(node: Node): String = emitWordRef(node, 0) // If we're generating multiple methods, literals and temporaries have to live in the main object. // We only get to ask isInObject once, so we'd better arrange for it to give the correct answer before we ask. @@ -259,17 +245,17 @@ class CppBackend extends Backend { def trunc(x: Node): String = { val gotWidth = x.needWidth() if (gotWidth % bpw == 0) "" - else s" ${emitWordRef(x, words(x)-1)} = ${emitWordRef(x, words(x)-1)} & ${emitLit((BigInt(1) << (gotWidth%bpw))-1)};\n" + else s" ${emitWordRef(x, words(x)-1)} = ${emitWordRef(x, words(x)-1)} & ${emitValue((BigInt(1) << (gotWidth%bpw))-1)};\n" } def opFoldLeft(o: Op, initial: (String, String) => String, subsequent: (String, String, String) => String) = (1 until words(o.inputs(0))).foldLeft(initial(emitLoWordRef(o.inputs(0)), emitLoWordRef(o.inputs(1))))((c, i) => subsequent(c, emitWordRef(o.inputs(0), i), emitWordRef(o.inputs(1), i))) def emitLog2(x: Node, priEnc: Boolean = false) = { val (func, range) = - if (priEnc) ("priority_encode_1", (0 until words(x.inputs(0))-1)) - else ("log2_1", (words(x.inputs(0))-1 to 1 by -1)) - val body = range.map(i => s"${emitWordRef(x.inputs(0), i)} != 0, ${(i*bpw)} + ${func}(${emitWordRef(x.inputs(0), i)})") - .foldRight(s"${func}(${emitLoWordRef(x.inputs(0))})")((x, y) => s"TERNARY(${x}, ${y})") + if (priEnc) ("priority_encode_1", (0 until words(x.inputs(0)))) + else ("log2_1", (words(x.inputs(0))-1 to 0 by -1)) + val body = range.map(i => s"${emitWordRef(x.inputs(0), i)} != 0, ${i*bpw} + ${func}(${emitWordRef(x.inputs(0), i)})") + .foldRight("0")((x, y) => s"TERNARY(${x}, ${y})") s" ${emitLoWordRef(x)} = ${body};\n" } @@ -286,14 +272,14 @@ class CppBackend extends Backend { (if (o.op == "^") { val res = ArrayBuffer[String]() res += "val_t __x = " + (0 until words(o.inputs(0))).map(emitWordRef(o.inputs(0), _)).reduceLeft(_ + " ^ " + _) - for (i <- log2Up(min(bpw, o.inputs(0).needWidth()))-1 to 0 by -1) + for (i <- log2Up(scala.math.min(bpw, o.inputs(0).needWidth()))-1 to 0 by -1) res += "__x = (__x >> " + (1L << i) + ") ^ __x" res += emitLoWordRef(o) + " = __x & 1" block(res) } else if (o.op == "~") { block((0 until words(o)).map(i => emitWordRef(o, i) + " = ~" + emitWordRef(o.inputs(0), i))) + trunc(o) } else if (o.op == "f-") - " " + emitLoWordRef(o) + " = fromFloat(-(toFloat(" + emitLoWordRef(o.inputs(0)) + "));\n" + " " + emitLoWordRef(o) + " = fromFloat(-(toFloat(" + emitLoWordRef(o.inputs(0)) + ")));\n" else if (o.op == "fsin") " " + emitLoWordRef(o) + " = fromFloat(sin(toFloat(" + emitLoWordRef(o.inputs(0)) + ")));\n" else if (o.op == "fcos") @@ -349,7 +335,7 @@ class CppBackend extends Backend { else if (o.op == "PriEnc" || o.op == "OHToUInt") emitLog2(o, true) else { - assert(false, "operator " + o.op + " unsupported") + assert(false, ChiselError.error("operator " + o.op + " unsupported")) "" }) } else if (o.op == "+" || o.op == "-") { @@ -376,11 +362,11 @@ class CppBackend extends Backend { if (o.needWidth() <= bpw) { " " + emitLoWordRef(o) + " = " + emitLoWordRef(o.inputs(0)) + " << " + emitLoWordRef(o.inputs(1)) + ";\n" + trunc(o) } else { - var shb = emitLoWordRef(o.inputs(1)) + val shb = emitLoWordRef(o.inputs(1)) val res = ArrayBuffer[String]() res += s"val_t __c = 0" - res += s"val_t __w = ${emitLoWordRef(o.inputs(1))} / ${bpw}" - res += s"val_t __s = ${emitLoWordRef(o.inputs(1))} % ${bpw}" + res += s"val_t __w = ${shb} / ${bpw}" + res += s"val_t __s = ${shb} % ${bpw}" res += s"val_t __r = ${bpw} - __s" for (i <- 0 until words(o)) { val inputWord = wordMangle(o.inputs(0), s"CLAMP(${i}-__w, 0, ${words(o.inputs(0)) - 1})") @@ -393,6 +379,7 @@ class CppBackend extends Backend { } else if (o.op == ">>" || o.op == "s>>") { val arith = o.op == "s>>" val gotWidth = o.inputs(0).needWidth() + // Is this a single word shift? if (gotWidth <= bpw) { if (arith) { s" ${emitLoWordRef(o)} = sval_t(${emitLoWordRef(o.inputs(0))} << ${bpw - gotWidth}) >> (${bpw - gotWidth} + ${emitLoWordRef(o.inputs(1))});\n" + trunc(o) @@ -400,28 +387,25 @@ class CppBackend extends Backend { s" ${emitLoWordRef(o)} = ${emitLoWordRef(o.inputs(0))} >> ${emitLoWordRef(o.inputs(1))};\n" } } else { - var shb = emitLoWordRef(o.inputs(1)) val res = ArrayBuffer[String]() - res += s"val_t __c = 0" - res += s"val_t __w = ${emitLoWordRef(o.inputs(1))} / ${bpw}" - res += s"val_t __s = ${emitLoWordRef(o.inputs(1))} % ${bpw}" - res += s"val_t __r = ${bpw} - __s" - if (arith) - res += s"val_t __msb = (sval_t)${emitWordRef(o.inputs(0), words(o)-1)} << ${(bpw - o.needWidth() % bpw) % bpw} >> ${(bpw-1)}" - for (i <- words(o)-1 to 0 by -1) { - val inputWord = wordMangle(o.inputs(0), s"CLAMP(${i}+__w, 0, ${words(o.inputs(0))-1})") - res += s"val_t __v${i} = MASK(${inputWord}, __w + ${i} < ${words(o.inputs(0))})" - res += s"${emitWordRef(o, i)} = __v${i} >> __s | __c" - res += s"__c = MASK(__v${i} << __r, __s != 0)" - if (arith) { - val gotWidth = o.needWidth() - res += s"${emitWordRef(o, i)} |= MASK(__msb << ((${gotWidth-1}-${emitLoWordRef(o.inputs(1))}) % ${bpw}), ${(i + 1) * bpw} > ${gotWidth-1} - ${emitLoWordRef(o.inputs(1))})" - res += s"${emitWordRef(o, i)} |= MASK(__msb, ${i*bpw} >= ${gotWidth-1} - ${emitLoWordRef(o.inputs(1))})" - } - } + val nWords = ((gotWidth - 1) / bpw) + 1 + /* Use int and assume rsh < 2^32, define amount_shift as the amount to right shift */ + res += s"unsigned int __amount = ${emitLoWordRef(o.inputs(1))}" + /* Define in_words as number of 64 bit words for the input */ + res += s"const unsigned int __in_words = ${nWords}" + /* Define in_width as the bit width of the input */ + res += s"int __in_width = ${gotWidth}" + res += s"val_t __d0[${nWords}]" + val srcRef = s"&${emitLoWordRef(o.inputs(0))}" + // Call Rshift if (arith) { - val gotWidth = o.needWidth() - res += emitLoWordRef(o) + " |= MASK(__msb << ((" + (gotWidth-1) + "-" + emitLoWordRef(o.inputs(1)) + ") % " + bpw + "), " + bpw + " > " + (gotWidth-1) + "-" + emitLoWordRef(o.inputs(1)) + ")" + res += s"rsha_n(__d0, ${srcRef}, __amount, __in_words, __in_width)" + } else { + res += s"rsh_n(__d0, ${srcRef}, __amount, __in_words)" + } + /* Attach the result from __d0 to o */ + for ( i <- 0 until words(o) ) { + res += s"${emitWordRef(o, i)} = __d0[${i}]" } block(res) + (if (arith) trunc(o) else "") } @@ -479,6 +463,8 @@ class CppBackend extends Backend { " " + emitLoWordRef(o) + " = toFloat(" + emitLoWordRef(o.inputs(0)) + ") != toFloat(" + emitLoWordRef(o.inputs(1)) + ");\n" } else if (o.op == "f>") { " " + emitLoWordRef(o) + " = toFloat(" + emitLoWordRef(o.inputs(0)) + ") > toFloat(" + emitLoWordRef(o.inputs(1)) + ");\n" + } else if (o.op == "f<") { + " " + emitLoWordRef(o) + " = toFloat(" + emitLoWordRef(o.inputs(0)) + ") < toFloat(" + emitLoWordRef(o.inputs(1)) + ");\n" } else if (o.op == "f<=") { " " + emitLoWordRef(o) + " = toFloat(" + emitLoWordRef(o.inputs(0)) + ") <= toFloat(" + emitLoWordRef(o.inputs(1)) + ");\n" } else if (o.op == "f>=") { @@ -501,59 +487,88 @@ class CppBackend extends Backend { " " + emitLoWordRef(o) + " = toDouble(" + emitLoWordRef(o.inputs(0)) + ") != toDouble(" + emitLoWordRef(o.inputs(1)) + ");\n" } else if (o.op == "d>") { " " + emitLoWordRef(o) + " = toDouble(" + emitLoWordRef(o.inputs(0)) + ") > toDouble(" + emitLoWordRef(o.inputs(1)) + ");\n" + } else if (o.op == "d<") { + " " + emitLoWordRef(o) + " = toDouble(" + emitLoWordRef(o.inputs(0)) + ") < toDouble(" + emitLoWordRef(o.inputs(1)) + ");\n" } else if (o.op == "d<=") { " " + emitLoWordRef(o) + " = toDouble(" + emitLoWordRef(o.inputs(0)) + ") <= toDouble(" + emitLoWordRef(o.inputs(1)) + ");\n" } else if (o.op == "d>=") { " " + emitLoWordRef(o) + " = toDouble(" + emitLoWordRef(o.inputs(0)) + ") >= toDouble(" + emitLoWordRef(o.inputs(1)) + ");\n" } else { - assert(false, "operator " + o.op + " unsupported") + assert(false, ChiselError.error("operator " + o.op + " unsupported")) "" }) } case x: Extract => x.inputs.tail.foreach(e => x.validateIndex(e)) - emitTmpDec(node) + - (if (node.inputs.length < 3 || node.needWidth() == 1) { - if (node.inputs(1).isLit) { - val value = node.inputs(1).litValue().toInt - " " + emitLoWordRef(node) + " = (" + emitWordRef(node.inputs(0), value/bpw) + " >> " + (value%bpw) + ") & 1;\n" - } else if (node.inputs(0).needWidth() <= bpw) { - " " + emitLoWordRef(node) + " = (" + emitLoWordRef(node.inputs(0)) + " >> " + emitLoWordRef(node.inputs(1)) + ") & 1;\n" - } else { - val inputWord = wordMangle(node.inputs(0), emitLoWordRef(node.inputs(1)) + "/" + bpw) - s"${emitLoWordRef(node)} = ${inputWord} >> (${emitLoWordRef(node.inputs(1))} % ${bpw}) & 1" - } + val source = node.inputs(0) + val hi = node.inputs(1) + val lo = if (node.inputs.length < 3) { + hi } else { - val rsh = node.inputs(2).litValue().toInt - if (rsh % bpw == 0) { - block((0 until words(node)).map(i => emitWordRef(node, i) + " = " + emitWordRef(node.inputs(0), i + rsh/bpw))) + trunc(node) - } else { - block((0 until words(node)).map(i => emitWordRef(node, i) - + " = " + emitWordRef(node.inputs(0), i + rsh/bpw) + " >> " - + (rsh % bpw) + ( - if (i + rsh/bpw + 1 < words(node.inputs(0))) { - " | " + emitWordRef(node.inputs(0), i + rsh/bpw + 1) + " << " + (bpw - rsh % bpw) - } else { - "" - }))) + trunc(node) + node.inputs(2) + } + // Is this a no-op - (i.e., all the source bits are extracted)? + if (x.isNop) { + emitTmpDec(node) + { + // A straight assignment. + block((0 until words(node)).map(i => emitWordRef(node, i) + " = " + emitWordRef(source, i))) } - }) - - case x: Clock => - "" - - case x: Bits => - if (x.isInObject && x.inputs.length == 1) { - emitTmpDec(x) + block((0 until words(x)).map(i => emitWordRef(x, i) - + " = " + emitWordRef(x.inputs(0), i))) - } else if (x.inputs.length == 0 && !(x.isTopLevelIO && x.dir == INPUT)) { - emitTmpDec(x) + block("val_t __r = this->__rand_val()" +: - (0 until words(x)).map(i => s"${emitWordRef(x, i)} = __r")) + trunc(x) + } else if (x.isOneBit) { + emitTmpDec(node) + { + // Ensure all the other bits are zero. + if (words(node) > 1) { + if (node.isInObject) { + emitRef(node) + " = 0;\n" + } else { + " memset(" + emitValueAddress(node) + ", 0, sizeof(" + emitRef(node) + "));\n" + } + } else { + "" + } + } + { + if (hi.isLit) { + val value = hi.litValue().toInt + " " + emitLoWordRef(node) + " = (" + emitWordRef(source, value/bpw) + " >> " + (value%bpw) + ") & 1;\n" + } else if (source.needWidth() <= bpw) { + " " + emitLoWordRef(node) + " = (" + emitLoWordRef(source) + " >> " + emitLoWordRef(hi) + ") & 1;\n" + } else { + val inputWord = wordMangle(source, emitLoWordRef(hi) + "/" + bpw) + s"${emitLoWordRef(node)} = ${inputWord} >> (${emitLoWordRef(hi)} % ${bpw}) & 1;\n" + } + } + } else if (x.isStaticWidth) { + emitTmpDec(node) + { + val rsh = lo.litValue().toInt + if (rsh % bpw == 0) { + block((0 until words(node)).map(i => emitWordRef(node, i) + " = " + emitWordRef(source, i + rsh/bpw))) + trunc(node) + } else { + block((0 until words(node)).map(i => emitWordRef(node, i) + + " = " + emitWordRef(source, i + rsh/bpw) + " >> " + + (rsh % bpw) + ( + if (i + rsh/bpw + 1 < words(source)) { + " | " + emitWordRef(source, i + rsh/bpw + 1) + " << " + (bpw - rsh % bpw) + } else { + "" + }))) + trunc(node) + } + } } else { - "" + // Use the low level extract code. + val nw = words(node) + emitTmpDec(node) + ";\n " + " bit_word_funs<" + nw + ">::extract(" + emitValueAddress(node) + ", " + emitValueAddress(source) + ", " + emitRef(hi) + ", " + emitRef(lo) + ");\n" } + case x: Clock => "" + + case x: Bits if x.isInObject && x.inputs.length == 1 => { + emitTmpDec(x) + block((0 until words(x)).map(i => emitWordRef(x, i) + + " = " + emitWordRef(x.inputs(0), i))) + } + case x: Bits if x.inputs.length == 0 && !(x.isTopLevelIO && x.dir == INPUT) => + emitTmpDec(x) + block("val_t __r = this->__rand_val()" +: + (0 until words(x)).map(i => s"${emitWordRef(x, i)} = __r")) + trunc(x) + case m: MemRead => emitTmpDec(m) + block((0 until words(m)).map(i => emitWordRef(m, i) + " = " + emitRef(m.mem) + ".get(" + emitLoWordRef(m.addr) + ", " @@ -565,11 +580,12 @@ class CppBackend extends Backend { + i + ")")) case a: Assert => - val cond = emitLoWordRef(a.cond) + - (if (emitRef(a.cond) == "reset" || emitRef(a.cond) == Driver.implicitReset.name) "" - else " || " + Driver.implicitReset.name + ".lo_word()") + val cond = + if (emitRef(a.cond) == "reset" || emitRef(a.cond) == Driver.implicitReset.name) emitLoWordRef(a.cond) + else s"${emitLoWordRef(a.cond)} || !assert_fire || ${Driver.implicitReset.name}.lo_word()" if (!Driver.isAssert) "" - else " ASSERT(" + cond + ", " + CString(a.message) + ");\n" + else if (Driver.isAssertWarn) s" WARN(${cond}, ${CString(a.message)});\n" + else s" ASSERT(${cond}, ${CString(a.message)});\n" case s: Sprintf => ("#if __cplusplus >= 201103L\n" @@ -578,17 +594,9 @@ class CppBackend extends Backend { + ");\n" + "#endif\n") - case l: Literal => + case l: Literal if !l.isInObject && words(l) > 1 => // Have we already allocated this literal in the main class definition? - if (!l.isInObject) { - if (words(l) == 1) { - "" - } else { - s" val_t T${l.emitIndex}[] = {" + (0 until words(l)).map(emitWordRef(l, _)).reduce(_+", "+_) + "};\n" - } - } else { - "" - } + s" val_t T${l.emitIndex}[] = {" + (0 until words(l)).map(emitWordRef(l, _)).reduce(_ + ", " + _) + "};\n" case _ => "" @@ -606,7 +614,7 @@ class CppBackend extends Backend { val useShadow = if (allocateOnlyNeededShadowRegisters) { needShadow.contains(reg) } else { - next.isReg + next match { case _: Delay => true case _ => false } } if (useShadow) { emitRef(reg) + "__shadow" @@ -629,12 +637,19 @@ class CppBackend extends Backend { def emitInit(node: Node): String = { node match { - case x: Clock => - if (x.srcClock != null) { - " " + emitRef(node) + " = " + emitRef(x.srcClock) + x.initStr + - " " + emitRef(node) + "_cnt = " + emitRef(node) + ";\n" - } else - "" + case x: Clock => List( + x.srcClock match { + case None => + s" ${emitRef(node)}.len = ${x.period.round};\n" + case Some(src) => + s" ${emitRef(node)}.len = ${emitRef(src)}.len ${ + if (src.period > x.period) + "/ " + (src.period / x.period).round else + "* " + (x.period / src.period).round + };\n" + }, + s" ${emitRef(node)}.cnt = 0;\n", + s" ${emitRef(node)}.values[0] = 0;\n") mkString "" case x: Reg => s" ${emitRef(node)}.randomize(&__rand_seed);\n" @@ -654,11 +669,9 @@ class CppBackend extends Backend { } res.toString - case u: Bits => - if (u.driveRand && u.isInObject) + case u: Bits if u.driveRand && u.isInObject => s" ${emitRef(node)}.randomize(&__rand_seed);\n" - else - "" + case _ => "" } @@ -669,6 +682,8 @@ class CppBackend extends Backend { case reg: Reg => { potentialShadowRegisters += 1 val allocateShadow = !allocateOnlyNeededShadowRegisters || needShadow.contains(reg) + // If this isn't a shadow register, we've determined we don't need a shadow register + // for this register, so we don't need to initialize it. if (allocateShadow) { allocatedShadow += reg val storagePrefix = if (shadowRegisterInObject) { @@ -676,9 +691,9 @@ class CppBackend extends Backend { } else { " dat_t<" + node.needWidth() + ">" } - s"${shadowPrefix} ${storagePrefix} ${emitRef(reg)}__shadow = ${emitRef(reg.next)};\n" + s" ${storagePrefix} ${emitRef(reg)}__shadow = ${emitRef(reg.next)};\n" } else { - s" ${emitRef(reg)} = ${emitRef(reg.next)};\n" + "" } } @@ -694,101 +709,76 @@ class CppBackend extends Backend { } // If we write a register node before we use its inputs, we need to shadow it. - def determineRequiredShadowRegisters(node: Node) { + protected[this] def determineRequiredShadowRegisters(node: Node) { node match { case reg: Reg => { regWritten += node - if (reg.next.isReg) { - needShadow += node + reg.next match { + case _: Delay => needShadow += node + case _ => } } - case _ => {} + case _ => } for (n <- node.inputs if regWritten.contains(n)) { needShadow += n } } - def clkName (clock: Clock): String = + protected[this] def clkName (clock: Clock): String = (if (clock == Driver.implicitClock) "" else "_" + emitRef(clock)) - def genHarness(c: Module, name: String) { + protected[this] def genHarness(c: Module, name: String) { val n = Driver.appendString(Some(c.name),Driver.chiselConfigClassName) - val harness = createOutputFile(n + "-emulator.cpp"); - harness.write("#include \"" + n + ".h\"\n\n"); + val harness = createOutputFile(n + "-emulator.cpp") + harness.write(s"""#include "${n}.h"\n\n""") if (Driver.clocks.length > 1) { - harness.write("void " + c.name + "_t::setClocks ( std::vector< int > &periods ) {\n"); - var i = 0; - for (clock <- Driver.clocks) { - if (clock.srcClock == null) { - harness.write(" " + emitRef(clock) + " = periods[" + i + "];\n") - harness.write(" " + emitRef(clock) + "_cnt = periods[" + i + "];\n") - i += 1; - } + harness.write(s"void ${c.name}_t::setClocks ( std::vector< int > &periods ) {\n") + (Driver.clocks filter (_.srcClock == None)).zipWithIndex foreach {case (clk, i) => + harness.write(s" ${emitRef(clk)}.len = periods[${i}];\n") + harness.write(s" ${emitRef(clk)}.cnt = periods[${i}];\n") } - harness.write("}\n\n"); + harness.write("}\n\n") } - harness.write(s"""int main (int argc, char* argv[]) {\n"""); - harness.write(s""" ${name}_t* module = new ${name}_t();\n"""); - harness.write(s""" module->init();\n"""); - harness.write(s""" ${name}_api_t* api = new ${name}_api_t();\n"""); - harness.write(s""" api->init(module);\n"""); + harness.write(s"""int main (int argc, char* argv[]) {\n""") + harness.write(s""" ${name}_t module;\n""") + harness.write(s""" ${name}_api_t api(&module);\n""") + harness.write(s""" module.init();\n""") + harness.write(s""" api.init_sim_data();\n""") + harness.write(s""" api.init_channels();\n""") + harness.write(s""" std::vector args(argv+1, argv+argc);\n""") + harness.write(s""" std::string vcdfile = "${Driver.targetDir}/${name}.vcd";\n""") + harness.write(s""" std::vector::const_iterator it;\n""") + harness.write(s""" for (it = args.begin() ; it != args.end() ; it++) {\n""") + harness.write(s""" if (it->find("+vcdfile=") == 0) vcdfile = it->c_str()+9;\n""") + harness.write(s""" }\n""") if (Driver.isVCD) { - val basedir = ensureDir(Driver.targetDir) - harness.write(s""" FILE *f = fopen("${basedir}${name}.vcd", "w");\n"""); - } else { - harness.write(s""" FILE *f = NULL;\n"""); - } - if (Driver.dumpTestInput) { - harness.write(s""" FILE *tee = fopen("${name}.stdin", "w");\n"""); + harness.write(s""" FILE *f = fopen(vcdfile.c_str(), "w");\n""") } else { - harness.write(s""" FILE *tee = NULL;"""); + harness.write(s""" FILE *f = NULL;\n""") } - harness.write(s""" module->set_dumpfile(f);\n"""); - harness.write(s""" api->set_teefile(tee);\n"""); - harness.write(s""" api->read_eval_print_loop();\n"""); - harness.write(s""" if (f) fclose(f);\n"""); - harness.write(s""" if (tee) fclose(tee);\n"""); - harness.write(s"""}\n"""); - harness.close(); + harness.write(s""" module.set_dumpfile(f);\n""") + Driver.clocks foreach {clk => + harness write s" module.${emitRef(clk)}.cnt = module.${emitRef(clk)}.len;\n"} + harness.write(s""" while(!api.exit()) api.tick();\n""") + harness.write(s""" if (f) fclose(f);\n""") + harness.write(s"""}\n""") + harness.close() } - override def compile(c: Module, flagsIn: String) { - val CXXFLAGS = scala.util.Properties.envOrElse("CXXFLAGS", "" ) - val LDFLAGS = scala.util.Properties.envOrElse("LDFLAGS", "") - val chiselENV = java.lang.System.getenv("CHISEL") - + override def compile(c: Module, flagsIn: Option[String]) { val c11 = if (hasPrintfs) " -std=c++11 " else "" - val cxxFlags = (if (flagsIn == null) CXXFLAGS else flagsIn) + c11 - val cppFlags = scala.util.Properties.envOrElse("CPPFLAGS", "") + " -I../ -I" + chiselENV + "/csrc/" - val allFlags = cppFlags + " " + cxxFlags - val dir = Driver.targetDir + "/" - val CXX = scala.util.Properties.envOrElse("CXX", "g++" ) + val cxxFlags = (flagsIn getOrElse CXXFLAGS) + c11 + val cppFlags = CPPFLAGS + " -I../ -I" + chiselENV + "/csrc/" + val allFlags = List(cppFlags, cxxFlags).mkString(" ") + val dir = Driver.targetDir val parallelMakeJobs = Driver.parallelMakeJobs - def run(cmd: String) { - val bashCmd = Seq("bash", "-c", cmd) - val c = bashCmd.! - ChiselError.info(cmd + " RET " + c) - } - def linkOne(name: String) { - val ac = CXX + " " + LDFLAGS + " -o " + dir + name + " " + dir + name + ".o " + dir + name + "-emulator.o" - run(ac) - } - def linkMany(name: String, objects: Seq[String]) { - val ac = CXX + " " + LDFLAGS + " -o " + dir + name + " " + objects.map(dir + _ + ".o ").mkString(" ") + dir + name + "-emulator.o" - run(ac) - } - def cc(name: String, flags: String = allFlags) { - val cmd = CXX + " -c -o " + dir + name + ".o " + flags + " " + dir + name + ".cpp" - run(cmd) - } - def make(args: String) { // We explicitly unset CPPFLAGS and CXXFLAGS so the values // set in the Makefile will take effect. val cmd = "unset CPPFLAGS CXXFLAGS; make " + args - run(cmd) + if (!run(cmd)) throwException("make failed...") } def editToTarget(filename: String, replacements: HashMap[String, String]) = { @@ -818,9 +808,6 @@ class CppBackend extends Backend { } // Compile all the unoptimized files at a (possibly) lower level of optimization. - if (cloneCompiledO0) { - onceOnlyFiles += cloneFile - } // Set the default optimization levels. var optim0 = "-O0" var optim1 = "-O1" @@ -840,6 +827,8 @@ class CppBackend extends Backend { } val n = Driver.appendString(Some(c.name),Driver.chiselConfigClassName) + // Ensure onceOnlyFiles count as unoptimized. + unoptimizedFiles ++= onceOnlyFiles // Are we compiling multiple cpp files? if (compileMultipleCppFiles) { // Are we using a Makefile template and parallel makes? @@ -873,15 +862,15 @@ class CppBackend extends Backend { make("-C " + Driver.targetDir + " " + nJobs) } else { // No make. Compile everything discretely. - cc(n + "-emulator") + cc(dir, n + "-emulator", allFlags) // We should have unoptimized files. assert(unoptimizedFiles.size != 0 || onceOnlyFiles.size != 0, - "no unoptmized files to compile for '--compileMultipleCppFiles'") + ChiselError.error("Internal Error: no unoptmized files to compile for '--compileMultipleCppFiles'")) // Compile the O0 files. - onceOnlyFiles.map(cc(_, allFlags + " " + optim0)) + onceOnlyFiles.map(cc(dir, _, allFlags + " " + optim0)) // Compile the remaining (O1) files. - unoptimizedFiles.filter( ! onceOnlyFiles.contains(_) ).map(cc(_, allFlags + " " + optim1)) + unoptimizedFiles.filter( ! onceOnlyFiles.contains(_) ).map(cc(dir, _, allFlags + " " + optim1)) val objects: ArrayBuffer[String] = new ArrayBuffer(maxFiles) // Compile the remainder at the specified optimization level. for (f <- 0 until maxFiles) { @@ -889,100 +878,20 @@ class CppBackend extends Backend { // If we've already compiled this file, don't do it again, // but do add it to the list of objects to be linked. if (!unoptimizedFiles.contains(basename)) { - cc(basename, allFlags + " " + optim2) + cc(dir, basename, allFlags + " " + optim2) } - objects += basename + objects += basename + ".o" } - linkMany(n, objects) + objects += (n + "-emulator.o") + link(dir, n, objects) } } else { - cc(n + "-emulator") - cc(n) - linkOne(n) + cc(dir, n + "-emulator", allFlags) + cc(dir, n, allFlags) + link(dir, n, List(n, n + "-emulator") map (_ + ".o")) } } - def emitDefLos(c: Module): String = { - var res = ""; - for ((n, w) <- c.wires) { - w match { - case io: Bits => - if (io.dir == INPUT) { - res += " " + emitRef(c) + "->" + n + " = " + emitRef(io.inputs(0)) + ";\n"; - } - }; - } - res += emitRef(c) + "->clock_lo(reset);\n"; - for ((n, w) <- c.wires) { - w match { - case io: Bits => - if (io.dir == OUTPUT) { - res += " " + emitRef(io.consumers.head) + " = " + emitRef(c) + "->" + n + ";\n"; - } - }; - } - res - } - - def emitDefHis(c: Module): String = { - var res = emitRef(c) + "->clock_hi(reset);\n"; - res - } - - /** Ensures each node such that it has a unique name accross the whole - hierarchy by prefixing its name by a component path (except for "reset" - and all nodes in *c*). */ - def renameNodes(nodes: ArrayBuffer[Node]) { - val comp = Driver.topComponent - for (m <- nodes) { - m match { - case _: Literal => - case _ if m.named && (m != comp.defaultResetPin) && m.component != null => - // only modify name if it is not the reset signal or not in top component - if (m.name != "reset" || m.name != Driver.implicitReset.name || m.component != comp) - m.name = m.component.getPathName + "__" + m.name - case _ => - } - } - } - - /** - * Takes a list of nodes and returns a list of tuples with the names attached. - * Used to preserve original node names before the rename process. - */ - def generateNodeMapping = { - val mappings = new ArrayBuffer[(String, Node)] - for (m <- Driver.orderedNodes) { - if (m.chiselName != "") { - val mapping = (m.chiselName, m) - mappings += mapping - } - } - mappings - } - - def emitMapping(mapping: Tuple2[String, Node]): String = { - val (name, node) = mapping - node match { - case x: Binding => - "" - case x: Literal => - "" - case x: Reg => - s""" dat_table["${name}"] = new dat_api<${node.needWidth()}>(&mod_typed->${emitRef(node)}, "${name}", "");\n""" - case m: Mem[_] => - s""" mem_table["${name}"] = new mem_api<${m.needWidth()}, ${m.n}>(&mod_typed->${emitRef(node)}, "${name}", "");\n""" - case r: ROMData => - s""" mem_table["${name}"] = new mem_api<${r.needWidth()}, ${r.n}>(&mod_typed->${emitRef(node)}, "${name}", "");\n""" - case c: Clock => - s""" dat_table["${name}"] = new dat_api<${node.needWidth()}>(&mod_typed->${emitRef(node)}, "${name}", "");\n""" - case _ => - s""" dat_table["${name}"] = new dat_api<${node.needWidth()}>(&mod_typed->${emitRef(node)}, "${name}", "");\n""" - } - } - - def backendElaborate(c: Module) = super.elaborate(c) - override def elaborate(c: Module): Unit = { val minimumLinesPerFile = Driver.minimumLinesPerFile val partitionIslands = Driver.partitionIslands @@ -992,9 +901,13 @@ class CppBackend extends Backend { // Generate CPP files val out_cpps = ArrayBuffer[CppFile]() - val all_cpp = new StringBuilder - def cppFileSuffix = "-" + out_cpps.length + def cppFileSuffix: String = if (compileMultipleCppFiles) { + "-" + out_cpps.length + } else { + "" + } + class CppFile(val suffix: String = cppFileSuffix) { var lines = 0 var done = false @@ -1017,9 +930,6 @@ class CppBackend extends Backend { done = true fileWriter.close() } - def advance() { - this.done = true - } } // Define some classes to help us deal with C++ methods. @@ -1034,7 +944,7 @@ class CppBackend extends Backend { val genCall = "%s(%s);\n".format(name.name, callArgs) val prototype = "%s %s( %s );\n".format(name.ctype, name.name, argumentList) } - + // Split a large method up into a series of calls to smaller methods. // We assume the following: // - all state is maintained in the class object (there is no local state @@ -1060,15 +970,14 @@ class CppBackend extends Backend { } def addString(s: String) { - if (s == "") { - return - } - val lines = s.count(_ == '\n') - if (maxLines > 0 && lines + bodyLines > maxLines) { - newBody() + if (s != "") { + val lines = s.count(_ == '\n') + if (maxLines > 0 && lines + bodyLines > maxLines) { + newBody() + } + body.append(s) + bodyLines += lines } - body.append(s) - bodyLines += lines } def genCalls() { var offset = 0 @@ -1111,41 +1020,95 @@ class CppBackend extends Backend { bodycalls.result } } + + // This is the opposite of LineLimitedMethods. + // It collects output until a threshold is reached. + class CoalesceMethods(limit: Int) { + var accumlation = 0 + var accumlatedMethodHead = "" + var accumlatedMethodTail = "" + val separateMethods = ArrayBuffer[CMethod]() + + def append(methodDefinition: CMethod) { + val methodBody = methodDefinition.body.toString + val nLinesApprox = methodBody.count(_ == '\n') + + def newMethod() { + accumlation = 0 + accumlatedMethodHead = methodDefinition.head + accumlatedMethodTail = methodDefinition.tail + separateMethods.append(methodDefinition) + createCppFile() + writeCppFile(accumlatedMethodHead) + } + + // Are we currently accumulating a method? + if (accumlatedMethodHead == "") { + // We are now. + newMethod() + } + // Can we just merge this method in with the previous one? + if (accumlation + nLinesApprox > limit) { + // No. Time for a new method. + // First, close off any accumulated method .. + if (accumlation > 0) { + writeCppFile(accumlatedMethodTail) + // ... and start a new one. + newMethod() + } + } + writeCppFile(methodBody) + accumlation += nLinesApprox + } + + def done() { + // First, close off any accumulated method. + if (accumlation > 0) { + writeCppFile(accumlatedMethodTail) + } + } + } + def createCppFile(suffix: String = cppFileSuffix) { // If we're trying to coalesce cpp files (minimumLinesPerFile > 0), - // don't actually create a new file unless we've hit the line limit. - if ((out_cpps.size > 0) && (minimumLinesPerFile == 0 || out_cpps.last.lines < minimumLinesPerFile) && !out_cpps.last.done) { + // don't actually create a new file unless the current file has been closed or we've hit the line limit. + if ((out_cpps.size > 0) && (!compileMultipleCppFiles || (!out_cpps.last.done && out_cpps.last.lines < minimumLinesPerFile)) ) { out_cpps.last.write("\n\n") } else { + // If the current file hasn't been closed, do so now. + if (out_cpps.size > 0 && !out_cpps.last.done) { + out_cpps.last.close() + } out_cpps += new CppFile(suffix) println("CppBackend: createCppFile " + out_cpps.last.name) } } def writeCppFile(s: String) { out_cpps.last.write(s) - if (! suppressMonolithicCppFile) { - all_cpp.append(s) - } } + + // If we're generating multiple cpp files, now is a good time to advance to the next. def advanceCppFile() { - out_cpps.last.advance() + if (compileMultipleCppFiles) { + out_cpps.last.close() + } } // Generate header file - def genHeader(vcd: Backend, islands: Array[Island], nInitMethods: Int, nSetCircuitMethods: Int, nDumpInitMethods: Int, nDumpMethods: Int, nInitMappingTableMethods: Int) { + def genHeader(vcd: Backend, islands: Array[Island], nInitMethods: Int, nDumpInitMethods: Int, nDumpMethods: Int, nSimMethods: Int) { val n = Driver.appendString(Some(c.name),Driver.chiselConfigClassName) - val out_h = createOutputFile(n + ".h"); - out_h.write("#ifndef __" + c.name + "__\n"); - out_h.write("#define __" + c.name + "__\n\n"); - out_h.write("#include \"emulator.h\"\n\n"); + val out_h = createOutputFile(n + ".h") + out_h.write("#ifndef __" + c.name + "__\n") + out_h.write("#define __" + c.name + "__\n\n") + out_h.write("#include \"emulator.h\"\n\n") // Generate module headers - out_h.write("class " + c.name + "_t : public mod_t {\n"); - out_h.write(" private:\n"); - out_h.write(" val_t __rand_seed;\n"); - out_h.write(" void __srand(val_t seed) { __rand_seed = seed; }\n"); - out_h.write(" val_t __rand_val() { return ::__rand_val(&__rand_seed); }\n"); - out_h.write(" public:\n"); + out_h.write("class " + c.name + "_t : public mod_t {\n") + out_h.write(" private:\n") + out_h.write(" val_t __rand_seed;\n") + out_h.write(" void __srand(val_t seed) { __rand_seed = seed; }\n") + out_h.write(" val_t __rand_val() { return ::__rand_val(&__rand_seed); }\n") + out_h.write(" public:\n") def headerOrderFunc(a: Node, b: Node) = { // pack smaller objects at start of header for better locality @@ -1153,24 +1116,36 @@ class CppBackend extends Backend { val bMem = b.isInstanceOf[Mem[_]] || b.isInstanceOf[ROMData] aMem < bMem || aMem == bMem && a.needWidth() < b.needWidth() } - for (m <- Driver.orderedNodes.filter(_.isInObject).sortWith(headerOrderFunc)) + // If we have a constant pool, output its definitions. + for (((_, _),l) <- constantPool) { + out_h.write(s" static const val_t T${l.emitIndex}[${words(l)}];\n") + } + // Header declarations should be unique, add a simple check + for (m <- Driver.orderedNodes.filter(_.isInObject).sortWith(headerOrderFunc)) { + assertUnique(emitDec(m), "redeclaration in header for nodes") out_h.write(emitDec(m)) - for (m <- Driver.orderedNodes.filter(_.isInVCD).sortWith(headerOrderFunc)) + } + for (m <- Driver.orderedNodes.filter(_.isInVCD).sortWith(headerOrderFunc)){ + assertUnique(vcd.emitDec(m), "redeclaration in header for vcd") out_h.write(vcd.emitDec(m)) - for (clock <- Driver.clocks) + } + for (clock <- Driver.clocks) { + assertUnique(emitDec(clock), "redeclaration in header for clock") out_h.write(emitDec(clock)) + } + if (Driver.isVCD) out_h.write(" dat_t<1> reset__prev;\n") // also records reset - out_h.write("\n"); + out_h.write("\n") // If we're generating multiple init methods, wrap them in private/public. if (nInitMethods > 1) { - out_h.write(" private:\n"); + out_h.write(" private:\n") for (i <- 0 until nInitMethods - 1) { - out_h.write(" void init_" + i + " ( );\n"); + out_h.write(" void init_" + i + " ( );\n") } - out_h.write(" public:\n"); + out_h.write(" public:\n") } - out_h.write(" void init ( val_t rand_init = 0 );\n"); + out_h.write(" void init ( val_t rand_init = 0 );\n") // Do we have already generated clock prototypes? if (clockPrototypes.length > 0) { @@ -1178,90 +1153,90 @@ class CppBackend extends Backend { for (proto <- clockPrototypes) { out_h.write(" " + proto) } - out_h.write(" public:\n"); + out_h.write(" public:\n") } - for ( clock <- Driver.clocks) { + for (clock <- Driver.clocks) { val clockNameStr = clkName(clock).toString() - out_h.write(" void clock_lo" + clockNameStr + " ( dat_t<1> reset );\n") - out_h.write(" void clock_hi" + clockNameStr + " ( dat_t<1> reset );\n") + out_h.write(s" void clock_lo${clockNameStr} ( dat_t<1> reset, bool assert_fire=true );\n") + out_h.write(s" void clock_hi${clockNameStr} ( dat_t<1> reset );\n") } out_h.write(" int clock ( dat_t<1> reset );\n") if (Driver.clocks.length > 1) { out_h.write(" void setClocks ( std::vector< int >& periods );\n") } - out_h.write(" mod_t* clone();\n"); - - // If we're generating multiple set_circuit methods, wrap them in private/public. - if (nSetCircuitMethods > 1) { - out_h.write(" private:\n"); - for (i <- 0 until nSetCircuitMethods - 1) { - out_h.write(" void set_circuit_from_" + i + " ( " + c.name + "_t* mod_typed );\n"); - } - out_h.write(" public:\n"); - } - out_h.write(" bool set_circuit_from(mod_t* src);\n"); - // For backwards compatibility, output both stream and FILE-based code. - out_h.write(" void print ( FILE* f );\n"); - out_h.write(" void print ( std::ostream& s );\n"); + // For backwards compatibility, output both stream and FILE-based code. + out_h.write(" void print ( FILE* f );\n") + out_h.write(" void print ( std::ostream& s );\n") // If we're generating multiple dump methods, wrap them in private/public. if (nDumpMethods > 1) { - out_h.write(" private:\n"); + out_h.write(" private:\n") for (i <- 0 until nDumpMethods - 1) { - out_h.write(" void dump_" + i + " ( FILE* f );\n"); + out_h.write(" void dump_" + i + " ( FILE* f, val_t t, dat_t<1> reset);\n") } - out_h.write(" public:\n"); + out_h.write(" public:\n") } - out_h.write(" void dump ( FILE* f, int t );\n"); + out_h.write(" void dump ( FILE* f, val_t t, dat_t<1> reset=LIT<1>(0) );\n") // If we're generating multiple dump_init methods, wrap them in private/public. if (nDumpInitMethods > 1) { out_h.write(" private:\n"); for (i <- 0 until nDumpInitMethods - 1) { - out_h.write(" void dump_init_" + i + " ( FILE* f );\n"); + out_h.write(" void dump_init_" + i + " ( FILE* f );\n") } - out_h.write(" public:\n"); + out_h.write(" public:\n") } - out_h.write(" void dump_init ( FILE* f );\n"); + out_h.write(" void dump_init ( FILE* f );\n") // All done with the class definition. Close it off. - out_h.write("\n};\n\n"); - out_h.write(Params.toCxxStringParams); - - // Generate API headers - out_h.write(s"class ${c.name}_api_t : public mod_api_t {\n"); - // If we're generating multiple init_mapping_table( methods, wrap them in private/public. - if (nInitMappingTableMethods > 1) { - out_h.write(" private:\n"); - for (i <- 0 until nInitMappingTableMethods - 1) { - out_h.write(" void init_mapping_table_" + i + " ( " + c.name + "_t* mod_typed );\n"); + out_h.write("\n};\n\n") + out_h.write(Params.toCxxStringParams) + + if (Driver.isGenHarness) { + out_h.write("#include \"emul_api.h\"\n") + out_h.write("class " + c.name + "_api_t : public emul_api_t {\n") + out_h.write(" public:\n") + out_h.write(" %s_api_t(mod_t* m) : emul_api_t(m) { }\n".format(c.name)) + if (nSimMethods > 1) { + out_h.write(" private:\n") + for (i <- 0 until nSimMethods - 1) { + out_h.write(" void init_sim_data_" + i + "(" + c.name + "_t* mod );\n") + } + out_h.write(" public:\n") } - out_h.write(" public:\n"); + out_h.write(" void init_sim_data();\n") + out_h.write("};") } - out_h.write(s" void init_mapping_table();\n"); - out_h.write(s"};\n\n"); - out_h.write("\n\n#endif\n"); out_h.close(); } def genInitMethod(): Int = { - createCppFile() // If we're putting literals in the class as static const's, // generate the code to initialize them here. if (multiwordLiteralInObject) { + // The ROM init code may generate multi-word constants. + // Ensure they're in the constant pool if we're generating one. + // NOTE: We call emitInit() only for its side-effects (allocating constants to the constant pool if the latter is enabled). + // We throw away the generated intialization strings created during this invocation. + // We'll accumulate and output them later (after the constants have been assigned their values). + def collectConstants(): Unit = { + Driver.orderedNodes foreach (emitInit(_)) + } // Emit code to assign static const literals. def emitConstAssignment(l: Literal): String = { - s"const val_t ${c.name}_t::T${l.emitIndex}[] = {" + (0 until words(l)).map(emitWordRef(l, _)).reduce(_+", "+_) + "};\n" + s"const val_t ${c.name}_t::T${l.emitIndex}[] = {" + (0 until words(l)).map(emitLitVal(l, _)).reduce(_ + ", " + _) + "};\n" } var wroteAssignments = false // Get the literals from the constant pool (if we're using one) ... if (coalesceConstants) { - for ((v,l) <- constantPool) { + // Ensure any constants we will use are accounted for. + collectConstants() + for (((v,w),l) <- constantPool) { writeCppFile(emitConstAssignment(l)) wroteAssignments = true } @@ -1279,12 +1254,8 @@ class CppBackend extends Backend { } val method = CMethod(CTypedName("void", "init"), Array[CTypedName](CTypedName("val_t", "rand_init"))) val llm = new LineLimitedMethod(method, " this->__srand(rand_init);\n") - for (m <- Driver.orderedNodes) { - llm.addString(emitInit(m)) - } - for (clock <- Driver.clocks) { - llm.addString(emitInit(clock)) - } + Driver.orderedNodes foreach (llm addString emitInit(_)) + Driver.clocks foreach (llm addString emitInit(_)) llm.done() val nMethods = llm.bodies.length writeCppFile(llm.getBodies) @@ -1292,7 +1263,6 @@ class CppBackend extends Backend { } def genClockMethod() { - createCppFile() writeCppFile("int " + c.name + "_t::clock ( dat_t<1> reset ) {\n") writeCppFile(" uint32_t min = ((uint32_t)1<<31)-1;\n") @@ -1303,66 +1273,28 @@ class CppBackend extends Backend { } for (clock <- Driver.clocks) { - writeCppFile(" if (" + emitRef(clock) + "_cnt < min) min = " + emitRef(clock) +"_cnt;\n") + writeCppFile(" if (" + emitRef(clock) + ".cnt < min) min = " + emitRef(clock) + ".cnt;\n") } for (clock <- Driver.clocks) { - writeCppFile(" " + emitRef(clock) + "_cnt-=min;\n") + writeCppFile(" " + emitRef(clock) + ".cnt-=min;\n") } for (clock <- Driver.clocks) { - writeCppFile(" if (" + emitRef(clock) + "_cnt == 0) clock_hi" + clkName(clock) + "( reset );\n") + writeCppFile(" if (" + emitRef(clock) + ".cnt == 0) clock_lo" + clkName(clock) + "( reset );\n") } + writeCppFile(" if (!reset.to_bool()) print( std::cerr );\n") + if (Driver.isVCD) writeCppFile(" mod_t::dump( reset );\n") for (clock <- Driver.clocks) { - writeCppFile(" if (" + emitRef(clock) + "_cnt == 0) clock_lo" + clkName(clock) + "( reset );\n") + writeCppFile(" if (" + emitRef(clock) + ".cnt == 0) clock_hi" + clkName(clock) + "( reset );\n") } for (clock <- Driver.clocks) { - writeCppFile(" if (" + emitRef(clock) + "_cnt == 0) " + emitRef(clock) + "_cnt = " + - emitRef(clock) + ";\n") + writeCppFile(" if (" + emitRef(clock) + ".cnt == 0) " + emitRef(clock) + ".cnt = " + + emitRef(clock) + ".len;\n") } writeCppFile(" return min;\n") writeCppFile("}\n") } - def genCloneMethod() { - createCppFile() - writeCppFile(s"mod_t* ${c.name}_t::clone() {\n") - writeCppFile(s" mod_t* cloned = new ${c.name}_t(*this);\n") - writeCppFile(s" return cloned;\n") - writeCppFile(s"}\n") - - // Make a special note of the clone file. We may want to compile it -O0. - cloneFile = out_cpps.last.name.dropRight(".cpp".length()) - } - - def genSetCircuitFromMethod(): Int = { - createCppFile() - val codePrefix = s" ${c.name}_t* mod_typed = dynamic_cast<${c.name}_t*>(src);\n" + - s" assert(mod_typed);\n" - val codeSuffix = " return true;\n" - val method = CMethod(CTypedName("bool", "set_circuit_from"), Array[CTypedName](CTypedName("mod_t*", "src"))) - val llm = new LineLimitedMethod(method, codePrefix, codeSuffix, Array[CTypedName](CTypedName(s"${c.name}_t*", "mod_typed"))) - for (m <- Driver.orderedNodes) { - if(m.name != "reset" && m.name != Driver.implicitReset.name && m.isInObject) { - // Skip the circuit assign if this is a literal and we're - // including literals in the objet. - // The literals are declared as "static const" and will be - // initialized elsewhere. - if (!(multiwordLiteralInObject && m.isInstanceOf[Literal])) { - llm.addString(emitCircuitAssign("mod_typed->", m)) - } - } - } - for (clock <- Driver.clocks) { - llm.addString(emitCircuitAssign("mod_typed->", clock)) - } - llm.done() - val nMethods = llm.bodies.length - writeCppFile(llm.getBodies) - nMethods - } - - // For backwards compatibility, output both stream and FILE-based code. def genPrintMethod() { - createCppFile() writeCppFile("void " + c.name + "_t::print ( FILE* f ) {\n") for (cc <- Driver.components; p <- cc.printfs) { hasPrintfs = true @@ -1395,7 +1327,6 @@ class CppBackend extends Backend { } def genDumpInitMethod(vcd: VcdBackend): Int = { - createCppFile() val method = CMethod(CTypedName("void", "dump_init"), Array[CTypedName](CTypedName("FILE*", "f"))) val llm = new LineLimitedMethod(method, "", "", Array[CTypedName](CTypedName("FILE*", "f"))) vcd.dumpVCDInit(llm.addString) @@ -1406,16 +1337,17 @@ class CppBackend extends Backend { } def genDumpMethod(vcd: VcdBackend): Int = { - val method = CMethod(CTypedName("void", "dump"), Array[CTypedName](CTypedName("FILE*", "f"), CTypedName("int", "t"))) - createCppFile() + val method = CMethod(CTypedName("void", "dump"), + Array[CTypedName](CTypedName("FILE*", "f"), CTypedName("val_t", "t"), CTypedName("dat_t<1>", "reset"))) // Are we actually generating VCD? if (Driver.isVCD) { // Yes. dump is a real method. - val codePrefix = " if (t == 0) return dump_init(f);\n" + - " fprintf(f, \"#%d\\n\", t);\n" + val codePrefix = List( + " if (t == 0L) return dump_init(f);\n", + " fprintf(f, \"#%lu\\n\", t << 1);\n") mkString "" // Are we generating a large dump method with gotos? (i.e., not inline) if (Driver.isVCDinline) { - val llm = new LineLimitedMethod(method, codePrefix, "", Array[CTypedName](CTypedName("FILE*", "f"))) + val llm = new LineLimitedMethod(method, codePrefix, "", Array[CTypedName](CTypedName("FILE*", "f"), CTypedName("val_t", "t"), CTypedName("dat_t<1>", "reset"))) vcd.dumpVCD(llm.addString) llm.done() val nMethods = llm.bodies.length @@ -1435,28 +1367,47 @@ class CppBackend extends Backend { } } - def genInitMappingTableMethod(mappings: ArrayBuffer[Tuple2[String, Node]]): Int = { - createCppFile() - val method = CMethod(CTypedName("void", "init_mapping_table"), Array[CTypedName](), s"${c.name}_api_t") - val codePrefix = s" dat_table.clear();\n" + - s" mem_table.clear();\n" + - s" ${c.name}_t* mod_typed = dynamic_cast<${c.name}_t*>(module);\n" + - s" assert(mod_typed);\n" - val llm = new LineLimitedMethod(method, codePrefix, "", Array[CTypedName](CTypedName(s"${c.name}_t*", "mod_typed"))) - for (m <- mappings) { - if (m._2.name != "reset" && m._2.name != Driver.implicitReset.name && (m._2.isInObject || m._2.isInVCD)) { - llm.addString(emitMapping(m)) - } + def genInitSimDataMethod(c: Module) = { + val method = CMethod(CTypedName("void", "init_sim_data"), Array[CTypedName](), c.name + "_api_t") + val codePrefix = s" sim_data.inputs.clear();\n" + + s" sim_data.outputs.clear();\n" + + s" sim_data.signals.clear();\n" + + s" ${c.name}_t* mod = dynamic_cast<${c.name}_t*>(module);\n" + + s" assert(mod);\n" + val llm = new LineLimitedMethod(method, codePrefix, "", Array[CTypedName](CTypedName(s"${c.name}_t*", "mod"))) + val (inputs, outputs) = c.wires.unzip._2 partition (_.dir == INPUT) + var id = 0 + Driver.orderedNodes.map { + case m: Mem[_] => + Driver.signalMap(m) = id + id += m.n + case node if node.prune || node.driveRand => + case node if node.chiselName != "" && !node.isTopLevelIO && node.isInObject => + Driver.signalMap(node) = id + id += 1 + case _ => } + llm addString (inputs map (in => + " sim_data.inputs.push_back(new dat_api<%d>(&mod->%s));\n".format(in.needWidth, emitRef(in))) mkString "") + llm addString (outputs map (out => + " sim_data.outputs.push_back(new dat_api<%d>(&mod->%s));\n".format(out.needWidth, emitRef(out))) mkString "") + llm addString (Driver.signalMap flatMap { + case (mem: Mem[_], id) => List( + " std::string %s_path = \"%s\";\n".format(emitRef(mem), mem.chiselName), + " for (size_t i = 0 ; i < %d ; i++) {\n".format(mem.n), + " sim_data.signals.push_back(new dat_api<%d>(&mod->%s.contents[i]));\n".format(mem.needWidth, emitRef(mem)), + " sim_data.signal_map[%s_path+\"[\"+itos(i,false)+\"]\"] = %d+i;\n".format(emitRef(mem), id), " }\n") + case (node, id) => List( + " sim_data.signals.push_back(new dat_api<%d>(&mod->%s));\n".format(node.needWidth, emitRef(node)), + " sim_data.signal_map[\"%s\"] = %d;\n".format(node.chiselName, Driver.signalMap(node))) + } mkString "") + llm addString (Driver.clocks map { clk => + " sim_data.clk_map[\"%s\"] = new clk_api(&mod->%s);\n".format(clk.name, clk.name) + } mkString "") + llm.done() val nMethods = llm.bodies.length writeCppFile(llm.getBodies) - - // Add the init_mapping_table file to the list of unoptimized files. - if (compileInitializationUnoptimized) { - val trimLength = ".cpp".length() - unoptimizedFiles += out_cpps.last.name.dropRight(trimLength) - } nMethods } @@ -1470,7 +1421,6 @@ class CppBackend extends Backend { flattenAll // created Driver.orderedNodes ChiselError.checkpoint() - val mappings = generateNodeMapping renameNodes(Driver.orderedNodes) if (Driver.isReportDims) { val (numNodes, maxWidth, maxDepth) = findGraphDims @@ -1501,8 +1451,9 @@ class CppBackend extends Backend { for (clock <- Driver.clocks) { // All clock methods take the same arguments and return void. val clockArgs = Array[CTypedName](CTypedName("dat_t<1>", Driver.implicitReset.name)) + val clockLoArgs = clockArgs :+ CTypedName("bool", "assert_fire") val clockLoName = "clock_lo" + clkName(clock) - val clock_dlo = new CMethod(CTypedName("void", clockLoName), clockArgs) + val clock_dlo = new CMethod(CTypedName("void", clockLoName), clockLoArgs) val clockHiName = "clock_hi" + clkName(clock) val clock_ihi = new CMethod(CTypedName("void", clockHiName), clockArgs) // For simplicity, we define a dummy method for the clock_hi exec code. @@ -1522,7 +1473,7 @@ class CppBackend extends Backend { islandClkCode += ((islandId, new ClockCodeMethods)) } val clockLoName = "clock_lo" + clkName(clock) + "_I_" + islandId - val clock_dlo_I = new CMethod(CTypedName("void", clockLoName), clockArgs) + val clock_dlo_I = new CMethod(CTypedName("void", clockLoName), clockLoArgs) // Unlike the unpartitioned case, we will generate and call separate // initialize and execute clock_hi methods if we're partitioning. val clockIHiName = "clock_ihi" + clkName(clock) + "_I_" + islandId @@ -1534,12 +1485,12 @@ class CppBackend extends Backend { } } - def clock(n: Node) = if (n.clock == null) Driver.implicitClock else n.clock + def clock(n: Node) = n.clock getOrElse Driver.implicitClock def populate() { var nodeCount = 0 def isNodeInIsland(node: Node, island: Island): Boolean = { - return island == null || nodeToIslandArray(node._id).contains(island) + island == null || nodeToIslandArray(node._id).contains(island) } // Return tuple of booleans if we actually added any clock code. @@ -1574,23 +1525,21 @@ class CppBackend extends Backend { // We're generating partitioned islands val addedCode = new Array[Boolean](3) for (m <- Driver.orderedNodes) { - for (island <- islands) { - if (isNodeInIsland(m, island)) { - val islandId = island.islandId - val codeMethods = islandClkCode(islandId) - val addedCodeTuple = addClkDefs(m, codeMethods) - addedCode(0) = addedCodeTuple._1 - addedCode(1) = addedCodeTuple._2 - addedCode(2) = addedCodeTuple._3 - // Update the generation number if we added any code to this island. - for (lohi <- 0 to 2) { - if (addedCode(lohi)) { - // Is this the first time we've added code to this island? - if (islandStarted(lohi)(islandId) == 0) { - islandOrder(lohi)(islandSequence(lohi)) = islandId - islandSequence(lohi) += 1 - islandStarted(lohi)(islandId) = islandSequence(lohi) - } + for (island <- nodeToIslandArray(m._id)) { + val islandId = island.islandId + val codeMethods = islandClkCode(islandId) + val addedCodeTuple = addClkDefs(m, codeMethods) + addedCode(0) = addedCodeTuple._1 + addedCode(1) = addedCodeTuple._2 + addedCode(2) = addedCodeTuple._3 + // Update the generation number if we added any code to this island. + for (lohi <- 0 to 2) { + if (addedCode(lohi)) { + // Is this the first time we've added code to this island? + if (islandStarted(lohi)(islandId) == 0) { + islandOrder(lohi)(islandSequence(lohi)) = islandId + islandSequence(lohi) += 1 + islandStarted(lohi)(islandId) = islandSequence(lohi) } } } @@ -1603,54 +1552,6 @@ class CppBackend extends Backend { } } - // This is the opposite of LineLimitedMethods. - // It collects output until a threshold is reached. - class CoalesceMethods(limit: Int) { - var accumlation = 0 - var accumlatedMethodHead = "" - var accumlatedMethodTail = "" - val separateMethods = ArrayBuffer[CMethod]() - - def append(methodDefinition: CMethod) { - val methodBody = methodDefinition.body.toString - val nLinesApprox = methodBody.count(_ == '\n') - - def newMethod() { - accumlation = 0 - accumlatedMethodHead = methodDefinition.head - accumlatedMethodTail = methodDefinition.tail - separateMethods.append(methodDefinition) - createCppFile() - writeCppFile(accumlatedMethodHead) - } - - // Are we currently accumulating a method? - if (accumlatedMethodHead == "") { - // We are now. - newMethod() - } - // Can we just merge this method in with the previous one? - if (accumlation + nLinesApprox > limit) { - // No. Time for a new method. - // First, close off any accumulated method .. - if (accumlation > 0) { - writeCppFile(accumlatedMethodTail) - // ... and start a new one. - newMethod() - } - } - writeCppFile(methodBody) - accumlation += nLinesApprox - } - - def done() { - // First, close off any accumulated method. - if (accumlation > 0) { - writeCppFile(accumlatedMethodTail) - } - } - } - def outputAllClkDomains() { // Are we generating partitioned islands? if (!partitionIslands) { @@ -1661,10 +1562,11 @@ class CppBackend extends Backend { val clockXHi = clockMethods._3 createCppFile() writeCppFile(clockLo.head + clockLo.body.result + clockLo.tail) + createCppFile() writeCppFile(clockIHi.head + clockIHi.body.result) // Note, we tacitly assume that the clock_hi initialization and execution // code have effectively the same signature and tail. - assert(clockIHi.tail == clockXHi.tail) + assert(clockIHi.tail == clockXHi.tail, ChiselError.error("Internal Error: clockIHi.tail != clockXHi.tail")) writeCppFile(clockXHi.body.result + clockXHi.tail) } } else { @@ -1708,7 +1610,7 @@ class CppBackend extends Backend { // Output the island-specific clock_hi def code val accumulatedClockHiXs = new CoalesceMethods(lineLimitFunctions) - for (islandId <- islandOrder(1) if islandId > 0) { + for (islandId <- islandOrder(2) if islandId > 0) { for (clockHiX <- islandClkCode(islandId).values.map(_._3)) { accumulatedClockHiXs.append(clockHiX) clockHiX.body.clear() // free the memory. @@ -1732,7 +1634,7 @@ class CppBackend extends Backend { } writeCppFile(clock_xhi.tail) } - + // Put the accumulated method definitions where the header // generation code can find them. for( method <- accumulatedClockLos.separateMethods ++ accumulatedClockHiIs.separateMethods ++ accumulatedClockHiXs.separateMethods) { @@ -1742,18 +1644,20 @@ class CppBackend extends Backend { } } - val clkDomains = new ClockDomains - if (Driver.isGenHarness) { - genHarness(c, c.name); + genHarness(c, c.name) + /* Copy the emulator headers into the targetDirectory. */ + copyToTarget("sim_api.h") + copyToTarget("emul_api.h") } if (!Params.space.isEmpty) { - val out_p = createOutputFile(c.name + ".p"); - out_p.write(Params.toDotpStringParams); - out_p.close(); + val out_p = createOutputFile(c.name + ".p") + out_p.write(Params.toDotpStringParams) + out_p.close() } ChiselError.info("populating clock domains") + val clkDomains = new ClockDomains clkDomains.populate() println("CppBackend::elaborate: need " + needShadow.size + ", redundant " + (potentialShadowRegisters - needShadow.size) + " shadow registers") @@ -1767,31 +1671,24 @@ class CppBackend extends Backend { ChiselError.info("generating cpp files") // generate init block + createCppFile() val nInitMethods = genInitMethod() // generate clock(...) method + createCppFile() genClockMethod() - advanceCppFile() - // generate clone() method - genCloneMethod() - - advanceCppFile() - // generate set_circuit_from method - val nSetCircuitFromMethods = genSetCircuitFromMethod() - // generate print(...) method. - // This will probably end up in the same file as the above clone code. + createCppFile() genPrintMethod() - advanceCppFile() + createCppFile() val nDumpInitMethods = genDumpInitMethod(vcd) createCppFile() val nDumpMethods = genDumpMethod(vcd) - out_cpps.foreach(_.fileWriter.flush()) - // If we're compiling initialization methods -O0, add the current files + // If we're compiling initialization methods -O0 or -O1, add the current files // to the unoptimized file list. // We strip off the trailing ".cpp" to facilitate creating both ".cpp" and ".o" files. if (compileInitializationUnoptimized) { @@ -1800,63 +1697,49 @@ class CppBackend extends Backend { } // Ensure we start off in a new file before we start outputting the clock_lo/hi. advanceCppFile() + createCppFile() clkDomains.outputAllClkDomains() - advanceCppFile() // Generate API methods - val nInitMappingTableMethods = genInitMappingTableMethod(mappings) + val nSimMethods = if (Driver.isGenHarness) { + advanceCppFile() + createCppFile() + // If we're compiling initialization methods -O0, add the current file to the unoptimized file list. + // We strip off the trailing ".cpp" to facilitate creating both ".cpp" and ".o" files. + if (compileInitializationUnoptimized) { + val trimLength = ".cpp".length() + onceOnlyFiles += out_cpps.last.name.dropRight(trimLength) + } + genInitSimDataMethod(c) + } else { + 0 + } // Finally, generate the header - once we know how many methods we'll have. - genHeader(vcd, islands, nInitMethods, nSetCircuitFromMethods, nDumpInitMethods, nDumpMethods, nInitMappingTableMethods) + genHeader(vcd, islands, nInitMethods, nDumpInitMethods, nDumpMethods, nSimMethods) maxFiles = out_cpps.length - if (! suppressMonolithicCppFile) { - // We're now going to write the entire contents out to a singe file. - // Make sure it's really a new file. - advanceCppFile() - createCppFile("") - writeCppFile(all_cpp.result) - } out_cpps.foreach(_.close) - all_cpp.clear() out_cpps.clear() - def copyToTarget(filename: String) = { - val resourceStream = getClass().getResourceAsStream("/" + filename) - if( resourceStream != null ) { - val classFile = createOutputFile(filename) - while(resourceStream.available > 0) { - classFile.write(resourceStream.read()) - } - classFile.close() - resourceStream.close() - } else { - println(s"WARNING: Unable to copy '$filename'" ) - } - } - /* Copy the emulator headers into the targetDirectory. */ - copyToTarget("emulator_mod.h") - copyToTarget("emulator_api.h") copyToTarget("emulator.h") } // Return true if we want this node to be included in the main object. // The Driver (and node itself) may also help determine this. - override def isInObject(n: Node): Boolean = { - n match { - // Should we put multiword literals in the object? - case l: Literal if multiwordLiteralInObject && words(n) > 1 => { - multiwordLiterals += l - true - } - // Should we put disconnected inputs in the object (we will generated random values for them) - case b: Bits if unconnectedInputsInObject && b.inputs.length == 0 => { - unconnectedInputs += b - true - } - case _ => false + override def isInObject(n: Node): Boolean = n match { + // Should we put multiword literals in the object? + case l: Literal if multiwordLiteralInObject && words(n) > 1 => { + multiwordLiterals += l + true + } + // Should we put disconnected inputs in the object (we will generated random values for them) + case b: Bits if unconnectedInputsInObject && b.inputs.length == 0 => { + unconnectedInputs += b + true } + case _ => false } } diff --git a/src/main/scala/Data.scala b/src/main/scala/Data.scala index ef1c7668..96f7b005 100644 --- a/src/main/scala/Data.scala +++ b/src/main/scala/Data.scala @@ -1,5 +1,5 @@ /* - Copyright (c) 2011, 2012, 2013, 2014 The Regents of the University of + Copyright (c) 2011 - 2016 The Regents of the University of California (Regents). All Rights Reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: @@ -30,83 +30,103 @@ package Chisel -import Node._ -import ChiselError._ +import scala.util.{Try,Success,Failure} +import java.lang.reflect.Method +/** This trait enforces numerical properties on the data + * such as being able to add, subtract, multiply, divide etc */ abstract trait Num[T <: Data] { - // def << (b: T): T; - // def >> (b: T): T; - def unary_-(): T; - def + (b: T): T; - def * (b: T): T; - def / (b: T): T; - def % (b: T): T; - def - (b: T): T; - def < (b: T): Bool; - def <= (b: T): Bool; - def > (b: T): Bool; - def >= (b: T): Bool; + // def << (b: T): T + // def >> (b: T): T + def unary_-(): T + def + (b: T): T + def * (b: T): T + def / (b: T): T + def % (b: T): T + def - (b: T): T + def < (b: T): Bool + def <= (b: T): Bool + def > (b: T): Bool + def >= (b: T): Bool def min(b: T): T = Mux(this < b, this.asInstanceOf[T], b) def max(b: T): T = Mux(this < b, b, this.asInstanceOf[T]) } -/** *Data* is part of the *Node* Composite Pattern class hierarchy. - It is the root of the type system which includes composites (Bundle, Vec) - and atomic types (UInt, SInt, etc.). +object Data { + implicit def toOption[T <: Data](data: T): Option[T] = Option(data) +} - Instances of Data are meant to help with construction and correctness - of a logic graph. They will trimmed out of the graph before a *Backend* - generates target code. +/** *Data* is part of the *Node* Composite Pattern class hierarchy. + * It is the root of the type system which includes composites (Bundle, Vec) + * and atomic types (UInt, SInt, etc.). + ** + *Instances of Data are meant to help with construction and correctness + *of a logic graph. They will trimmed out of the graph before a *Backend* + *generates target code. */ abstract class Data extends Node { - var comp: proc = null; + var comp: Option[proc] = None // TODO: better name? // Interface required by Vec: def ===[T <: Data](right: T): Bool = { - throw new Exception("=== not defined on " + this.getClass + throwException("=== not defined on " + this.getClass + + " and " + right.getClass) + } + + def =/=[T <: Data](right: T): Bool = { + throwException("=/= not defined on " + this.getClass + " and " + right.getClass) } + /** Try to convert this data to a Bool + * + * @throws ChiselException if the width is not 1*/ def toBool(): Bool = { val gotWidth = this.getWidth() if( gotWidth < 1) { - throw new Exception("unable to automatically convert " + this + " to Bool, convert manually instead") + throwException("unable to automatically convert " + this + " to Bool, convert manually instead") } else if(gotWidth > 1) { - throw new Exception("multi bit signal " + this + " converted to Bool"); + throwException("multi bit signal " + this + " converted to Bool") } - chiselCast(this){Bool()}; + chiselCast(this){Bool()} } - // Interface required by Cat: + /** Interface required by [[Chisel.Cat Cat]] + *is an operator to combine data nodes together */ def ##[T <: Data](right: T): this.type = { - throw new Exception("## not defined on " + this.getClass + " and " + right.getClass) + throwException("## not defined on " + this.getClass + " and " + right.getClass) } - + /** make this node a type node */ def setIsTypeNode { assert(inputs.length > 0, ChiselError.error("Type Node must have an input")) isTypeNode = true - inferWidth = widthOf(0) + inferWidth = Node.widthOf(0) } - def apply(name: String): Data = null + def apply(name: String): Data = null // TODO: neccessary? def flatten: Array[(String, Bits)] - def flip(): this.type = this; - def asInput(): this.type = this; + /** Change INPUTs to OUTPUTs and visa versa */ + def flip(): this.type = this + /** Return this object as an INPUT */ + def asInput(): this.type = this /** Sets the direction (*dir*) of instances derived from Bits to OUTPUT - or recursively sets members of Bundle/Vec to OUTPUT. - Returns this instance with its exact type. + *or recursively sets members of Bundle/Vec to OUTPUT. + * + *@return this instance with its exact type. */ def asOutput(): this.type + /** set this node as directionless */ def asDirectionless(): this.type - def isDirectionless: Boolean = true; + /** check if this node is neither INPUT or OUTPUT */ + def isDirectionless: Boolean = true /** Factory method to create and assign a leaf-type instance out of a subclass - of *Node* instance which we have lost the concrete type. */ + *of *Node* instance which we have lost the concrete type. */ def fromNode(n: Node): this.type = { - val res = this.clone + val res = this.cloneType val packet = res.flatten.reverse.zip(this.flatten.reverse.map(_._2.getWidth)) var ind = 0 for (((name, io), gotWidth) <- packet) { @@ -140,45 +160,120 @@ abstract class Data extends Node { protected def colonEquals(that: Bits): Unit = illegalAssignment(that) protected def colonEquals(that: Bundle): Unit = illegalAssignment(that) - protected def colonEquals[T <: Data](that: Iterable[T]): Unit = illegalAssignment(that) + protected def colonEquals[T <: Data](that: Seq[T]): Unit = illegalAssignment(that) protected def illegalAssignment(that: Any): Unit = ChiselError.error(":= not defined on " + this.getClass + " and " + that.getClass) - override def clone(): this.type = { - try { - val constructor = this.getClass.getConstructors.head - - if(constructor.getParameterTypes.size == 0) { - constructor.newInstance().asInstanceOf[this.type] - } else if(constructor.getParameterTypes.size == 1) { - val paramtype = constructor.getParameterTypes.head - // If only 1 arg and is a Bundle or Module then this is probably the implicit argument - // added by scalac for nested classes and closures. Thus, try faking the constructor - // by not supplying said class or closure (pass null). - // CONSIDER: Don't try to create this - if(classOf[Bundle].isAssignableFrom(paramtype) || classOf[Module].isAssignableFrom(paramtype)){ - constructor.newInstance(null).asInstanceOf[this.type] - } else throw new Exception("Cannot auto-create constructor for ${this.getClass.getName} that requires arguments") + // Chisel3 prep + override def clone(): this.type = this.cloneType() + + def cloneType(): this.type = { + val check = Try(checkClone()) + check match { + case Failure(e) => + e match { + case npe: java.lang.reflect.InvocationTargetException if npe.getCause.isInstanceOf[java.lang.NullPointerException] => + ChiselError.error("Parameterized Bundle " + this.getClass + " needs cloneType method. You are probably using an anonymous Bundle object that captures external state and hence is un-cloneable" + npe) + this + case e: java.lang.Exception => + ChiselError.error("Parameterized Bundle " + this.getClass + " needs cloneType method. " + e) + this + } + // Return something "acceptable" so we can continue. We'll report a failure before finishing. + this + case Success(c) => + c.get.asInstanceOf[this.type] + } + } + + /** Attempt to clone this object. + * @param cloneNames list of potential/allowable cloning methods. We accept more than one for backward compatibility. + * @return a Scala Try. On success a cloned object. On failure a Throwable. + * + * This is called from our generic cloneType() so we need to avoid calling it, or we'll die trying to + * initialize the Try as the stack overflows. + * We use throwQuietException to avoid logging errors (leaving it up to our caller), in order to support + * compatibility checks. + */ + private[Chisel] def checkClone(cloneNames: Array[String] = Array("cloneType", "clone")): Try[this.type] = { + val clazz = this.getClass + + def getCloneMethod(c: Class[_]): Option[java.lang.reflect.Method] = { + def chooseBestClone(methods: Array[Method]): Option[Method] = { + // Avoid our method, otherwise we'll end up infinitely recursing. + val myMethods = methods.filter(m => m.getDeclaringClass() != classOf[Chisel.Data]) + if (myMethods.nonEmpty) { + val (cloneTypeMethods, otherCloneMethods) = myMethods.partition { x => x.getName() == "cloneType" } + if (cloneTypeMethods.nonEmpty) { + Some(cloneTypeMethods.last) // We tacitly assume that the "last" method is the "highest" + } else if (otherCloneMethods.nonEmpty) { + Some(otherCloneMethods.last) // We tacitly assume that the "last" method is the "highest" + } else { + None + } + } else { + None + } + } + val methods = c.getMethods.filter(m => cloneNames.contains(m.getName()) && m.getParameterTypes.size == 0) + if (methods.size > 0) { + chooseBestClone(methods) } else { - throw new Exception(s"Cannot auto-create constructor for ${this.getClass.getName} that requires arguments") + None } + } - } catch { - case npe: java.lang.reflect.InvocationTargetException if npe.getCause.isInstanceOf[java.lang.NullPointerException] => - throwException("Parameterized Bundle " + this.getClass + " needs clone method. You are probably using an anonymous Bundle object that captures external state and hence is un-cloneable", npe) - case e: java.lang.Exception => - throwException("Parameterized Bundle " + this.getClass + " needs clone method", e) + getCloneMethod(clazz) match { + case Some(p) => Try(p.invoke(this).asInstanceOf[this.type]) + case _ => { + val constructor = clazz.getConstructors.head + if(constructor.getParameterTypes.size == 0) { + val obj = constructor.newInstance() + Try(obj.asInstanceOf[this.type]) + } else { + val params = constructor.getParameterTypes.toList + if(constructor.getParameterTypes.size == 1) { + val paramtype = constructor.getParameterTypes.head + // If only 1 arg and is a Bundle or Module then this is probably the implicit argument + // added by scalac for nested classes and closures. Thus, try faking the constructor + // by not supplying said class or closure (pass null). + // CONSIDER: Don't try to create this + if(classOf[Bundle].isAssignableFrom(paramtype) || classOf[Module].isAssignableFrom(paramtype)){ + Try(constructor.newInstance(null).asInstanceOf[this.type]) + } else { + throwQuietException(s"Cannot auto-create constructor for ${this.getClass.getName} that requires arguments: " + params) + } + } else { + throwQuietException(s"Cannot auto-create constructor for ${this.getClass.getName} that requires arguments: " + params) + } + } + } } } + /** name this node + * + * @note use [[Chisel.Node.setName setName]] in [[Chisel.Node Node]] rather than this directly */ override def nameIt(path: String, isNamingIo: Boolean) { - if (isTypeNode && comp != null) { - comp.nameIt(path, isNamingIo) - } else { - super.nameIt(path, isNamingIo) + comp match { + case Some(p) if isTypeNode => p nameIt (path, isNamingIo) + case _ => super.nameIt(path, isNamingIo) } } def params = if(Driver.parStack.isEmpty) Parameters.empty else Driver.parStack.top + + // Chisel3 - This node has been wrapped in Wire() and may participate in assignment (:=, <>) statements. + private var _isWired = false + def isWired = _isWired + def setIsWired(value: Boolean) { _isWired = value } + + // Chisel3 - type-only nodes (no data - initialization or assignment) - used for verifying Wire() wrapping + override def isTypeOnly = { + comp match { + case Some(p) if isTypeNode => p.isTypeOnly + case _ => super.isTypeOnly + } + } } diff --git a/src/main/scala/Dot.scala b/src/main/scala/Dot.scala index 8c3541c6..a7f35e2a 100644 --- a/src/main/scala/Dot.scala +++ b/src/main/scala/Dot.scala @@ -1,5 +1,5 @@ /* - Copyright (c) 2011, 2012, 2013, 2014 The Regents of the University of + Copyright (c) 2011 - 2016 The Regents of the University of California (Regents). All Rights Reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: @@ -29,43 +29,31 @@ */ package Chisel -import Node._ -import Reg._ -import ChiselError._ -import scala.collection.mutable.HashSet -import scala.collection.mutable.HashMap -import scala.collection.mutable.ArrayBuffer -import PartitionIslands._ class DotBackend extends Backend { - val keywords = Set[String]() + import PartitionIslands._ var islands = Array[Island]() val allDottable = false val useComponentNames = false override def emitRef(node: Node): String = { node match { - case r: Reg => - if (r.name == "") { - r.name = "R" + r.emitIndex - } // If we're explicitly outputting literal nodes, make sure they have a legitimate name and not just a number. - case l: Literal => if (allDottable) { - return "L" + l.toString - } + case l: Literal if (allDottable) => "L" + l.toString + case r: Reg => + if (r.name == "") r.name = "R" + r.emitIndex + fullyQualifiedName(node) case _ => - if(node.name == "") { - node.name = "T" + node.emitIndex - } + if(node.name == "") node.name = "T" + node.emitIndex + fullyQualifiedName(node) } - fullyQualifiedName(node) } private def isDottable (m: Node): Boolean = { if (allDottable) { true } else - if (m == m.component.defaultResetPin) { + if (m.component.resetPin != None && m == m.component.resetPin.get) { false } else { m match { @@ -123,6 +111,11 @@ class DotBackend extends Backend { def outputAnIsland(island: Island) { val island_res = new StringBuilder() val islandId = if (island == null) 0 else island.islandId + // Should we identify ports? Currently, only for Mux nodes. + def usePort(n: Node) = n match { + case mux: Mux => true + case _ => false + } for (m <- top.nodes) { if (isDottable(m)) { @@ -149,6 +142,7 @@ class DotBackend extends Backend { if (isNodeInIsland(m, island)) { m match { case reg: Delay => island_res.append("[shape=square," + label + "];" + EOL) + case mux: Mux => island_res.append("[shape=Mdiamond," + label + "];" + EOL) case _ => island_res.append("[" + label + "];" + EOL) } } @@ -159,11 +153,22 @@ class DotBackend extends Backend { if( m.component == top && isDottable(m)) { /* We have to check the node's component agrees because output nodes are part of a component *mods* as well as its parent *mods*! */ - for (in <- m.inputs) { + val muxPort = usePort(m) + for ((in, index) <- m.inputs.zip(List("n", "w", "e"))) { if (isDottable(in)) { if (isNodeInIsland(in, island)) { - val edge = (emitRef(in) + " -> " + emitRef(m) - + "[label=\"" + in.needWidth() + "\"];"+ EOL) + val srcPort = if (usePort(in)) { + ":s" + } else { + "" + } + val dstPort = if (muxPort) { + ":" + index + } else { + "" + } + val edge = (emitRef(in) + srcPort + " -> " + emitRef(m) + dstPort + + "[label=\"" + in.needWidth() + "\"];" + EOL) if (islandId != 0) { // If we're drawing partitioned islands, duplicate the logic // for boundary crossings below. @@ -229,51 +234,46 @@ class DotBackend extends Backend { islands = createIslands() } var gn = -1; - val out_cd = createOutputFile(c.name + "_c.dot"); - out_cd.write("digraph TopTop {\n"); - out_cd.write("rankdir = LR;\n"); - def genNum: Int = { gn += 1; gn }; + val out_cd = createOutputFile(c.name + "_c.dot") + out_cd.write("digraph TopTop {\n") + out_cd.write("rankdir = LR;\n") + def genNum: Int = { gn += 1; gn } def dumpComponent (c: Module): Unit = { - out_cd.write("subgraph cluster" + c.name + "{\n"); - out_cd.write("label = \"" + c.name + "\";\n"); - def dumpIo (n: String, d: Data): Unit = { - d match { - case b: Bundle => - out_cd.write("subgraph cluster" + n + "__" + genNum + "{\n"); - out_cd.write("node [shape=box];\n"); - out_cd.write("label = \"" + n + "\";\n"); - for ((cn, cd) <- b.elements) - dumpIo(cn, cd); - out_cd.write("}\n"); - case o => - out_cd.write(emitRef(d) + "[label=\"" + n + "\"];\n"); - for (in <- d.inputs) - if (isDottable(in)) { - out_cd.write(emitRef(in) + " -> " + emitRef(d) + "[label=\"" + in.needWidth() + "\"];\n"); - } - } + out_cd.write("subgraph cluster" + c.name + "{\n") + out_cd.write("label = \"" + c.name + "\";\n") + def dumpIo (n: String, d: Data): Unit = d match { + case b: Bundle => + out_cd.write("subgraph cluster" + n + "__" + genNum + "{\n") + out_cd.write("node [shape=box];\n") + out_cd.write("label = \"" + n + "\";\n") + b.elements foreach { case (cn, cd) => dumpIo(cn, cd) } + out_cd.write("}\n") + case o => + out_cd.write(emitRef(d) + "[label=\"" + n + "\"];\n") + for (in <- d.inputs if isDottable(in)) { + out_cd.write(emitRef(in) + " -> " + emitRef(d) + "[label=\"" + in.needWidth() + "\"];\n") + } } - dumpIo("io", c.io); - for (cc <- c.children) - dumpComponent(cc); + dumpIo("io", c.io) + c.children foreach (dumpComponent(_)) out_cd.write("}\n"); } - dumpComponent(c); - out_cd.write("}"); - out_cd.close(); + dumpComponent(c) + out_cd.write("}") + out_cd.close() - val out_d = createOutputFile(c.name + ".dot"); - out_d.write("digraph " + c.name + "{\n"); - out_d.write("rankdir = LR;\n"); + val out_d = createOutputFile(c.name + ".dot") + out_d.write("digraph " + c.name + "{\n") + out_d.write("rankdir = LR;\n") val (innertext, innercrossings) = emitModuleText(c, 0) - out_d.write(innertext); + out_d.write(innertext) if (Driver.partitionIslands && innercrossings.length > 0) { - out_d.write(innercrossings); + out_d.write(innercrossings) } else { Predef.assert(innercrossings.length == 0, - {println("length:" + innercrossings.length + ", " + innercrossings)}) + ChiselError.error("Internal Error: length:" + innercrossings.length + ", " + innercrossings)) } - out_d.write("}"); - out_d.close(); + out_d.write("}") + out_d.close() } } diff --git a/src/main/scala/Driver.scala b/src/main/scala/Driver.scala index 2da1757e..8ec5c9f0 100644 --- a/src/main/scala/Driver.scala +++ b/src/main/scala/Driver.scala @@ -1,5 +1,5 @@ /* - Copyright (c) 2011, 2012, 2013, 2014 The Regents of the University of + Copyright (c) 2011 - 2016 The Regents of the University of California (Regents). All Rights Reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: @@ -30,27 +30,55 @@ package Chisel -import collection.mutable.{ArrayBuffer, HashSet, HashMap, Stack, LinkedHashSet, Queue => ScalaQueue} -import scala.math.min +import collection.mutable.{ArrayBuffer, HashSet, HashMap, LinkedHashMap, Stack, Queue => ScalaQueue} +import scala.collection.immutable.ListSet +import sys.process.{BasicIO,stringSeqToProcess} +import BuildInfo._ object Driver extends FileSystemUtilities{ + // Indicate this version of Chisel is deprecated and advise moving to chisel3. + val deprecatedWarning = new ChiselError(() => "Chisel2 is deprecated. Please use Chisel3: https://github.com/freechipsproject/chisel3", null, ChiselError.warningLevel) + + def done: Unit = { + deprecatedWarning.print() + } + def apply[T <: Module](args: Array[String], gen: () => T, wrapped:Boolean): T = { initChisel(args) try { if(wrapped) execute(gen) else executeUnwrapped(gen) } finally { ChiselError.report - if (ChiselError.hasErrors && !getLineNumbers) { + if (wantLineNumbers) { println("Re-running Chisel in debug mode to obtain erroneous line numbers...") apply(args :+ "--lineNumbers", gen, wrapped) } + done + } + } + + // If we encountered errors, and re-running with --lineNumbers may help + // diagnose the problem, indicate we should do so. + def wantLineNumbers: Boolean = { + if (ChiselError.hasErrors && !getLineNumbers) { + // If we have a non-cpp compilation error with no line number information, + // re-running may help. + ChiselError.getErrorList.exists(e => e.line == null && !e.msgFun().startsWith("failed to compile ")) + } else { + false } } - def apply[T <: Module](args: Array[String], gen: () => T, - ftester: T => Tester[T], wrapped:Boolean): T = { + def apply[T <: Module](args: Array[String], gen: () => T, ftester: T => Tester[T], wrapped:Boolean): T = { val mod = apply(args, gen, wrapped) - if (isTesting) test(mod, ftester) + if (isTesting) { + try { + if (!ftester(mod).finish) throwException("Module under test FAILED at least one test vector.") + } finally { + Tester.close + } + done + } mod } @@ -93,36 +121,23 @@ object Driver extends FileSystemUtilities{ backend.elaborate(c) if (isCompiling && isGenHarness) backend.compile(c) if(chiselConfigDump && !Dump.dump.isEmpty) { - val w = createOutputFile(appendString(Some(topComponent.name),chiselConfigClassName) + ".prm") + val w = createOutputFile(appendString(Some(c.name),chiselConfigClassName) + ".prm") w.write(Dump.getDump); w.close } } c } - private def test[T <: Module](mod: T, ftester: T => Tester[T]): Unit = { - var res = false - var tester: Tester[T] = null - try { - tester = ftester(mod) - } finally { - if (tester != null && tester.process != null) - res = tester.finish() - } - println(if (res) "PASSED" else "*** FAILED ***") - if(!res) throwException("Module under test FAILED at least one test vector.") - } - def elapsedTime: Long = System.currentTimeMillis - startTime - def setTopComponent(mod: Module): Unit = { - topComponent = mod - implicitReset.component = topComponent - implicitClock.component = topComponent - topComponent.reset = implicitReset - topComponent.hasExplicitReset = true - topComponent.clock = implicitClock - topComponent.hasExplicitClock = true + def setTopComponent(mod: Module) { + topComponent = Some(mod) + implicitReset.compOpt = topComponent + implicitClock.compOpt = topComponent + mod._reset = Some(implicitReset) + mod._clock = Some(implicitClock) + mod.hasExplicitReset = true + mod.hasExplicitClock = true } def bfs (visit: Node => Unit) = { @@ -137,36 +152,28 @@ object Driver extends FileSystemUtilities{ queue enqueue io // Ensure any nodes connected to reset are visited. for (c <- components) { - if (!(c.defaultResetPin == null)) { - queue enqueue c.defaultResetPin - } - if (!(c._reset == null) && !(c._reset == implicitReset)) { - queue enqueue c._reset.getNode + c._reset match { + case Some(r) if r != implicitReset => queue enqueue r.getNode + case _ => } + for (pin <- c.resets.values) + queue enqueue pin } // Do BFS - val walked = HashSet[Node]() + val _walked = HashSet[Node](queue:_*) + // Avoid a "java.lang.IllegalArgumentException: Flat hash tables cannot contain null elements" if node is null - unassigned MUX + def walked(node: Node) = node == null || _walked(node) + def enqueueNode(node: Node) { if (node != null) { queue enqueue node ; _walked += node }} + def enqueueInputs(top: Node) { ListSet((top.inputs.filter(_ != null)):_*) filterNot walked foreach enqueueNode } + def enqueueElems(agg: Data) { agg.flatten.unzip._2 filterNot walked foreach enqueueNode } while (!queue.isEmpty) { val top = queue.dequeue - walked += top visit(top) top match { - case b: Bundle => - for ((n, io) <- b.flatten; if !(io == null) && !(walked contains io)) { - queue enqueue io - walked += io - } - case v: Vec[_] => - for ((n, e) <- v.flatten; if !(e == null) && !(walked contains e)) { - queue enqueue e - walked += e - } - case _ => - } - for (i <- top.inputs; if !(i == null) && !(walked contains i)) { - queue enqueue i - walked += i + case b: Bundle => enqueueElems(b) + case v: Vec[_] => enqueueElems(v) ; enqueueInputs(v) + case _ => enqueueInputs(top) } } } @@ -178,12 +185,12 @@ object Driver extends FileSystemUtilities{ stack push io // Ensure any nodes connected to reset are visited. for (c <- components) { - if (!(c.defaultResetPin == null)) { - stack push c.defaultResetPin - } - if (!(c._reset == null) && !(c._reset == implicitReset)) { - stack push c._reset.getNode + c._reset match { + case Some(r) if r != implicitReset => stack push r.getNode + case _ => } + for (pin <- c.resets.values) + stack push pin } for (c <- components; a <- c.debugs) stack push a @@ -191,33 +198,19 @@ object Driver extends FileSystemUtilities{ stack push b.io // Do DFS - val walked = HashSet[Node]() + val _walked = HashSet[Node](stack:_*) + // Avoid a "java.lang.IllegalArgumentException: Flat hash tables cannot contain null elements" if node is null - unassigned MUX + def walked(node: Node) = node == null || _walked(node) + def pushNode(node: Node) { stack push node ; _walked += node } + def pushInputs(top: Node) { ListSet(top.inputs:_*) filterNot walked foreach pushNode } + def pushElems(agg: Data) { agg.flatten.unzip._2 filterNot walked foreach pushNode } while (!stack.isEmpty) { val top = stack.pop - walked += top visit(top) top match { - case b: Bundle => - for ((n, io) <- b.flatten; if !(io == null) && !(walked contains io)) { - stack push io - walked += io - } - case v: Vec[_] => { - for ((n, e) <- v.flatten; if !(e == null) && !(walked contains e)) { - stack push e - walked += e - } - for (i <- top.inputs; if !(i == null) && !(walked contains i) && !i.isIo) { - stack push i - walked += i - } - } - case _ => { - for (i <- top.inputs; if !(i == null) && !(walked contains i) && !i.isIo) { - stack push i - walked += i - } - } + case b: Bundle => pushElems(b) + case v: Vec[_] => pushElems(v) ; pushInputs(v) + case _ => pushInputs(top) } } } @@ -247,17 +240,16 @@ object Driver extends FileSystemUtilities{ pushInitialNode(a) for(b <- blackboxes) pushInitialNode(b.io) - for(c <- components; (n, io) <- c.wires) { + for(c <- components; (n, io) <- c.wires) pushInitialNode(io) - } // Ensure any nodes connected to reset are visited. for (c <- components) { - if (!(c.defaultResetPin == null)) { - pushInitialNode(c.defaultResetPin) - } - if (!(c._reset == null) && !(c._reset == implicitReset)) { - pushInitialNode(c._reset.getNode) + c._reset match { + case Some(r) if r != implicitReset => pushInitialNode(r.getNode) + case _ => } + for (pin <- c.resets.values) + pushInitialNode(pin) } val stack = inputs ++ res @@ -268,6 +260,8 @@ object Driver extends FileSystemUtilities{ stack.push((n, false)) } + def visited(node: Node) = stacked contains node + def pushElems(agg: Data) { agg.flatten.unzip._2 filterNot visited foreach pushBareNode } // Walk the graph in depth-first order, // visiting nodes as we do so. while (!stack.isEmpty) { @@ -281,25 +275,12 @@ object Driver extends FileSystemUtilities{ // Put this node back on the stack, with a flag indicating we've dealt with its children stack push ((top, true)) top match { - case v: Vec[_] => { - for ((n, e) <- v.flatten; - if !(stacked contains e)) { - pushBareNode(e) - } - } - case b: Bundle => { - for ((n, e) <- b.flatten; - if !(stacked contains e)) { - pushBareNode(e) - } - } + case v: Vec[_] => pushElems(v) + case b: Bundle => pushElems(b) case _ => {} } // Push any un-visited children - for (c <- top.inputs; - if !(stacked contains c)) { - pushBareNode(c) - } + for (c <- top.inputs if !(stacked contains c)) { pushBareNode(c) } } } } @@ -311,31 +292,27 @@ object Driver extends FileSystemUtilities{ saveConnectionWarnings = false saveComponentTrace = false dontFindCombLoop = false - isGenHarness = false isDebug = false getLineNumbers = false isCSE = false isIoDebug = true isVCD = false isVCDMem = false + isInlineMem = true + isGenHarness = false isReportDims = false + includeArgs = Nil targetDir = "." - components.clear() - sortedComps.clear() - compStack.clear() - stackIndent = 0 - printStackStruct.clear() - blackboxes.clear() - chiselOneHotMap.clear() - chiselOneHotBitMap.clear() isCompiling = false isCheckingPorts = false isTesting = false + testCommand = None + isAssert = true + isAssertWarn = false isDebugMem = false - isSupportW0W = false partitionIslands = false lineLimitFunctions = 0 - minimumLinesPerFile = 0 + minimumLinesPerFile = 10000 shadowRegisterInObject = false allocateOnlyNeededShadowRegisters = false compileInitializationUnoptimized = false @@ -343,21 +320,34 @@ object Driver extends FileSystemUtilities{ parallelMakeJobs = 0 isVCDinline = false isSupportW0W = false - hasMem = false - hasSRAM = false - sramMaxSize = 0 - topComponent = null - clocks.clear() + backend = new CppBackend + topComponent = None + moduleNamePrefix = "" + components.clear() + sortedComps.clear() + orderedNodes.clear() + blackboxes.clear() + chiselOneHotMap.clear() + chiselOneHotBitMap.clear() + compStack.clear() + parStack.clear() + stackIndent = 0 + printStackStruct.clear() implicitReset.isIo = true implicitReset.setName("reset") - implicitClock = new Clock() implicitClock.setName("clk") - nodes.clear() - orderedNodes.clear() + clocks.clear() + clocks += implicitClock isInGetWidth = false - startTime = System.currentTimeMillis modStackPushed = false - + minimumCompatibility = Version("0.0.0") + wError = false + chiselConfigClassName = None + chiselProjectName = None + chiselConfigMode = None + chiselConfigDump = false + startTime = System.currentTimeMillis + signalMap.clear readArgs(args) } @@ -389,10 +379,11 @@ object Driver extends FileSystemUtilities{ case "--vcd" => isVCD = true case "--vcdMem" => isVCDMem = true case "--v" => backendName = "v" - case "--moduleNamePrefix" => Backend.moduleNamePrefix = args(i + 1); i += 1 + case "--moduleNamePrefix" => moduleNamePrefix = args(i + 1); i += 1 case "--inlineMem" => isInlineMem = true case "--noInlineMem" => isInlineMem = false case "--assert" => isAssert = true + case "--assertWarn" => isAssertWarn = true case "--noAssert" => isAssert = false case "--debugMem" => isDebugMem = true case "--partitionIslands" => partitionIslands = true @@ -407,18 +398,23 @@ object Driver extends FileSystemUtilities{ case "--backend" => backendName = args(i + 1); i += 1 case "--compile" => isCompiling = true case "--test" => isTesting = true - case "--targetDir" => targetDir = args(i + 1); i += 1 + case "--testCommand" => + var cmd = "" + while(i + 1 < args.size && args(i + 1).substring(0,2) != "--") { + cmd += args(i + 1) + " " ; i += 1 } + testCommand = Some(cmd); i += 1 + case "--targetDir" => targetDir = ensureDir(args(i + 1)); i += 1 case "--include" => includeArgs = args(i + 1).split(' ').toList; i += 1 case "--checkPorts" => isCheckingPorts = true case "--reportDims" => isReportDims = true //Jackhammer Flags - case "--configCollect" => chiselConfigMode = Some("collect"); chiselConfigClassName = Some(getArg(args(i+1),1)); chiselProjectName = Some(getArg(args(i+1),0)); i+=1; //dump constraints in dse dir - case "--configInstance" => chiselConfigMode = Some("instance"); chiselConfigClassName = Some(getArg(args(i+1),1)); chiselProjectName = Some(getArg(args(i+1),0)); i+=1; //use ChiselConfig to supply parameters + case "--configName" => chiselConfigClassName = Some(args(i + 1)); i += 1 + case "--configCollect" => chiselConfigMode = Some("collect"); chiselConfigClassName = Some(getArg(args(i + 1),1)); chiselProjectName = Some(getArg(args(i + 1),0)); i += 1; //dump constraints in dse dir + case "--configInstance" => chiselConfigMode = Some("instance"); chiselConfigClassName = Some(getArg(args(i + 1),1)); chiselProjectName = Some(getArg(args(i + 1),0)); i += 1; //use ChiselConfig to supply parameters case "--configDump" => chiselConfigDump = true; //when using --configInstance, write Dump parameters to .prm file in targetDir case "--dumpTestInput" => dumpTestInput = true case "--testerSeed" => { - testerSeedValid = true - testerSeed = args(i+1).toLong + testerSeed = args(i + 1).toLong i += 1 } case "--emitTempNodes" => { @@ -428,16 +424,19 @@ object Driver extends FileSystemUtilities{ // Dreamer configuration flags case "--numRows" => { if (backend.isInstanceOf[FloBackend]) { - backend.asInstanceOf[FloBackend].DreamerConfiguration.numRows = args(i+1).toInt + backend.asInstanceOf[FloBackend].DreamerConfiguration.numRows = args(i + 1).toInt } i += 1 } case "--numCols" => { if (backend.isInstanceOf[FloBackend]) { - backend.asInstanceOf[FloBackend].DreamerConfiguration.numCols = args(i+1).toInt + backend.asInstanceOf[FloBackend].DreamerConfiguration.numCols = args(i + 1).toInt } i += 1 } + case "--minimumCompatibility" => minimumCompatibility = Version(args(i + 1)); i += 1 + case "--wError" => wError = true + case "--version" => println(chiselVersionString) case any => ChiselError.warning("'" + arg + "' is an unknown argument.") } i += 1 @@ -449,13 +448,23 @@ object Driver extends FileSystemUtilities{ // Set the backend after we've interpreted all the arguments. // (The backend may want to configure itself based on the arguments.) backend = backendName match { - case "v" => new VerilogBackend + case "null" => new Backend case "c" => new CppBackend - case "flo" => new FloBackend case "dot" => new DotBackend + case "flo" => new FloBackend case "fpga" => new FPGABackend case "sysc" => new SysCBackend - case _ => Class.forName(backendName).newInstance.asInstanceOf[Backend] + case "v" => new VerilogBackend + case _ => + try { + Class.forName(backendName).newInstance.asInstanceOf[Backend] + } + catch { + case cnf: ClassNotFoundException => + println("Chisel.Driver: backend %s not found: %s, using default backend".format(backendName, cnf)) + backend + + } } } @@ -474,15 +483,17 @@ object Driver extends FileSystemUtilities{ var isGenHarness = false var isReportDims = false var includeArgs: List[String] = Nil - var targetDir: String = null + var targetDir: String = "." var isCompiling = false var isCheckingPorts = false var isTesting = false + var testCommand: Option[String] = None var isAssert = true + var isAssertWarn = false var isDebugMem = false var partitionIslands = false var lineLimitFunctions = 0 - var minimumLinesPerFile = 0 + var minimumLinesPerFile = 10000 var shadowRegisterInObject = false var allocateOnlyNeededShadowRegisters = false var compileInitializationUnoptimized = false @@ -490,14 +501,11 @@ object Driver extends FileSystemUtilities{ var parallelMakeJobs = 0 var isVCDinline = false var isSupportW0W = false - var hasMem = false - var hasSRAM = false - var sramMaxSize = 0 - var backend: Backend = null - var topComponent: Module = null + var backend: Backend = new CppBackend + var topComponent: Option[Module] = None + var moduleNamePrefix = "" val components = ArrayBuffer[Module]() val sortedComps = ArrayBuffer[Module]() - val nodes = ArrayBuffer[Node]() val orderedNodes = ArrayBuffer[Node]() val blackboxes = ArrayBuffer[BlackBox]() val chiselOneHotMap = HashMap[(UInt, Int), UInt]() @@ -508,16 +516,28 @@ object Driver extends FileSystemUtilities{ val printStackStruct = ArrayBuffer[(Int, Module)]() val clocks = ArrayBuffer[Clock]() val implicitReset = Bool(INPUT) - var implicitClock: Clock = null + val implicitClock = Clock() var isInGetWidth: Boolean = false var modStackPushed: Boolean = false var modAdded: Boolean = false - var startTime = 0L + var minimumCompatibility = Version("0.0.0") + var wError = false /* ChiselConfig flags */ var chiselConfigClassName: Option[String] = None var chiselProjectName: Option[String] = None var chiselConfigMode: Option[String] = None var chiselConfigDump: Boolean = false + var startTime = 0L + val version = BuildInfo.version + val chiselVersionString = BuildInfo.toString + /* For tester */ + val signalMap = LinkedHashMap[Node, Int]() + var nodeId = 0 + def getNodeId = { + val id = nodeId + nodeId +=1 + id + } def appendString(s1:Option[String],s2:Option[String]):String = { if(s1.isEmpty && s2.isEmpty) "" else { @@ -534,12 +554,23 @@ object Driver extends FileSystemUtilities{ // standard input stream to a file. var dumpTestInput = false - // Setting this to TRUE will initialize the tester's RNG with the - // seed below. - var testerSeedValid = false + // This value may be overridden with a command line option --testerSeed var testerSeed = System.currentTimeMillis() // Setting this to TRUE will result in temporary values (ie, nodes // named "T*") to be emited to the VCD file. var emitTempNodes = false + + // Indicate if an external command is available. + def isCommandAvailable(cmd: String): Boolean = { + // Eat any output. + val sb = new StringBuffer + val ioToDevNull = BasicIO(false, sb, None) + + Seq("bash", "-c", "which %s".format(cmd)).run(ioToDevNull).exitValue == 0 + } + + lazy val isVCSAvailable = isCommandAvailable("vcs") + // Print Chisel version when driver object is constructed, hopefully, just once. + println(chiselVersionString) } diff --git a/src/main/scala/Enum.scala b/src/main/scala/Enum.scala index 93363ff5..523ad16f 100644 --- a/src/main/scala/Enum.scala +++ b/src/main/scala/Enum.scala @@ -1,5 +1,5 @@ /* - Copyright (c) 2011, 2012, 2013, 2014 The Regents of the University of + Copyright (c) 2011 - 2016 The Regents of the University of California (Regents). All Rights Reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: @@ -29,16 +29,32 @@ */ package Chisel -import Literal._ +/** An object for creating C style Enums */ object Enum { - /** create n enum values of given type */ + import Literal.sizeof + /** create n enum values of given type for n <= 22 + * @param nodeType the type of node to create + * @param n the number of nodes to create + * @example {{{ val s1 :: s2 :: s3 :: Nil = Enum(UInt(), 3) }}} + * @note When declaring vals the first character must be lower case, ie S1 is illegal + * @note The 22 state size limitation is due to the maximum Scala tuple size of 22 (other methods avoid this limitation)*/ def apply[T <: UInt](nodeType: T, n: Int): List[T] = (Range(0, n, 1).map(x => (Lit(x, sizeof(n-1))(nodeType)))).toList; - /** create enum values of given type and names */ + /** create enum values of given type and names + * @param nodeType the type of node to create + * @param l any number of Symbols to create as an Enum + * @return a map from Symbol to the node created*/ def apply[T <: UInt](nodeType: T, l: Symbol *): Map[Symbol, T] = (l.toList zip (Range(0, l.length, 1).map(x => Lit(x, sizeof(l.length-1))(nodeType)))).toMap; - /** create enum values of given type and names */ + /** create enum values of given type and names + * @param nodeType the type of node to create + * @param l a list of symbols + * @return a map of symbols to a node created + * @example {{{ + * val states = Enum(UInt(), List('s1, 's2, 's3)) + * val state = Reg(UInt(), init = states('s1)) + * }}}*/ def apply[T <: UInt](nodeType: T, l: List[Symbol]): Map[Symbol, T] = (l zip (Range(0, l.length, 1).map(x => Lit(x, sizeof(l.length-1))(nodeType)))).toMap; } diff --git a/src/main/scala/Extract.scala b/src/main/scala/Extract.scala index 52e76612..e341b274 100644 --- a/src/main/scala/Extract.scala +++ b/src/main/scala/Extract.scala @@ -1,5 +1,5 @@ /* - Copyright (c) 2011, 2012, 2013, 2014 The Regents of the University of + Copyright (c) 2011 - 2016 The Regents of the University of California (Regents). All Rights Reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: @@ -29,8 +29,6 @@ */ package Chisel -import Node._ -import Lit._ object NodeExtract { // extract one bit @@ -42,43 +40,32 @@ object NodeExtract { def apply(mod: Node, hi: Int, lo: Int, width: Int): Node = { if (hi < lo) { if (!((hi == lo - 1) && Driver.isSupportW0W)) { - ChiselError.error("Extract(hi = " + hi + ", lo = " + lo + ") requires hi >= lo") + ChiselError.error("Extract " + mod.getNode.name + "(hi = " + hi + ", lo = " + lo + ") requires hi >= lo") } } val w = if (width == -1) hi - lo + 1 else width - val bits_lit = mod.litOf // Currently, we don't restrict literals to their width, // so we can't use the literal directly if it overflows its width. val wmod = mod.widthW - if (lo == 0 && wmod.isKnown && w == wmod.needWidth()) { - mod - } else if (bits_lit != null) { - Literal((bits_lit.value >> lo) & ((BigInt(1) << w) - BigInt(1)), w) - } else { - makeExtract(mod, Literal(hi), Literal(lo), fixWidth(w)) + if (lo == 0 && wmod.isKnown && w == wmod.needWidth()) mod + else mod.litOpt match { + case Some(l) => Literal((l.value >> lo) & ((BigInt(1) << w) - BigInt(1)), w) + case None => makeExtract(mod, Literal(hi), Literal(lo), Node.fixWidth(w)) } } // extract bit range def apply(mod: Node, hi: Node, lo: Node, width: Int = -1): Node = { - val hiLit = hi.litOf - val loLit = lo.litOf - val widthInfer = if (width == -1) widthOf(0) else fixWidth(width) - if (hiLit != null && loLit != null) { - apply(mod, hiLit.value.toInt, loLit.value.toInt, width) - } else { // avoid extracting from constants and avoid variable part selects - val rsh = Op(">>", widthInfer, mod, lo) - val hiMinusLoPlus1 = Op("+", maxWidth _, Op("-", maxWidth _, hi, lo), UInt(1)) - val mask = Op("-", widthInfer, Op("<<", widthInfer, UInt(1), hiMinusLoPlus1), UInt(1)) - Op("&", widthInfer, rsh, mask) + val widthInfer = if (width == -1) Node.widthOf(0) else Node.fixWidth(width) + (hi.litOpt, lo.litOpt) match { + case (Some(hl), Some(ll)) => apply(mod, hl.value.toInt, ll.value.toInt, width) + case _ => makeExtract(mod, hi, lo, widthInfer) } } private def makeExtract(mod: Node, hi: Node, lo: Node, widthFunc: (=> Node) => Width) = { - val res = new Extract + val res = new Extract(hi, lo) res.init("", widthFunc, mod, hi, lo) - res.hi = hi - res.lo = lo res } } @@ -107,21 +94,20 @@ object Extract { } } -class Extract extends Node { - var lo: Node = null; - var hi: Node = null; - +class Extract(hi: Node, lo: Node) extends Node { override def toString: String = - ("/*" + (if (name != null && !name.isEmpty) name else "?") + "*/ Extract(" + ("/*" + (if (!name.isEmpty) name else "?") + "*/ Extract(" + inputs(0) + (if (hi == lo) "" else (", " + hi)) + ", " + lo + ")") def validateIndex(x: Node) { - val lit = x.litOf val w0 = inputs(0).widthW - assert(lit == null || lit.value >= 0 && lit.value < w0.needWidth(), - ChiselError.error("Extract(" + lit.value + ")" + - " out of range [0," + (w0.needWidth()-1) + "]" + - " of " + inputs(0), line)) + x.litOpt match { + case Some(l) => assert(l.value >= 0 && l.value < w0.needWidth(), + ChiselError.error("Extract(" + l.value + ")" + + " out of range [0," + (w0.needWidth()-1) + "]" + + " of " + inputs(0), line)) + case _ => + } } override def canCSE: Boolean = true @@ -136,15 +122,59 @@ class Extract extends Node { * the high and lo must be n-1 and n respectively. * If this is true, we ensure our width is zero. */ - val hi_lit = inputs(1).litOf - val lo_lit = inputs(2).litOf - if (inputs(0).getWidth == 0 && hi_lit != null && lo_lit != null && - hi_lit.value == (lo_lit.value - 1)) { - setWidth(0) - modified = true - } else { - ChiselError.error("Extract(" + inputs(0) + ", " + inputs(1) + ", " + inputs(2) + ")" + + (inputs(1).litOpt, inputs(2).litOpt) match { + case (Some(hl), Some(ll)) if inputs(0).getWidth == 0 && hl.value == (ll.value-1) => + setWidth(0) + modified = true + case _ => + ChiselError.error("Extract(" + inputs(0) + ", " + inputs(1) + ", " + inputs(2) + ")" + " W0Wtransform", line) } } + + // Static width - we can determine the width of the extracted bits at elaboration time. + def isStaticWidth: Boolean = { + if (this.inputs.length < 3 || this.needWidth() == 1) { + true + } else { + val hi = this.inputs(1) + val lo = this.inputs(2) + // The width is known if both inputs will have the same runtime value, or both are literals. + hi == lo || (hi.isLit && lo.isLit) + } + } + + // Is this a (known) single bit extraction? + def isOneBit: Boolean = { + // It must at least be static, then either have only one argument, or two identical arguments, + // or two arguments with identical values. + // TODO: This last test is redundant if literal nodes are identical if their values are identical + isStaticWidth && (this.inputs.length < 3 || { + (this.inputs(1), this.inputs(2)) match { + case (hi: Literal, lo: Literal) => hi.value == lo.value + case _ => { + // If the width is static and we get here, both inputs must be the same. + assert(hi == lo) + true + } + } + }) + } + + // Is this operation a no-op - extract all source bits? + def isNop: Boolean = { + // The extracted width must be static and equal to the source width, and the lo value must be 0. + isStaticWidth && this.inputs(1).isLit && { + val hiValue = this.inputs(1).litValue() + val loValue = if (this.inputs.length < 3) { + hiValue + } else { + this.inputs(2).litValue() + } + hiValue - loValue + 1 == this.inputs(0).needWidth && loValue == 0 + } + } + + // Chisel3 - this node contains data - used for verifying Wire() wrapping + override def isTypeOnly = false } diff --git a/src/main/scala/FP.scala b/src/main/scala/FP.scala index 10cbab1e..d5c52943 100644 --- a/src/main/scala/FP.scala +++ b/src/main/scala/FP.scala @@ -1,5 +1,5 @@ /* - Copyright (c) 2011, 2012, 2013, 2014 The Regents of the University of + Copyright (c) 2011 - 2016 The Regents of the University of California (Regents). All Rights Reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: @@ -29,36 +29,42 @@ */ package Chisel -import Node._ -import ChiselError._ +import Node.fixWidth /// FLO - -import java.lang.Float.floatToIntBits - +/** Create a 32 bit floating point Object */ object Flo { - def apply(x: Float): Flo = Lit(floatToIntBits(x), 32){ Flo() } + /** Convert a Float to a Flo literal */ + def apply(x: Float): Flo = Lit(java.lang.Float.floatToIntBits(x), 32){ Flo() } + /** Convert a Double to a Flo literal + * @note Flo uses 32 bits so the Double is first converted to a Float */ def apply(x: Double): Flo = Flo(x.toFloat); - def apply(dir: IODirection = null): Flo = { + /** Create a Flo for I/O */ + def apply(dir: IODirection = NODIR): Flo = { val res = new Flo(); res.dir = dir; - res.init("", fixWidth(32)) + // The width is fixed, really fixed. + res.init("", 32) res } } +/** A 32 bit floating point representation class + * Create using the [[Chisel.Flo$ Flo]] object */ class Flo extends Bits with Num[Flo] { // setIsSigned // override def setIsTypeNode = {inputs(0).setIsSigned; super.setIsTypeNode} type T = Flo; + /** Convert a node to a [[Chisel.Flo Flo]] */ override def fromNode(n: Node): this.type = { val res = Flo(OUTPUT).asTypeFor(n).asInstanceOf[this.type] res } + /** Get the floating point representation of an Int */ override def fromInt(x: Int): this.type = { Flo(x.toFloat).asInstanceOf[this.type] } @@ -68,6 +74,7 @@ class Flo extends Bits with Num[Flo] { case _ => illegalAssignment(that) } + /** Get Flo as an instance of T */ def gen[T <: Bits](): T = Flo().asInstanceOf[T]; def unary_-(): Flo = newUnaryOp("f-") @@ -77,7 +84,9 @@ class Flo extends Bits with Num[Flo] { def / (b: Flo): Flo = newBinaryOp(b, "f/") def % (b: Flo): Flo = newBinaryOp(b, "f%") def ===(b: Flo): Bool = newLogicalOp(b, "f==") + @deprecated("Use =/= rather than != for chisel comparison", "3") def != (b: Flo): Bool = newLogicalOp(b, "f!=") + def =/= (b: Flo): Bool = newLogicalOp(b, "f!=") def > (b: Flo): Bool = newLogicalOp(b, "f>") def < (b: Flo): Bool = newLogicalOp(b, "f<") def <= (b: Flo): Bool = newLogicalOp(b, "f<=") @@ -100,32 +109,40 @@ class Flo extends Bits with Num[Flo] { /// DBL -import java.lang.Double.doubleToLongBits - +/** Create a 64 bit double precision floating point representation */ object Dbl { + /** Convert a float to a [[Chisel.Dbl Dbl]] literal + * @note first converted to a Double */ def apply(x: Float): Dbl = Dbl(x.toDouble); - def apply(x: Double): Dbl = Lit(doubleToLongBits(x), 64){ Dbl() } + /** Convert a Double to a [[Chisel.Dbl Dbl]] literal */ + def apply(x: Double): Dbl = Lit(java.lang.Double.doubleToLongBits(x), 64){ Dbl() } - def apply(dir: IODirection = null): Dbl = { + /** Create a [[Chisel.Dbl Dbl]] as I/O */ + def apply(dir: IODirection = NODIR): Dbl = { val res = new Dbl(); res.dir = dir; - res.init("", fixWidth(64)) + // The width is fixed, really fixed. + res.init("", 64) res } } +/** A double precision floating point representation + * Create using [[Chisel.Dbl$ Dbl]] */ class Dbl extends Bits with Num[Dbl] { // setIsSigned // override def setIsTypeNode = {inputs(0).setIsSigned; super.setIsTypeNode} type T = Dbl; + /** Convert a node to [[Chisel.Dbl Dbl]] representation */ override def fromNode(n: Node) = { val res = Dbl(OUTPUT).asTypeFor(n).asInstanceOf[this.type] res } + /** Convert an Integer to [[Chisel.Dbl Dbl]] representation */ override def fromInt(x: Int): this.type = { Dbl(x.toDouble).asInstanceOf[this.type] } @@ -144,7 +161,9 @@ class Dbl extends Bits with Num[Dbl] { def / (b: Dbl): Dbl = newBinaryOp(b, "d/") def % (b: Dbl): Dbl = newBinaryOp(b, "d%") def ===(b: Dbl): Bool = newLogicalOp(b, "d==") + @deprecated("Use =/= rather than != for chisel comparison", "3") def != (b: Dbl): Bool = newLogicalOp(b, "d!=") + def =/= (b: Dbl): Bool = newLogicalOp(b, "d!=") def > (b: Dbl): Bool = newLogicalOp(b, "d>") def < (b: Dbl): Bool = newLogicalOp(b, "d<") def <= (b: Dbl): Bool = newLogicalOp(b, "d<=") @@ -165,64 +184,92 @@ class Dbl extends Bits with Num[Dbl] { override def toUInt (): UInt = UInt(OUTPUT).fromNode(Op("dToUInt", fixWidth(64), this)) } +/** Compute the sin value of a [[Chisel.Flo Flo]] or [[Chisel.Dbl Dbl]] in radians + * @note This computes the value in scala on a literal and will not generate hardware */ object Sin { def apply (x: Flo): Flo = x.sin def apply (x: Dbl): Dbl = x.sin } +/** Compute the cos value of a [[Chisel.Flo Flo]] or [[Chisel.Dbl Dbl]] in radians + * @note This computes the value in scala on a literal and will not generate hardware */ object Cos { def apply (x: Flo): Flo = x.cos def apply (x: Dbl): Dbl = x.cos } +/** Compute the tan value of a [[Chisel.Flo Flo]] or [[Chisel.Dbl Dbl]] in radians + * @note This computes the value in scala on a literal and will not generate hardware */ object Tan { def apply (x: Flo): Flo = x.tan def apply (x: Dbl): Dbl = x.tan } +/** Compute the asin or inverse sin value of a [[Chisel.Flo Flo]] or [[Chisel.Dbl Dbl]] returning the result in radians + * @note This computes the value in scala on a literal and will not generate hardware */ object ASin { def apply (x: Flo): Flo = x.asin def apply (x: Dbl): Dbl = x.asin } +/** Compute the acos or inverse cos value of a [[Chisel.Flo Flo]] or [[Chisel.Dbl Dbl]] returning the result in radians + * @note This computes the value in scala on a literal and will not generate hardware */ object ACos { def apply (x: Flo): Flo = x.acos def apply (x: Dbl): Dbl = x.acos } +/** Compute the atan or inverse tan value of a [[Chisel.Flo Flo]] or [[Chisel.Dbl Dbl]] returning the result in radians + * @note This computes the value in scala on a literal and will not generate hardware */ object ATan { def apply (x: Flo): Flo = x.atan def apply (x: Dbl): Dbl = x.atan } +/** Compute the square root of a [[Chisel.Flo Flo]] or [[Chisel.Dbl Dbl]] + * @note This computes the value in scala on a literal and will not generate hardware */ object Sqrt { def apply (x: Flo): Flo = x.sqrt def apply (x: Dbl): Dbl = x.sqrt } +/** Compute the floor of a [[Chisel.Flo Flo]] or [[Chisel.Dbl Dbl]] + * @note This computes the value in scala on a literal and will not generate hardware */ object Floor { def apply (x: Flo): Flo = x.floor def apply (x: Dbl): Dbl = x.floor } +/** Compute the ceiling of a [[Chisel.Flo Flo]] or [[Chisel.Dbl Dbl]] + * @note This computes the value in scala on a literal and will not generate hardware */ object Ceil { def apply (x: Flo): Flo = x.ceil def apply (x: Dbl): Dbl = x.ceil } +/** Round a [[Chisel.Flo Flo]] or [[Chisel.Dbl Dbl]] to the nearest integer + * @note This computes the value in scala on a literal and will not generate hardware */ object Round { def apply (x: Flo): Flo = x.round def apply (x: Dbl): Dbl = x.round } +/** Compute the log of a [[Chisel.Flo Flo]] or [[Chisel.Dbl Dbl]] + * @note This computes the value in scala on a literal and will not generate hardware */ object Log { def apply (x: Flo): Flo = x.log def apply (x: Dbl): Dbl = x.log + /** @param p the base of the log to use */ def apply (x: Flo, p: Flo): Flo = Log(x)/Log(p) + /** @param p the base of the log to use */ def apply (x: Dbl, p: Dbl): Dbl = Log(x)/Log(p) } +/** Compute the power of a [[Chisel.Flo Flo]] or [[Chisel.Dbl Dbl]] + * @note This computes the value in scala on a literal and will not generate hardware */ object Pow { + /** Compute x^y */ def apply (x: Flo, y: Flo): Flo = x.pow(y) + /** Compute x^y */ def apply (x: Dbl, y: Dbl): Dbl = x.pow(y) } diff --git a/src/main/scala/FPGA.scala b/src/main/scala/FPGA.scala index 7cc3e926..f159bdda 100644 --- a/src/main/scala/FPGA.scala +++ b/src/main/scala/FPGA.scala @@ -1,5 +1,5 @@ /* - Copyright (c) 2011, 2012, 2013, 2014 The Regents of the University of + Copyright (c) 2011 - 2016 The Regents of the University of California (Regents). All Rights Reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: @@ -30,6 +30,7 @@ package Chisel +/** class with no inline mem */ class FPGABackend extends VerilogBackend { Driver.isInlineMem = false diff --git a/src/main/scala/FameBackend.scala b/src/main/scala/FameBackend.scala index f512023a..2c9833d0 100644 --- a/src/main/scala/FameBackend.scala +++ b/src/main/scala/FameBackend.scala @@ -1,5 +1,5 @@ /* - Copyright (c) 2011, 2012, 2013, 2014 The Regents of the University of + Copyright (c) 2011 - 2016 The Regents of the University of California (Regents). All Rights Reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: @@ -29,9 +29,7 @@ */ package Chisel -import scala.collection.mutable.ArrayBuffer -import scala.collection.mutable.HashMap -import scala.collection.mutable.HashSet +import scala.collection.mutable.{ArrayBuffer, HashMap, HashSet} object FameDecoupledIO { @@ -58,7 +56,7 @@ class FameDecoupledIO[+T <: Data](data: T) extends Bundle val host_valid = Bool(OUTPUT) val host_ready = Bool(INPUT) val target = new DecoupledIO(data) - override def clone: this.type = { new FameDecoupledIO(data).asInstanceOf[this.type]} + override def cloneType: this.type = new FameDecoupledIO(data).asInstanceOf[this.type] } class FameQueue[T <: Data] (val entries: Int)(data: => T) extends Module @@ -103,10 +101,10 @@ class FameQueueTrackerIO() extends Bundle{ class FameQueueTracker(num_tgt_entries: Int, num_tgt_cycles: Int) extends Module{ val io = new FameQueueTrackerIO() - val aregs = Vec.fill(num_tgt_cycles){ Reg(init = UInt(0, width = log2Up(num_tgt_entries))) } + val aregs = Reg { Vec(num_tgt_cycles, UInt(0, width = log2Up(num_tgt_entries))) } val tail_pointer = Reg(init = UInt(1, width = log2Up(num_tgt_cycles))) - val next_tail_pointer = UInt() + val next_tail_pointer = Wire(UInt()) tail_pointer := next_tail_pointer next_tail_pointer := tail_pointer when(io.produce && !io.consume){ @@ -115,7 +113,7 @@ class FameQueueTracker(num_tgt_entries: Int, num_tgt_cycles: Int) extends Module next_tail_pointer := tail_pointer - UInt(1) } for (i <- 1 until num_tgt_cycles - 1){ - val next_reg_val = UInt() + val next_reg_val = Wire(UInt()) aregs(i) := next_reg_val next_reg_val := aregs(i) when(UInt(i) === tail_pointer){ @@ -147,7 +145,7 @@ class FameQueueTracker(num_tgt_entries: Int, num_tgt_cycles: Int) extends Module } } } - val next_reg_val0 = UInt() + val next_reg_val0 = Wire(UInt()) aregs(0) := next_reg_val0 next_reg_val0 := aregs(0) when(UInt(0) === tail_pointer){ @@ -180,7 +178,7 @@ class FameQueueTracker(num_tgt_entries: Int, num_tgt_cycles: Int) extends Module next_reg_val0 := aregs(1) } } - val next_reg_val_last = UInt() + val next_reg_val_last = Wire(UInt()) aregs(num_tgt_cycles - 1) := next_reg_val_last next_reg_val_last := aregs(num_tgt_cycles - 1) when(UInt(num_tgt_cycles - 1) === tail_pointer){ @@ -200,28 +198,28 @@ class FameQueueTracker(num_tgt_entries: Int, num_tgt_cycles: Int) extends Module } io.full := tail_pointer === UInt(num_tgt_cycles) io.empty := tail_pointer === UInt(0) - io.entry_avail := aregs(0) != UInt(0) + io.entry_avail := ( aregs(0) =/= UInt(0) ) } class RegIO[T <: Data](data: T) extends Bundle { - val bits = data.clone.asOutput + val bits = data.cloneType.asOutput } class Fame1WrapperIO(num_queues: Int, num_regs: Int, num_debug: Int) extends Bundle { - val queues = Vec.fill(num_queues){ new FameDecoupledIO(Bits())} - val regs = Vec.fill(num_regs){ new DecoupledIO(Bits())} - val debug = Vec.fill(num_debug){Bits()} + val queues = Vec(num_queues, new FameDecoupledIO(Bits())) + val regs = Vec(num_regs, new DecoupledIO(Bits())) + val debug = Vec(num_debug, Bits()) } class Fame1Wrapper(f: => Module) extends Module { def transform(isTop: Boolean, module: Module, parent: Module): Unit = { Fame1Transform.fame1Modules += module - val isFire = Bool(INPUT) + val isFire = Wire(Bool(INPUT)) module.addPin(isFire, "is_fire") Fame1Transform.fireSignals(module) = isFire if(!isTop){ - Predef.assert(Fame1Transform.fireSignals(parent) != null) + Predef.assert(Fame1Transform.fireSignals(parent) != null, ChiselError.error("Internal Error: Fame1Transform")) isFire := Fame1Transform.fireSignals(parent) } for(submodule <- module.children){ @@ -267,7 +265,7 @@ class Fame1Wrapper(f: => Module) extends Module { fame1Decoupled.flip() fame1Decoupled.target.ready := decoupled.ready decoupled.valid := fame1Decoupled.target.valid - val decoupledBitsClone = decoupled.bits.clone() + val decoupledBitsClone = decoupled.bits.cloneType() decoupled.bits := decoupledBitsClone.fromBits(fame1Decoupled.target.bits) } else { decoupled.ready := fame1Decoupled.target.ready @@ -282,7 +280,7 @@ class Fame1Wrapper(f: => Module) extends Module { val fame1RegIO = io.regs(reg_counter) if (is_flip) { fame1RegIO.flip() - val regBitsClone = reg.bits.clone() + val regBitsClone = reg.bits.cloneType() reg.bits := regBitsClone.fromBits(fame1RegIO.bits) } else { fame1RegIO.bits := reg.bits.toBits @@ -292,8 +290,8 @@ class Fame1Wrapper(f: => Module) extends Module { } case _ => { if (name != "is_fire") { - Predef.assert(ioNode.isInstanceOf[Bits]) - val elementClone = ioNode.clone + Predef.assert(ioNode.isInstanceOf[Bits], ChiselError.error("ioNode isn't is_fire or instance of Bits")) + val elementClone = Wire(ioNode.cloneType) elementClone.isIo = true elementClone.setName(name) DebugIOs(name) = elementClone diff --git a/src/main/scala/Fill.scala b/src/main/scala/Fill.scala index 98bbb579..34c10f98 100644 --- a/src/main/scala/Fill.scala +++ b/src/main/scala/Fill.scala @@ -1,5 +1,5 @@ /* - Copyright (c) 2011, 2012, 2013, 2014 The Regents of the University of + Copyright (c) 2011 - 2016 The Regents of the University of California (Regents). All Rights Reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: @@ -29,21 +29,31 @@ */ package Chisel -import Fill._ -import Lit._ +/** Fill fans out a Node to multiple copies */ object Fill { + /** Fan out mod n times */ def apply(n: Int, mod: Bool): UInt = n match { case 0 => UInt(width=0) case 1 => mod case x if n > 1 => UInt(0,n) - mod case _ => throw new IllegalArgumentException(s"n (=$n) must be nonnegative integer.") } + /** Fan out mod n times */ def apply(n: Int, mod: UInt): UInt = UInt(NodeFill(n, mod)) - def apply(mod: UInt, n: Int): UInt = apply(n, mod) + /** Fan out mod n times */ + @deprecated("Fill(mod: UInt, n: Int) is deprecated. Please use Fill(n: Int, mode: UInt) instead.", "3.0") + def apply(mod: UInt, n: Int): UInt = { + ChiselError.check("Chisel3 compatibility: Fill(mod: UInt, n:Int) is deprecated. Please use Fill(n: Int, mod: UInt) instead.", Version("3.0")) + apply(n, mod) + } } +/** NodeFill copys an instance of a Node multiple times or fans it out + * Any change to a Node such as setting inputs or changing width will is applied to all of them */ object NodeFill { + /** @param n number of times to copy 'mod' + * @param mod the node to copy */ def apply(n: Int, mod: Node): Node = { val w = mod.widthW n match { @@ -54,11 +64,11 @@ object NodeFill { Multiplex(mod, Literal((BigInt(1) << x) - 1, x), Literal(0, x)) } else { /* Build up a Concatenate tree for more ILP in simulation. */ - val p2 = Array.ofDim[Node](log2Up(x+1)) + val p2 = Array.ofDim[Node](log2Up(x + 1)) p2(0) = mod for (i <- 1 until p2.length) - p2(i) = Concatenate(p2(i-1), p2(i-1)) - Concatenate((0 until log2Up(x+1)).filter(i => (x & (1 << i)) != 0).map(p2(_))) + p2(i) = Concatenate(p2(i-1), p2(i - 1)) + Concatenate((0 until log2Up(x + 1)).filter(i => (x & (1 << i)) != 0).map(p2(_))) } case _ => throw new IllegalArgumentException(s"n (=$n) must be nonnegative integer.") } diff --git a/src/main/scala/Fixed.scala b/src/main/scala/Fixed.scala new file mode 100644 index 00000000..adbbebd1 --- /dev/null +++ b/src/main/scala/Fixed.scala @@ -0,0 +1,228 @@ +/* + Copyright (c) 2011, 2012, 2013, 2014 The University of Sydney. + All Rights Reserved. Redistribution and use in source and + binary forms, with or without modification, are permitted + provided that the following conditions are met: + + * Redistributions of source code must retain the above + copyright notice, this list of conditions and the following + two paragraphs of disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + two paragraphs of disclaimer in the documentation and/or other materials + provided with the distribution. + * Neither the name of the Regents nor the names of its contributors + may be used to endorse or promote products derived from this + software without specific prior written permission. + + IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, + SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, + ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF + REGENTS HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF + ANY, PROVIDED HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION + TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR + MODIFICATIONS. +*/ + +package Chisel + +import Node._ +import ChiselError._ + +/** Factory methods for [[Chisel.Fixed Fixed]] */ +object Fixed { + /** Convert a double to fixed point with a specified fractional width + * @param x Double to convert + * @param fracWidth the integer fractional width to use in the conversion + * @return A BigInt representing the bits in the fixed point + */ + def toFixed(x : Double, fracWidth : Int) : BigInt = BigInt(scala.math.round(x*scala.math.pow(2, fracWidth))) + /** Convert a Float to fixed point with a specified fractional width + * @param x Float to convert + * @param fracWidth the integer fractional width to use in the conversion + * @return A BigInt representing the bits in the fixed point + */ + def toFixed(x : Float, fracWidth : Int) : BigInt = BigInt(scala.math.round(x*scala.math.pow(2, fracWidth))) + /** Convert an Int to fixed point with a specified fractional width + * @param x Double to convert + * @param fracWidth the integer fractional width to use in the conversion + * @return A BigInt representing the bits in the fixed point + */ + def toFixed(x : Int, fracWidth : Int) : BigInt = BigInt(scala.math.round(x*scala.math.pow(2, fracWidth))) + + /** Create a Fixed [[Chisel.Node]] with specified width and fracWidth + * @param x An Int to convert to fixed point + * @param width the total number of bits to use in the representation + * @param fracWidth the integer fractional width to use in the conversion + * @return A fixed node with the specified parameters + */ + def apply(x : Int, width : Int, fracWidth : Int) : Fixed = apply(toFixed(x, fracWidth), width, fracWidth) + /** Create a Fixed [[Chisel.Node]] with specified width and fracWidth + * @param x An Float to convert to fixed point + * @param width the total number of bits to use in the representation + * @param fracWidth the integer fractional width to use in the conversion + * @return A fixed node with the specified parameters + */ + def apply(x : Float, width : Int, fracWidth : Int) : Fixed = apply(toFixed(x, fracWidth), width, fracWidth) + /** Create a Fixed [[Chisel.Node]] with specified width and fracWidth + * @param x An Double to convert to fixed point + * @param width the total number of bits to use in the representation + * @param fracWidth the integer fractional width to use in the conversion + * @return A fixed node with the specified parameters + */ + def apply(x : Double, width : Int, fracWidth : Int) : Fixed = apply(toFixed(x, fracWidth), width, fracWidth) + /** Create a Fixed [[Chisel.Node]] with specified width and fracWidth + * @param x An BigInt to use literally as the fixed point bits + * @param width the total number of bits to use in the representation + * @param fracWidth the integer fractional width to use + * @return A fixed node with the specified parameters + */ + def apply(x : BigInt, width : Int, fracWidth : Int) : Fixed = { + val res = Lit(x, width){Fixed()} + res.fractionalWidth = fracWidth + res + } + + /** Create a Fixed I/O [[Chisel.Node]] with specified width and fracWidth + * @param dir Direction of I/O for the node, eg) INPUT or OUTPUT + * @param width the total number of bits to use in the representation + * @param fracWidth the integer fractional width to use + * @return A fixed node with the specified parameters + */ + def apply(dir : IODirection = null, width : Int = -1, fracWidth : Int = -1) : Fixed = { + val res = new Fixed(fracWidth); + res.create(dir, width) + res + } +} + +/** A Fixed point data type + * @constructor Use [[Chisel.Fixed$ Fixed]] object to create rather than this class directly */ +class Fixed(var fractionalWidth : Int = 0) extends Bits with Num[Fixed] { + type T = Fixed + + /** Convert a Node to a Fixed data type with the same fractional width as this instantiation */ + override def fromNode(n : Node): this.type = { + val res = Fixed(OUTPUT).asTypeFor(n).asInstanceOf[this.type] + res.fractionalWidth = this.getFractionalWidth() + res + } + + /** Create a Fixed representation from an Int */ + override def fromInt(x : Int) : this.type = Fixed(x, this.getWidth(), this.getFractionalWidth()).asInstanceOf[this.type] + + /** clone this Fixed instantiation */ + override def cloneType: this.type = Fixed(this.dir, this.getWidth(), this.getFractionalWidth()).asInstanceOf[this.type]; + + override protected def colonEquals(that : Bits): Unit = that match { + case f: Fixed => { + val res = if((f.getWidth() == this.getWidth()*2) && (f.getFractionalWidth() == this.getFractionalWidth()*2)) { + truncate(f, this.getFractionalWidth()) + } else { + checkAligned(f) + f + } + super.colonEquals(res) + } + case _ => illegalAssignment(that) + } + + def getFractionalWidth() : Int = this.fractionalWidth + + private def truncate(f : Fixed, truncateAmount : Int) : Fixed = fromSInt(f.toSInt >> UInt(truncateAmount)) + private def truncate(f : SInt, truncateAmount : Int) : SInt = f >> UInt(truncateAmount) + + /** Ensure two Fixed point data types have the same fractional width, Error if not */ + private def checkAligned(b : Fixed) { + if(this.getFractionalWidth() != b.getFractionalWidth()) ChiselError.error(this.getFractionalWidth() + " Fractional Bits does not match " + b.getFractionalWidth()) + if(this.getWidth() != b.getWidth()) ChiselError.error(this.getWidth() + " Width does not match " + b.getWidth()) + } + + /** Convert a SInt to a Fixed by reinterpreting the Bits */ + private def fromSInt(s : SInt, width : Int = this.getWidth(), fracWidth : Int = this.getFractionalWidth()) : Fixed = { + val res = chiselCast(s){Fixed()} + res.fractionalWidth = fracWidth + res.width = width + res + } + + // Order Operators + def > (b : Fixed) : Bool = { + checkAligned(b) + this.toSInt > b.toSInt + } + + def < (b : Fixed) : Bool = { + checkAligned(b) + this.toSInt < b.toSInt + } + + def >= (b : Fixed) : Bool = { + checkAligned(b) + this.toSInt >= b.toSInt + } + + def <= (b : Fixed) : Bool = { + checkAligned(b) + this.toSInt <= b.toSInt + } + + def === (b : Fixed) : Bool = { + checkAligned(b) + this.toSInt === b.toSInt + } + + def >> (b : UInt) : Fixed = { + fromSInt(this.toSInt >> b) + } + + // Arithmetic Operators + def unary_-() : Fixed = Fixed(0, this.getWidth(), this.getFractionalWidth()) - this + + def + (b : Fixed) : Fixed = { + checkAligned(b) + fromSInt(this.toSInt + b.toSInt) + } + + def - (b : Fixed) : Fixed = { + checkAligned(b) + fromSInt(this.toSInt - b.toSInt) + } + + /** Multiply increasing the Bit Width */ + def * (b : Fixed) : Fixed = { + checkAligned(b) + val temp = this.toSInt * b.toSInt + fromSInt(temp, temp.getWidth(), this.getFractionalWidth()*2) + } + + /** Multiply with one bit of rounding */ + def *& (b : Fixed) : Fixed = { + checkAligned(b) + val temp = this.toSInt * b.toSInt + val res = temp + ((temp & UInt(1)< "" + x.value + "'" + cnode.needWidth() @@ -79,12 +65,12 @@ class FloBackend extends Backend { super.emitRef(node) } // } else { - // "" + node.litOf.value + // "" + node.litValue() // } } def emitRef(node: Node, sum_to: Node, other: Node): String = { - // if (node.litOf == null) { + // if (node.litOpt == None) { node match { case x: Literal => "" + x.value + "'" + (sum_to.needWidth() - other.needWidth()) @@ -99,7 +85,7 @@ class FloBackend extends Backend { super.emitRef(node) } // } else { - // "" + node.litOf.value + // "" + node.litValue() // } } @@ -149,11 +135,11 @@ class FloBackend extends Backend { case x: Bits => if (x.inputs.length == 1) { - // println("NAME " + x.name + " DIR " + x.dir + " COMP " + x.componentOf + " TOP-COMP " + Driver.topComponent) + // println("NAME " + x.name + " DIR " + x.dir + " COMP " + x.componentOf + " TOP-COMP " + topMod) if (node.isInObject && x.inputs.length == 1) { - // ((x.consumers.length > 1 && x.consumers.forall(x => x.componentOf == Driver.topComponent)) || + // ((x.consumers.length > 1 && x.consumers.forall(x => x.componentOf == topMod)) || // TODO: SHOULD HANDLE TOP OUTPUTS THAT ARE ALSO FANNED OUT -- NEED EXTRA NODE - if (x.dir == OUTPUT && x.component == Driver.topComponent) + if (x.dir == OUTPUT && x.component == topMod) emitDec(x) + (if (isRnd) "eat" else ("out'" + x.needWidth())) + " " + emitRef(x.inputs(0)) + "\n" else emitDec(x) + "mov" + " " + emitRef(x.inputs(0)) + "\n" @@ -201,27 +187,13 @@ class FloBackend extends Backend { } } - def renameNodes(nodes: ArrayBuffer[Node]) { - val comp = Driver.topComponent - for (m <- nodes) { - m match { - case _: Literal => - case _ if m.named && (m != comp.defaultResetPin) && m.component != null => - // only modify name if it is not the reset signal or not in top component - if (m.name != "reset" || m.component != comp) - m.name = m.component.getPathName(":") + "::" + m.name - case _ => - } - } - } - override def elaborate(c: Module): Unit = { super.elaborate(c) flattenAll ChiselError.checkpoint() - renameNodes(Driver.orderedNodes) + renameNodes(Driver.orderedNodes, ":") if (Driver.isReportDims) { val (numNodes, maxWidth, maxDepth) = findGraphDims // ChiselError.info("NUM " + numNodes + " MAX-WIDTH " + maxWidth + " MAX-DEPTH " + maxDepth); @@ -234,28 +206,21 @@ class FloBackend extends Backend { out.close(); } - override def compile(c: Module, flagsIn: String) { - val flags = if (flagsIn == null) "-O2" else flagsIn - - val chiselENV = java.lang.System.getenv("CHISEL") + override def compile(c: Module, flagsIn: Option[String]) { + val flags = flagsIn getOrElse "-O2" val allFlags = flags + " -I../ -I" + chiselENV + "/csrc/" val dir = Driver.targetDir + "/" - def run(cmd: String) { - val bashCmd = Seq("bash", "-c", cmd) - val c = bashCmd.! - ChiselError.info(cmd + " RET " + c) - } def build(name: String) { - val mweCmd = ArrayBuffer("flo-mwe", "--width", "32", "--depth", "64", "--input", dir + name + ".flo", "--output", dir + name + ".mwe.flo") + val mweCmd = List("flo-mwe", "--width", "32", "--depth", "64", "--input", dir + name + ".flo", "--output", dir + name + ".mwe.flo") println("EXPANDING WITH " + mweCmd) run(mweCmd.mkString(" ")) - val cmd = ArrayBuffer(floDir + "lay", "-is-console") - cmd ++= ArrayBuffer(":dims", DreamerConfiguration.numCols.toString() + "," + DreamerConfiguration.numRows.toString()) - cmd ++= ArrayBuffer("<", dir + name + ".mwe.flo", "|") - cmd ++= ArrayBuffer(floDir + "fix-sched", ">", dir + name + ".hex") + val cmd = List(floDir + "lay", "-is-console") ++ + List(":dims", DreamerConfiguration.numCols.toString() + "," + DreamerConfiguration.numRows.toString()) ++ + List("<", dir + name + ".mwe.flo", "|") ++ + List(floDir + "fix-sched", ">", dir + name + ".hex") val cmdString = cmd.mkString(" ") println("BUILDING " + cmdString) - run(cmdString) + if (!run(cmdString)) throwException("failed to build flo") } build(c.name) } diff --git a/src/main/scala/IO.scala b/src/main/scala/IO.scala index e4a0ebf0..7cd6c02d 100644 --- a/src/main/scala/IO.scala +++ b/src/main/scala/IO.scala @@ -1,5 +1,5 @@ /* - Copyright (c) 2011, 2012, 2013, 2014 The Regents of the University of + Copyright (c) 2011 - 2016 The Regents of the University of California (Regents). All Rights Reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: @@ -30,8 +30,21 @@ package Chisel -trait IODirection; +abstract class IODirection { + def toString: String +} -object INPUT extends IODirection; +/** Define the IODirection INPUT */ +object INPUT extends IODirection { + override def toString = "INPUT" +} -object OUTPUT extends IODirection; +/** Define the IODirection OUTPUT */ +object OUTPUT extends IODirection { + override def toString = "OUTPUT" +} + +/** Define the IODirection NODIR */ +object NODIR extends IODirection { + override def toString = "NODIR" +} diff --git a/src/main/scala/ImplicitConversions.scala b/src/main/scala/ImplicitConversions.scala index 1e68e974..09dc0416 100644 --- a/src/main/scala/ImplicitConversions.scala +++ b/src/main/scala/ImplicitConversions.scala @@ -1,5 +1,5 @@ /* - Copyright (c) 2011, 2012, 2013, 2014 The Regents of the University of + Copyright (c) 2011 - 2016 The Regents of the University of California (Regents). All Rights Reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: @@ -33,6 +33,7 @@ package Chisel object ImplicitConversions { implicit def intToUInt(x: Int): UInt = UInt(x) + @deprecated("It is not advisable to use implicit conversion between Boolean and Bool", "3") implicit def booleanToBool(x: Boolean): Bool = Bool(x) // These ones for the lazy programmer. diff --git a/src/main/scala/Insert.scala b/src/main/scala/Insert.scala index 39dbd4bd..5a02801c 100644 --- a/src/main/scala/Insert.scala +++ b/src/main/scala/Insert.scala @@ -1,5 +1,5 @@ /* - Copyright (c) 2011, 2012, 2013, 2014 The Regents of the University of + Copyright (c) 2011 - 2016 The Regents of the University of California (Regents). All Rights Reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: @@ -32,15 +32,18 @@ package Chisel class Insert(tgt: Bits, bit: UInt, length: Int) extends proc { override def procAssign(src: Node): Unit = { - if (tgt.next == null) { - ChiselError.error("Subword assignment requires a default value to have been assigned") - } else { - val mask = UInt((BigInt(1) << length) - 1, length) - val shiftedMask = (mask << bit) | (tgt ^ tgt) // zero-extend to tgt.width - val fill = - if (length == 1) src.asInstanceOf[Bits].toBool.toSInt & shiftedMask - else (src.asInstanceOf[Bits] & mask) << bit - tgt := UInt(tgt.next) & ~shiftedMask | fill + tgt.nextOpt match { + case None => ChiselError.error("Subword assignment requires a default value to have been assigned") + case Some(next) => + val mask = UInt((BigInt(1) << length) - 1, length) + val shiftedMask = (mask << bit).zext // zero-extend to tgt.width + val fill = + if (length == 1) src.asInstanceOf[Bits].toBool.toSInt & shiftedMask + else (src.asInstanceOf[Bits] & mask) << bit + tgt := UInt(next) & ~shiftedMask | fill } } + + // Chisel3 - this node contains data - used for verifying Wire() wrapping + override def isTypeOnly = false } diff --git a/src/main/scala/JHFormat.scala b/src/main/scala/JHFormat.scala index e177835e..97c39e78 100644 --- a/src/main/scala/JHFormat.scala +++ b/src/main/scala/JHFormat.scala @@ -1,5 +1,5 @@ /* - Copyright (c) 2011, 2012, 2013, 2014 The Regents of the University of + Copyright (c) 2011 - 2016 The Regents of the University of California (Regents). All Rights Reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: @@ -29,10 +29,7 @@ */ package Chisel -import scala.collection.mutable.HashMap import scala.collection.mutable.ArrayBuffer -import scala.io.Source -import java.io._ object JHFormat { type Space = ArrayBuffer[(String,Param[Any],Int)] diff --git a/src/main/scala/Lit.scala b/src/main/scala/Lit.scala index 88f6ad66..b4711549 100644 --- a/src/main/scala/Lit.scala +++ b/src/main/scala/Lit.scala @@ -1,5 +1,5 @@ /* - Copyright (c) 2011, 2012, 2013, 2014 The Regents of the University of + Copyright (c) 2011 - 2016 The Regents of the University of California (Regents). All Rights Reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: @@ -29,40 +29,97 @@ */ package Chisel -import scala.math.log -import scala.math.abs -import scala.math.ceil -import scala.math.max -import scala.math.min -import Literal._ -import ChiselError._ +import scala.math.{log, abs, ceil, max, min} /* Factory for literal values to be used by Bits and SInt factories. */ +/** A factory for literal values */ object Lit { + /** Create a Lit value + * @tparam T type to create Lit of + * @param n a string representing the value of the literal + * format is Bxxxx where B is a single char base and xxx is the number in that base + * base can be: + * - h for hex + * - d for decimal + * - o for octal + * - b for binary + * @param gen a function generating the type to use + * @example {{{ Lit[UInt]("21010")(UInt(width=4)) }}} */ def apply[T <: Bits](n: String)(gen: => T): T = { makeLit(Literal(n, -1))(gen) } + /** Create a Lit Value + * @tparam T type to create Lit of + * @param n string representing value of the Lit + * format is Bxxxx where B is a single char base and xxx is the number in that base + * base can be: + * - h for hex + * - d for decimal + * - o for octal + * - b for binary + * @param gen a function generating the type to use + * @example {{{ Lit[UInt]("21010", 4)(UInt()) }}} */ def apply[T <: Bits](n: String, width: Int)(gen: => T): T = { makeLit(Literal(n, width))(gen) } + /** Create a Lit Value + * @tparam T type to create Lit of + * @param n string representing value of the Lit in the base specified + * @param base a character representing the base + * base can be: + * - h for hex + * - d for decimal + * - o for octal + * - b for binary + * @param gen a function generating the type to use + * @example {{{ Lit[UInt]("987", 'a')(UInt()) }}} */ def apply[T <: Bits](n: String, base: Char)(gen: => T): T = { makeLit(Literal(-1, base, n))(gen) } + /** Create a Lit Value + * @tparam T type to create Lit of + * @param n string representing value of the Lit in the base specified + * @param base a character representing the base + * base can be: + * - h for hex + * - d for decimal + * - o for octal + * - b for binary + * @param width force the width of the Lit created + * @param gen a function generating the type to use + * @example {{{ Lit[UInt]("987", 'a')(UInt()) }}} */ def apply[T <: Bits](n: String, base: Char, width: Int)(gen: => T): T = { makeLit(Literal(width, base, n))(gen) } + /** Create a Lit Value + * @tparam T type to create Lit of + * @param n a BigInt for the bits of the Lit + * @param gen a function generating the type to use + * @example {{{ Lit[UInt](BigInt(987))(UInt()) }}} */ def apply[T <: Bits](n: BigInt)(gen: => T): T = { makeLit(Literal(n, signed = gen.isInstanceOf[SInt]))(gen) } + /** Create a Lit Value + * @tparam T type to create Lit of + * @param n a BigInt for the bits of the Lit + * @param width force the width of the Lit created + * @param gen a function generating the type to use + * @example {{{ Lit[UInt](BigInt(987), 12)(UInt()) }}} */ def apply[T <: Bits](n: BigInt, width: Int)(gen: => T): T = { makeLit(Literal(n, width, signed = gen.isInstanceOf[SInt]))(gen) } + /** A function to make a Lit from a Literal + * @tparam T type to create Lit of + * @param x a Literal to transform into a Lit + * @param gen a function generating the type to use + * @return a Lit of type T with the value of x + */ def makeLit[T <: Bits](x: Literal)(gen: => T): T = { gen.fromNode(x) } @@ -70,46 +127,33 @@ object Lit { object Literal { - private def bigMax(x: BigInt, y: BigInt): BigInt = if (x > y) x else y; + private def bigMax(x: BigInt, y: BigInt): BigInt = if (x > y) x else y + /** Get the number of bits in x */ def sizeof(x: BigInt): Int = { - val y = bigMax(BigInt(1), x.abs).toDouble; - val res = max(1, (ceil(log(y + 1)/log(2.0))).toInt); + val y = bigMax(BigInt(1), x.abs).toDouble + val res = max(1, (ceil(log(y + 1)/log(2.0))).toInt) res - } + } @deprecated("This part of the implementation is not used anymore?", "2.0") def signedsizeof(x: BigInt, width: Int = -1, signed: Boolean = false): (Int, String) = { - var count = 0; - var n = x; - var resNum = BigInt(0); + var count = 0 + var n = x + var resNum = BigInt(0) while((x > 0 && n != 0) || (x < 0 && n != -1)){ - resNum += (n & BigInt(1)) << count; - count += 1; - n >>= 1; + resNum += (n & BigInt(1)) << count + count += 1 + n >>= 1 } - var resWidth = count + ( - if(x == -1) { - 2 - } else if(signed || x == 0) { - 1 - } else { - 0 - }); - resNum += ( - if(x == -1) { - 3 - } else if(x < 0) { - 1 << (resWidth-1) - } else { - 0 - }); + var resWidth = count + (if(x == -1) 2 else if(signed || x == 0) 1 else 0) + resNum += (if(x == -1) 3 else if(x < 0) 1 << (resWidth-1) else 0) if(width != -1) { if(width < resWidth) { - ChiselError.error({"width " + width + " is too small for literal " + x}); + ChiselError.error({"width " + width + " is too small for literal " + x}) } else if(width > resWidth && x < 0) { while(width > resWidth){ - resWidth += 1; - resNum += 1 << (resWidth-1); + resWidth += 1 + resNum += 1 << (resWidth-1) } } else { resWidth = width @@ -119,164 +163,158 @@ object Literal { } private def sizeof(base: Char, x: String): Int = { - var res = 0; - var first = true; - val size = - if(base == 'b') { - 1 - } else if(base == 'h') { - 4 - } else if(base == 'o') { - 3 - } else { - -1 - } + var res = 0 + var first = true + val size = if(base == 'b') 1 else if(base == 'h') 4 else if(base == 'o') 3 else -1 for(c <- x) if (c == '_') { } else if(first) { - first = false; - res += sizeof(c.asDigit); + first = false + res += sizeof(c.asDigit) } else if (c != '_') { - res += size; + res += size } res } - val hexNibbles = "0123456789abcdef"; + val hexNibbles = "0123456789abcdef" + /** Convert 4 chars in a binary string to a hex char starting at 'off' */ def toHexNibble(x: String, off: Int): Char = { - var res = 0; + var res = 0 for (i <- 0 until 4) { - val idx = off + i; - val c = if (idx < 0) '0' else x(idx); - res = 2 * res + (if (c == '1') 1 else 0); + val idx = off + i + val c = if (idx < 0) '0' else x(idx) + res = 2 * res + (if (c == '1') 1 else 0) } hexNibbles(res) } - val pads = Vector(0, 3, 2, 1); + // TODO should be private? + val pads = Vector(0, 3, 2, 1) + /** Convert a binary string to hex */ def toHex(x: String): String = { - var res = ""; - val numNibbles = (x.length-1) / 4 + 1; - val pad = pads(x.length % 4); + var res = new StringBuilder + val numNibbles = (x.length-1) / 4 + 1 + val pad = pads(x.length % 4) for (i <- 0 until numNibbles) { - res += toHexNibble(x, i*4 - pad); + res append toHexNibble(x, i*4 - pad) } - res + res.result } + /** Convert a hex string to a BigInt */ def toLitVal(x: String): BigInt = { BigInt(x.substring(2, x.length), 16) } - + /** convert a string to a BigInt with base shamt */ def toLitVal(x: String, shamt: Int): BigInt = { - var res = BigInt(0); - for(c <- x) - if(c != '_'){ - if(!(hexNibbles + "?").contains(c.toLower)) ChiselError.error({"Literal: " + x + " contains illegal character: " + c}); - res = res * shamt + c.asDigit; - } - res - } - - def removeUnderscore(x: String): String = { - var res = "" - for(c <- x){ - if(c != '_'){ - res = res + c - } + var res = BigInt(0) + for(c <- x if c != '_') { + if (!(hexNibbles + "?").contains(c.toLower)) ChiselError.error("Literal: " + x + " contains illegal character: " + c) + res = res * shamt + c.asDigit } res } + /** remove all underscores from a string */ + def removeUnderscore(x: String): String = x filterNot (_ == '_') + + /** Parse a binary string with don't cares as '?' + * @param x input binary string + * @return a tuple of (bits, mask, width) + * bits is the string with '?' replaced with '0' + * mask is '0' for all '?' in the string but '1' otherwise + * width is the number of bits */ def parseLit(x: String): (String, String, Int) = { - var bits = ""; - var mask = ""; - var width = 0; - for (d <- x) { - if (d != '_') { - if(!"01?".contains(d)) ChiselError.error({"Literal: " + x + " contains illegal character: " + d}); - width += 1; - mask = mask + (if (d == '?') "0" else "1"); - bits = bits + (if (d == '?') "0" else d.toString); - } + val bits = new StringBuilder + val mask = new StringBuilder + var width = 0 + for (d <- x if d != '_') { + if(!"01?".contains(d)) ChiselError.error("Literal: " + x + " contains illegal character: " + d) + width += 1 + mask append (if (d == '?') '0' else '1') + bits append (if (d == '?') '0' else d) } - (bits, mask, width) + (bits.result, mask.result, width) } - def stringToVal(base: Char, x: String): BigInt = { - if(base == 'x') { - toLitVal(x); - } else if(base == 'd') { - BigInt(x.toInt) - } else if(base == 'h') { - toLitVal(x, 16) - } else if(base == 'b') { - toLitVal(x, 2) - } else if(base == 'o') { - toLitVal(x, 8) - } else { - BigInt(-1) - } + /** Convert a string to a BigInt + * @param base is: + * - h for hex + * - d for decimal + * - o for octal + * - b for binary + */ + def stringToVal(base: Char, x: String): BigInt = base match { + case 'x' => toLitVal(x) + case 'd' => BigInt(x.toInt) + case 'h' => toLitVal(x, 16) + case 'b' => toLitVal(x, 2) + case 'o' => toLitVal(x, 8) + case _ => BigInt(-1) } - /** Derive the bit length for a Literal - * - */ + /** Derive the bit length for a Literal */ def bitLength(b: BigInt): Int = { // Check for signedness // We have seen unexpected values (one too small) when using .bitLength on negative BigInts, // so use the positive value instead. val usePositiveValueForBitLength = false - (if (usePositiveValueForBitLength && b < 0) { - -b - } else { - b - }).bitLength + (if (usePositiveValueForBitLength && b < 0) -b else b).bitLength } /** Creates a *Literal* instance from a scala integer. */ def apply(x: BigInt, width: Int = -1, signed: Boolean = false): Literal = { - val res = new Literal(); + val res = new Literal() // Check for signedness // We get unexpected values (one too small) when using .bitLength on negative BigInts, // so use the positive value instead. val bl = bitLength(x) - val xWidth = if (signed) { - bl + 1 - } else { - max(bl, 1) - } - val w = if(width == -1) xWidth else width + val xWidth = if (signed) bl + 1 else max(bl, 1) + val w = if (width == -1) xWidth else width val xString = (if (x >= 0) x else (BigInt(1) << w) + x).toString(16) if(xWidth > width && width != -1) { // Is this a zero-width wire with value 0 if (!(x == 0 && width == 0 && Driver.isSupportW0W)) { - ChiselError.error({"width " + width + " is too small for literal " + x + ". Smallest allowed width is " + xWidth}); + ChiselError.error({"width " + width + " is too small for literal " + x + ". Smallest allowed width is " + xWidth}) } } - res.init("0x" + xString, w); + res.init("0x" + xString, w) res.hasInferredWidth = width == -1 res } - /** Creates a *Literal* instance from a scala string. The first character + /** Creates a [[Chisel.Literal Literal]] instance from a scala string. The first character of the string indicates the base for the suffix characters. + * base can be: + * - h for hex + * - d for decimal + * - o for octal + * - b for binary */ def apply(n: String, width: Int): Literal = - apply(width, n(0), n.substring(1, n.length)); + apply(width, n(0), n.substring(1, n.length)) + /** Create a Literal value + * @param width force the width of the Literal + * @param base can be: + * - h for hex + * - d for decimal + * - o for octal + * - b for binary + * @param literal is a string representing the number */ def apply(width: Int, base: Char, literal: String): Literal = { if (!"dhbo".contains(base)) { - ChiselError.error("no base specified"); + ChiselError.error("no base specified") } - val res = new Literal(); + val res = new Literal() if(width == -1) { - res.init(removeUnderscore(literal), sizeof(base, literal)); + res.init(removeUnderscore(literal), sizeof(base, literal)) } else { - res.init(removeUnderscore(literal), width); + res.init(removeUnderscore(literal), width) if(width < sizeof(base, literal)) { - ChiselError.error({"width " + width + " is too small for literal: " + res + " with min width " + sizeof(base, literal)}) + ChiselError.error("width " + width + " is too small for literal: " + res + " with min width " + sizeof(base, literal)) } } - res.base = base; + res.base = base if (base == 'b') res.isZ = literal.contains('?') res } @@ -287,11 +325,11 @@ object Literal { */ class Literal extends Node { var hasInferredWidth = false - var isZ = false; - var base = 'x'; - lazy val value: BigInt = stringToVal(base, name); - override def litOf: Literal = this - override def toString: String = name; + var isZ = false + var base = 'x' + lazy val value: BigInt = Literal.stringToVal(base, name) + override def litOpt: Option[Literal] = Some(this) + override def toString: String = name override lazy val isInVCD: Boolean = false override def canCSE: Boolean = true @@ -300,4 +338,6 @@ class Literal extends Node { case x: Literal => value == x.value && isZ == x.isZ && widthW == x.widthW case _ => false } + // Chisel3 - this node contains data - used for verifying Wire() wrapping + override def isTypeOnly = false } diff --git a/src/main/scala/Log2.scala b/src/main/scala/Log2.scala index a337d575..fc8a9fb8 100644 --- a/src/main/scala/Log2.scala +++ b/src/main/scala/Log2.scala @@ -1,5 +1,5 @@ /* - Copyright (c) 2011, 2012, 2013, 2014 The Regents of the University of + Copyright (c) 2011 - 2016 The Regents of the University of California (Regents). All Rights Reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: @@ -30,22 +30,30 @@ package Chisel +// TODO: Should be UInt rather than Bits as input must be positive +/** Compute Log2 with truncation of a UInt in hardware using a Mux Tree + * An alternative interpretation is it computes the minimum number of bits needed to represent x + * @example + * {{{ data_out := Log2(data_in) }}} + * @note Truncation is used so Log2(UInt(12412)) = 13*/ object Log2 { def apply(x: Bits): UInt = UInt().asTypeFor(new Log2(x)) + /** Compute the Log2 on the least significant n bits of x */ def apply(x: Bits, n: Int): UInt = apply(x(n-1,0)) } -/** Returns the bit position of the trailing 1 in the input vector - with the assumption that multiple bits of the input bit vector can be set +/** @return the bit position of the trailing 1 in the input vector + * with the assumption that multiple bits of the input bit vector can be set + * @example {{{ data_out := PriorityEncoder(data_in) }}} */ object PriorityEncoder { - def apply(in: Iterable[Bool]): UInt = PriorityMux(in, (0 until in.size).map(UInt(_))) + def apply(in: Seq[Bool]): UInt = PriorityMux(in, (0 until in.size).map(UInt(_))) def apply(in: Bits): UInt = UInt().asTypeFor(new PriorityEncoder(in)) } -/** Does the inverse of UIntToOH. - */ +/** Converts from One Hot Encoding to a UInt indicating which bit is active + * This is the inverse of [[Chisel.UIntToOH UIntToOH]]*/ object OHToUInt { def apply(in: Seq[Bool]): UInt = apply(Vec(in)) @@ -53,6 +61,8 @@ object OHToUInt def apply(in: Bits): UInt = UInt().asTypeFor(new OHToUInt(in)) } +// TODO: make protected or private? +/** A class defining an Operator which has a output width log2 of the number of input bits */ abstract class Log2Like(x: Bits, name: String) extends Op { val op = name inputs += x @@ -72,6 +82,8 @@ abstract class Log2Like(x: Bits, name: String) extends Op { } } +/** Compute Log2 with truncation + * Use the [[Chisel.Log2$ Log2]] object rather than this class directly*/ class Log2(x: Bits) extends Log2Like(x, "Log2") { override def lower: Node = { val w0 = inputs(0).widthW @@ -84,6 +96,8 @@ class Log2(x: Bits) extends Log2Like(x, "Log2") { } } +/** A class to detect the trailing bit + * Use the [[Chisel.PriorityEncoder$ PriorityEncoder]] object rather than this class directly */ class PriorityEncoder(x: Bits) extends Log2Like(x, "PriEnc") { override def lower: Node = { val w0 = inputs(0).widthW @@ -94,6 +108,8 @@ class PriorityEncoder(x: Bits) extends Log2Like(x, "PriEnc") { } } +/** Converts a One Hot encoding to a UInt + * Use the [[Chisel.OHToUInt$ OHToUInt]] object rather than this class directly */ class OHToUInt(x: Bits) extends Log2Like(x, "OHToUInt") { override def lower: Node = { def doLower(x: Node, length: Int): Node = { diff --git a/src/main/scala/Lookup.scala b/src/main/scala/Lookup.scala index 61d3a1ce..4f3ff9c8 100644 --- a/src/main/scala/Lookup.scala +++ b/src/main/scala/Lookup.scala @@ -1,5 +1,5 @@ /* - Copyright (c) 2011, 2012, 2013, 2014 The Regents of the University of + Copyright (c) 2011 - 2016 The Regents of the University of California (Regents). All Rights Reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: @@ -29,13 +29,14 @@ */ package Chisel -import Node._ -import Literal._ -import scala.collection.mutable.ArrayBuffer object ListLookup { - def apply[T <: Data](addr: UInt, default: List[T], mapping: Array[(UInt, List[T])]): List[T] = { - val map = mapping.map(m => (addr === m._1, m._2)) + def apply[U, T <: Data](addr: UInt, default: List[T], mapping: Array[(U, List[T])]): List[T] = { + val map = mapping.map { + case (x: BitPat, y) => (addr === x, y) + case (x: UInt, y) => (addr === x, y) + case _ => throwException("Not allowed type for mapping") + } default.zipWithIndex map { case (d, i) => map.foldRight(d)((m, n) => Mux(m._1, m._2(i), n)) } @@ -43,6 +44,6 @@ object ListLookup { } object Lookup { - def apply[T <: Bits](addr: UInt, default: T, mapping: Seq[(UInt, T)]): T = + def apply[U, T <: Bits](addr: UInt, default: T, mapping: Seq[(U, T)]): T = ListLookup(addr, List(default), mapping.map(m => (m._1, List(m._2))).toArray).head } diff --git a/src/main/scala/Mem.scala b/src/main/scala/Mem.scala index d55b9366..cd300501 100644 --- a/src/main/scala/Mem.scala +++ b/src/main/scala/Mem.scala @@ -1,5 +1,5 @@ /* - Copyright (c) 2011, 2012, 2013, 2014 The Regents of the University of + Copyright (c) 2011 - 2016 The Regents of the University of California (Regents). All Rights Reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: @@ -29,9 +29,6 @@ */ package Chisel -import ChiselError._ -import Node._ -import scala.reflect._ import scala.collection.mutable.{ArrayBuffer, HashMap} /** *seqRead* means that if a port tries to read the same address that another @@ -39,20 +36,34 @@ import scala.collection.mutable.{ArrayBuffer, HashMap} a LFSR, which returns "1" on its first invocation). */ object Mem { - def apply[T <: Data](out: T, n: Int, seqRead: Boolean = false, - orderedWrites: Boolean = false, - clock: Clock = null): Mem[T] = { - val gen = out.clone + private def construct[T <: Data](n: Int, t: => T, seqRead: Boolean, + orderedWrites: Boolean, + clock: Clock): Mem[T] = { + val gen = t.cloneType Reg.validateGen(gen) val res = new Mem(() => gen, n, seqRead, orderedWrites) - if (!(clock == null)) res.clock = clock - Driver.hasMem = true - Driver.hasSRAM = Driver.hasSRAM | seqRead - if (seqRead) { - Driver.sramMaxSize = math.max(Driver.sramMaxSize, n) - } + if (clock != null) res.clock = Some(clock) res } + + def apply[T <: Data](n: Int, t: => T): Mem[T] = { + construct(n, t, false, false, null) + } + + def apply[T <: Data](n: Int, t: => T, clock: Clock): Mem[T] = { + construct(n, t, false, false, clock) + } + + def apply[T <: Data](out: => T, n: Int, seqRead: Boolean = false, + orderedWrites: Boolean = false, + clock: Clock = null): Mem[T] = { + ChiselError.check("Chisel3 compatibility: Mem(out:T, n:Int) is deprecated. Please use Mem(n:Int, t:T) instead.", Version("3.0")) + if (seqRead) + ChiselError.check("Chisel3 compatibility: Mem(..., seqRead) is deprecated. Please use SeqMem(...)", Version("3.0")) + if (orderedWrites) + ChiselError.check("Chisel3 compatibility: Mem(..., orderedWrites) is deprecated.", Version("3.0")) + construct(n, out, seqRead, orderedWrites, clock) + } } abstract class AccessTracker extends Delay { @@ -61,8 +72,9 @@ abstract class AccessTracker extends Delay { } class Mem[T <: Data](gen: () => T, val n: Int, val seqRead: Boolean, val orderedWrites: Boolean) extends AccessTracker with VecLike[T] { - if (seqRead) + if (seqRead) { require(!orderedWrites) // sad reality of realizable SRAMs + } def writeAccesses: ArrayBuffer[MemWrite] = writes ++ readwrites.map(_.write) def readAccesses: ArrayBuffer[_ <: MemAccess] = reads ++ seqreads ++ readwrites.map(_.read) def ports: ArrayBuffer[_ <: MemAccess] = writes ++ reads ++ seqreads ++ readwrites @@ -71,35 +83,31 @@ class Mem[T <: Data](gen: () => T, val n: Int, val seqRead: Boolean, val ordered val reads = ArrayBuffer[MemRead]() val readwrites = ArrayBuffer[MemReadWrite]() val data = gen().toNode + def dataType = gen() - inferWidth = fixWidth(data.getWidth) + inferWidth = Node.fixWidth(data.getWidth) private val readPortCache = HashMap[UInt, T]() - def read(addr: UInt): T = { - if (readPortCache.contains(addr)) { - return readPortCache(addr) - } - + def read(addr: UInt): T = readPortCache getOrElseUpdate (addr, { val addrIsReg = addr.getNode.isInstanceOf[Reg] val rd = if (seqRead && !Driver.isInlineMem && addrIsReg) { (seqreads += new MemSeqRead(this, addr.getNode)).last } else { (reads += new MemRead(this, addr)).last } - val data = gen().fromNode(rd).asInstanceOf[T] - readPortCache += (addr -> data) - data - } + gen().fromNode(rd).asInstanceOf[T] + }) - def doWrite(addr: UInt, condIn: Bool, wdata: Node, wmaskIn: UInt): Unit = { + def doWrite(addr: UInt, condIn: Bool, wdata: Node, wmaskIn: Option[UInt]): Unit = { val cond = // add bounds check if depth is not a power of 2 condIn && (Bool(isPow2(n)) || addr(log2Up(n)-1,0) < UInt(n)) - val wmask = // remove constant-1 write masks - if (!(wmaskIn == null) && wmaskIn.litOf != null && wmaskIn.litOf.value == (BigInt(1) << data.getWidth)-1) { - null - } else { - wmaskIn + val wmask = wmaskIn match { // remove constant-1 write masks + case Some(mask) => mask.litOpt match { + case Some(l) if l.value == (BigInt(1) << data.getWidth)-1 => None + case _ => wmaskIn } + case _ => wmaskIn + } if (orderedWrites) // enforce priority ordering of write ports for (w <- writes) @@ -117,20 +125,26 @@ class Mem[T <: Data](gen: () => T, val n: Int, val seqRead: Boolean, val ordered // generate bogus data when reading & writing same address on same cycle val random16 = LFSR16() val random_data = Cat(random16, Array.fill((needWidth()-1)/16){random16}:_*) - doWrite(Reg(next=addr), Reg(next=cond), Reg(next=data), null.asInstanceOf[UInt]) - doWrite(addr, cond, random_data, null.asInstanceOf[UInt]) + doWrite(Reg(next=addr), Reg(next=cond), Reg(next=data), None) + doWrite(addr, cond, random_data, None) } else { - doWrite(addr, cond, data, null.asInstanceOf[UInt]) + doWrite(addr, cond, data, None) } } - def write(addr: UInt, data: T, wmask: UInt): Unit = - if (!Driver.isInlineMem) doWrite(addr, Module.current.whenCond, data, wmask) - else doWrite(addr, Module.current.whenCond, gen().fromBits(data.toBits & wmask | read(addr).toBits & ~wmask), null.asInstanceOf[UInt]) + def write(addr: UInt, data: T, wmask: UInt): Unit = { + ChiselError.check("Chisel3 compatibility: Chisel3 masked writes are only supported for Mem[Vec[_]].", Version("3.0")) + doWrite(addr, Module.current.whenCond, data, wmask) + } + + def write(addr: UInt, data: T, mask: Vec[Bool]) (implicit evidence: T <:< Vec[_]): Unit = { + val bitmask = FillInterleaved(gen().asInstanceOf[Vec[Data]].head.getWidth, mask) + doWrite(addr, Module.current.whenCond, data, bitmask) + } def apply(addr: UInt): T = { val rdata = read(addr) - rdata.comp = new PutativeMemWrite(this, addr) + rdata.comp = Some(new PutativeMemWrite(this, addr)) rdata } @@ -145,7 +159,20 @@ class Mem[T <: Data](gen: () => T, val n: Int, val seqRead: Boolean, val ordered override def toString: String = "TMEM(" + ")" - override def clone = new Mem(gen, n, seqRead, orderedWrites) + def cloneType = new Mem(gen, n, seqRead, orderedWrites) + override def clone = cloneType + + def convertMaskedWrites { + if (Driver.isInlineMem) { + writes filter (_.isMasked) foreach {write => + val addr = write.addr match {case u: UInt => u} + val mask = write.mask match {case u: UInt => u} + val data = write.data.asInstanceOf[T] + val read = readPortCache getOrElseUpdate (addr, gen().fromNode(new MemRead(this, addr))) + write.data = data.toBits & mask | read.toBits & ~mask + } + } + } def computePorts = { reads --= reads.filterNot(_.used) @@ -164,9 +191,11 @@ class Mem[T <: Data](gen: () => T, val n: Int, val seqRead: Boolean, val ordered def isInline = Driver.isInlineMem || !reads.isEmpty override def assignClock(clk: Clock): Unit = { - for (w <- writes) w.clock = clk + for (w <- writes) w.clock = Some(clk) super.assignClock(clk) } + // Chisel3 - this node contains data - used for verifying Wire() wrapping + override def isTypeOnly = false } abstract class MemAccess(val mem: Mem[_], addri: Node) extends Node { @@ -180,21 +209,23 @@ abstract class MemAccess(val mem: Mem[_], addri: Node) extends Node { override def forceMatchingWidths = if (addr.needWidth() != log2Up(mem.n)) inputs(0) = addr.matchWidth(Width(log2Up(mem.n))) + + // Chisel3 - this node contains data - used for verifying Wire() wrapping + override def isTypeOnly = false } class MemRead(mem: Mem[_ <: Data], addri: Node) extends MemAccess(mem, addri) { override def cond = Bool(true) inputs += mem - inferWidth = fixWidth(mem.data.getWidth) + inferWidth = Node.fixWidth(mem.data.getWidth) override def toString: String = mem + "[" + addr + "]" override def getPortType: String = "cread" } -class MemSeqRead(mem: Mem[_ <: Data], addri: Node) extends MemAccess(mem, addri) { +class MemSeqRead(mem: Mem[_ <: Data], addri: Node) extends MemAccess(mem, addri) with Delay { val addrReg = addri.asInstanceOf[Reg] - override def isReg = true override def addr = if (inputs.length > 2) inputs(2) else null override def cond = if (inputs.length > 3) inputs(3) else null @@ -204,7 +235,7 @@ class MemSeqRead(mem: Mem[_ <: Data], addri: Node) extends MemAccess(mem, addri) } inputs += mem - inferWidth = fixWidth(mem.data.getWidth) + inferWidth = Node.fixWidth(mem.data.getWidth) override def toString: String = mem + "[" + addr + "]" override def getPortType: String = "read" @@ -212,26 +243,27 @@ class MemSeqRead(mem: Mem[_ <: Data], addri: Node) extends MemAccess(mem, addri) class PutativeMemWrite(mem: Mem[_ <: Data], addri: UInt) extends Node with proc { override def procAssign(src: Node) = - mem.doWrite(addri, Module.current.whenCond, src, null) + mem.doWrite(addri, Module.current.whenCond, src, None) + // Chisel3 - this node contains data - used for verifying Wire() wrapping + override def isTypeOnly = false } class MemReadWrite(val read: MemSeqRead, val write: MemWrite) extends MemAccess(read.mem, null) { - override def cond = throw new Exception("") + override def cond = throwException("") override def getPortType = if (write.isMasked) "mrw" else "rw" } -class MemWrite(mem: Mem[_ <: Data], condi: Bool, addri: Node, datai: Node, maski: Node) extends MemAccess(mem, addri) { +class MemWrite(mem: Mem[_ <: Data], condi: Bool, addri: Node, datai: Node, maski: Option[Node]) extends MemAccess(mem, addri) { override def cond = inputs(1) def cond_=(c: Bool) = inputs(1) = c clock = mem.clock - inferWidth = fixWidth(mem.data.getWidth) + inferWidth = Node.fixWidth(mem.data.getWidth) inputs += condi inputs += datai - if (maski != null) - inputs += maski + maski match { case Some(m) => inputs += m case None => } override def forceMatchingWidths = { super.forceMatchingWidths @@ -239,7 +271,6 @@ class MemWrite(mem: Mem[_ <: Data], condi: Bool, addri: Node, datai: Node, maski if (isMasked) inputs(3) = inputs(3).matchWidth(mem.widthW) } - var pairedRead: MemSeqRead = null def emitRWEnable(r: MemSeqRead) = { def getProducts(x: Node): List[Node] = { if (x.isInstanceOf[Op] && x.asInstanceOf[Op].op == "&") { @@ -253,6 +284,7 @@ class MemWrite(mem: Mem[_ <: Data], condi: Bool, addri: Node, datai: Node, maski val rp = getProducts(r.addrReg.enableSignal) wp.find(wc => rp.exists(rc => rc._isComplementOf(wc))) } + def data_=(d: Bits) { inputs(2) = d } def data = inputs(2) def mask = inputs(3) def isMasked = inputs.length > 3 @@ -260,3 +292,35 @@ class MemWrite(mem: Mem[_ <: Data], condi: Bool, addri: Node, datai: Node, maski override def getPortType: String = if (isMasked) "mwrite" else "write" override def usesInClockHi(n: Node) = inputs.contains(n) } + +// Chisel3 +object SeqMem { + def apply[T <: Data](n: Int, out: => T): SeqMem[T] = { + val gen = out.cloneType + Reg.validateGen(gen) + new SeqMem(n, gen) + } + + @deprecated("SeqMem(out: => T, n:Int) is deprecated. Please use SeqMem(n:Int, out: => T) instead.", "2.29") + def apply[T <: Data](out: => T, n: Int): SeqMem[T] = { + ChiselError.check("Chisel3 compatibility: SeqMem(out: => T, n:Int) is deprecated. Please use SeqMem(n:Int, out: => T) instead.", Version("3.0")) + apply(n, out) + } +} + +class SeqMem[T <: Data](n: Int, out: T) extends Mem[T](() => out, n, true, false) { + override def apply(addr: UInt): T = throwException("SeqMem.apply unsupported") + override def read(addr: UInt): T = super.read(Reg(next = addr)) + def read(addr: UInt, enable: Bool): T = super.read(RegEnable(addr, enable)) + + override def write(addr: UInt, data: T, mask: Vec[Bool]) (implicit evidence: T <:< Vec[_]): Unit = { + val bitmask = FillInterleaved(out.asInstanceOf[Vec[Data]].head.getWidth, mask) + doWrite(addr, Module.current.whenCond, data, bitmask) + } + + override def write(addr: UInt, data: T, mask: UInt): Unit = + throwException("Chisel3 masked writes are only supported for Mem[Vec[_]]") + + @deprecated("setMemName is equivalent to setName and will be removed", "2.0") + def setMemName(name: String): Unit = setName(name) +} diff --git a/src/main/scala/Module.scala b/src/main/scala/Module.scala index 2db6d4e6..6e18a8d6 100644 --- a/src/main/scala/Module.scala +++ b/src/main/scala/Module.scala @@ -1,5 +1,5 @@ /* - Copyright (c) 2011, 2012, 2013, 2014 The Regents of the University of + Copyright (c) 2011 - 2016 The Regents of the University of California (Regents). All Rights Reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: @@ -29,19 +29,21 @@ */ package Chisel -import scala.math._ -import scala.collection.mutable.{ArrayBuffer, Stack, BitSet} -import scala.collection.mutable.{LinkedHashSet, HashSet, HashMap} -import scala.collection.mutable.{Queue=>ScalaQueue} -import java.lang.reflect.Modifier._ -import scala.sys.process._ -import scala.math.max -import Literal._ -import Bundle._ -import ChiselError._ -import Module._ +import scala.collection.mutable.{ArrayBuffer, LinkedHashSet, HashSet, HashMap, Stack, Queue=>ScalaQueue} +import scala.collection.immutable.ListSet +/** Methods to insert [[Chisel.Module Modules]] into components correctly */ object Module { + /** @return the top level module + * @throws ChiselException if no top component is set + */ + def topMod = Driver.topComponent getOrElse (throwException("no top component")) + + /** The wrapper method for all instantiations of modules + * @param m The module newly created + * @param p Parameters passed down implicitly from that it is created in + * @return A properly wrapped module that has been added to the Driver + */ def apply[T <: Module](m: => T)(implicit p: Parameters = params): T = { Driver.modStackPushed = true Driver.parStack.push(p.push) @@ -49,6 +51,11 @@ object Module { Driver.parStack.pop res } + /** The wrapper method for all instatiations of modules + * @param m The module newly created + * @param f Additonal parameters to be included + * @return A properly wrapped module that has been added to the Driver + */ def apply[T <: Module](m: => T, f: PartialFunction[Any,Any]): T = { val q = params.alterPartial(f) apply(m)(q) @@ -58,10 +65,13 @@ object Module { val res = c pop() for ((n, io) <- res.wires) { - if (io.dir == null) - ChiselErrors += new ChiselError(() => {"All IO's must be ports (dir set): " + io}, io.line) + if (io.dir == NODIR) { + val io_str = "<" + n + " (" + io.getClass.getName + ")>" + ChiselError.error(new ChiselError(() => { + "All IO's must be ports (dir set): " + io_str + " in " + res }, io.line)) + } // else if (! io.isKnownWidth) - // ChiselErrors += new ChiselError(() => {"All IO's must have width set: " + io}, io.line) + // ChiselError.error(new ChiselError(() => {"All IO's must have width set: " + io}, io.line)) io.isIo = true } res @@ -101,16 +111,13 @@ object Module { } } - // XXX Remove and instead call current() - def getComponent(): Module = if(Driver.compStack.length != 0) Driver.compStack.top else null - def current: Module = { - val comp = getComponent - if (comp == null) Driver.topComponent else comp - } + /** Do not use: call current instead */ + private[Chisel] def getComponent = if (Driver.compStack.length != 0) Some(Driver.compStack.top) else None + /** @return the current module */ + def current = getComponent getOrElse topMod - // despite being notionally internal, these have leaked into the API - def backend: Backend = Driver.backend - def components: ArrayBuffer[Module] = Driver.components + /** @return the backend from the [[Chisel.Driver Driver]] */ + def backend = Driver.backend protected[Chisel] def asModule(m: Module)(block: => Unit): Unit = { Driver.modStackPushed = true @@ -129,7 +136,21 @@ object Module { ( + ) sets the default reset signal ( + ) overridden if Delay specifies its own clock w/ reset != implicitReset */ -abstract class Module(var clock: Clock = null, private[Chisel] var _reset: Bool = null) { +/** A Module or block to logically divide a hardware design + * @note This is the same construct as module in verilog + * Also see [[Chisel.Module$ Module]] object + * @example + * {{{ class MyModule extends Module { + * val io = new Bundle { + * val dataIn = UInt(INPUT, 4) + * val dataOut = UInt(OUTPUT, 4) + * } + * io.dataOut := io.dataIn + * } + * val myInst = Module(new MyModule) // create a MyModule + * }}} + */ +abstract class Module(var _clock: Option[Clock] = None, private[Chisel] var _reset: Option[Bool] = None) extends Nameable { /** A backend(Backend.scala) might generate multiple module source code from one Module, based on the parameters to instantiate the component instance. Since we do not want to blindly generate one module per instance @@ -137,93 +158,103 @@ abstract class Module(var clock: Clock = null, private[Chisel] var _reset: Bool and discard textual duplicates. By walking the nodes from level zero (leafs) to level N (root), we are guaranteed to generate all Module/modules source text before their first instantiation. */ - var level = 0; - var traversal = 0; - var ioVal: Data = null; - /** Name of the instance. */ - var name: String = ""; + private[Chisel] var level = 0 + private[Chisel] var traversal = 0 /** Name of the module this component generates (defaults to class name). */ - var moduleName: String = ""; - var named = false; - val bindings = new ArrayBuffer[Binding]; - var parent: Module = null; + var moduleName: String = "" + var parent: Module = null val children = ArrayBuffer[Module]() - val debugs = LinkedHashSet[Node]() - val printfs = ArrayBuffer[Printf]() - val asserts = ArrayBuffer[Assert]() - val switchKeys = Stack[Bits]() - val whenConds = Stack[Bool]() - private lazy val trueCond = Bool(true) - def hasWhenCond: Boolean = !whenConds.isEmpty - def whenCond: Bool = if (hasWhenCond) whenConds.top else trueCond + /** Set the declaration name of the module to be string 'n' */ + def setModuleName(n : String) { moduleName = n } - val nodes = new LinkedHashSet[Node] - val names = new HashMap[String, Node] - var nindex = -1; - var defaultWidth = 32; - var pathParent: Module = null; - var verilog_parameters = ""; - val clocks = new ArrayBuffer[Clock] - val resets = new HashMap[Bool, Bool] + private[Chisel] val bindings = ArrayBuffer[Binding]() + private[Chisel] val printfs = ArrayBuffer[Printf]() + private[Chisel] val asserts = ArrayBuffer[Assert]() + private[Chisel] val debugs = LinkedHashSet[Node]() + private[Chisel] val nodes = LinkedHashSet[Node]() + private[Chisel] val names = HashMap[String, Node]() - def hasReset = !(reset == null) - def hasClock = !(clock == null) - - Driver.components += this - push(this) + private lazy val trueCond = Bool(true) + private[Chisel] val switchKeys = Stack[Bits]() + private[Chisel] val whenConds = Stack[Bool]() + private[Chisel] def hasWhenCond: Boolean = !whenConds.isEmpty + private[Chisel] def whenCond: Bool = if (hasWhenCond) whenConds.top else trueCond + private[Chisel] var verilog_parameters = ""; //Parameter Stuff lazy val params = Module.params params.path = this.getClass :: params.path - var hasExplicitClock = !(clock == null) - var hasExplicitReset = !(_reset == null) - - var defaultResetPin: Bool = null - def reset = { - if (defaultResetPin == null) { - defaultResetPin = Bool(INPUT) - defaultResetPin.isIo = true - defaultResetPin.component = this - defaultResetPin.setName("reset") + Driver.components += this + Module.push(this) + + if (_clock == null) _clock = None + if (_reset == null) _reset = None + private[Chisel] val clocks = LinkedHashSet[Clock]() + private[Chisel] val resets = HashMap[Bool, Bool]() + private[Chisel] var resetPin: Option[Bool] = None + private[Chisel] var hasExplicitClock = _clock != None + private[Chisel] var hasExplicitReset = _reset != None + /** @return the implied clock for this module */ + def clock: Clock = _clock getOrElse ( + if (parent == null) Driver.implicitClock else parent.clock) + /** @return the implied reset for this module */ + def reset = resetPin match { + case None => { + val r = Bool(INPUT) + r.isIo = true + r.compOpt = Some(this) + r setName ("reset") + resetPin = Some(r) + r } - defaultResetPin - } - def reset_=(r: Bool) { - _reset = r + case Some(r) => r } - def reset_=() { - _reset = parent._reset + private[Chisel] def reset_=(r: Bool) { + _reset = Some(r) } - - override def toString = this.getClass.toString - - // This function sets the IO's component. - def ownIo() { - val wires = io.flatten; - for ((n, w) <- wires) { - // This assert is a sanity check to make sure static resolution - // of IOs didn't fail - scala.Predef.assert(this == w.component, - ChiselError.error("Statically resolved component differs from dynamically resolved component of IO: " + w + " crashing compiler")) + /** @return the pin connected to the reset signal or creates a new one if no such pin exists */ + def addResetPin(r: Bool): Bool = { + val pin = _reset match { + case Some(p) if p == r => reset + case _ => + val p = Bool(INPUT) + p.isIo = true + p.compOpt = Some(this) + p } - // io naming - io nameIt ("io", true) + resets getOrElseUpdate (r, pin) } + /** Add a clock to the module + * @param clock the clock to add + */ + def addClock(clock: Clock) { clocks += clock } + + override def toString = s"<${this.name} (${this.getClass.toString})>" + /** A method to trace the graph of nodes backwards looking at inputs + * @param m Node to find bindings for + * @return nodes which have node m binded as their input + */ def findBinding(m: Node) = bindings find (_.inputs(0) == m) + /** the I/O for this module */ def io: Data - def nextIndex : Int = { nindex = nindex + 1; nindex } + private[Chisel] var nindex: Option[Int] = None + def nextIndex : Int = { + nindex = nindex match { case None => Some(0) case Some(i) => Some(i + 1) } + nindex.get + } // override def toString: String = name this one isn't really working... + /** Get the I/O names and connections */ def wires: Array[(String, Bits)] = io.flatten /** Add an assertion in the code generated by a backend. */ - def assert(cond: Bool, message: String): Unit = { - val a = new Assert(!Module.current.whenCond || cond, this.reset, message) + def assert(cond: Bool, message: String = ""): Unit = { + val a = new Assert(!Module.current.whenCond || cond, reset, message) debug(a) asserts += a } @@ -232,92 +263,89 @@ abstract class Module(var clock: Clock = null, private[Chisel] var _reset: Bool from the outputs. */ def debug(x: Node): Unit = { // XXX Because We cannot guarentee x is flatten later on in collectComp. - x.getNode.component = this + x.getNode.compOpt = Some(this) debugs += x.getNode } + def debug(data: Aggregate): Unit = { + data.flatten.map(x => debug(x._2)) + } + + /** Adds a printf to the module called each clock cycle + * @param message A c style sting to print out eg) %d, %x + * @param args Nodes whos data values should be printed + */ def printf(message: String, args: Node*): Unit = { - val p = new Printf(Module.current.whenCond && !this.reset, message, args) + val p = new Printf(Module.current.whenCond && !reset, message, args) printfs += p debug(p) p.inputs.foreach(debug _) - for (arg <- args) - if (arg.isInstanceOf[Aggregate]) - ChiselErrors += new ChiselError(() => { "unable to printf aggregate argument " + arg }, arg.line) - } - - def <>(src: Module) { - io <> src.io - } - - def apply(name: String): Data = io(name); - // COMPILATION OF REFERENCE - def emitDec(b: Backend): String = { - var res = ""; - // val wires = io.flatten; - for ((n, w) <- wires) - res += b.emitDec(w); - res - } - - // returns the pin connected to the reset signal, creates a new one if - // no such pin exists - def addResetPin(reset: Bool): Bool = { - def makeIO = { - val res = Bool(INPUT) - res.isIo = true - res.component = this - res + args foreach { + case arg: Aggregate => + ChiselError.error(new ChiselError(() => { "unable to printf aggregate argument " + arg }, arg.line)) + case _ => } - def pin = - if (reset == _reset) this.reset - else makeIO - this.resets.getOrElseUpdate(reset, pin) } - def addClock(clock: Clock) { - if (!this.clocks.contains(clock)) - this.clocks += clock - } + /** Connect io with matching names for two modules */ + def <>(src: Module) { io <> src.io } + def apply(name: String): Data = io(name) + + /** Add a pin with a name to the module + * @param pin the I/O to add + * @param name A name for the pin + */ def addPin[T <: Data](pin: T, name: String = "") = { + val gen = pin.clone io match { case b: Bundle => { - for ((n, io) <- pin.flatten) { - io.component = this + for ((n, io) <- gen.flatten if !io.isDirectionless && !io.getNode.isLit) { + io.compOpt = Some(this) io.isIo = true } - if (name != "") pin nameIt (name, true) - b.elements += ((pin.name, pin)) + if (name != "") gen nameIt (name, true) + b.elements += ((gen.name, gen)) } case _ => // Is it possible? } - pin + gen } + /** Add a submodule to this module */ def addModule[T<:Module](c: =>T, f: PartialFunction[Any,Any]) = { Driver.modStackPushed = true Driver.modAdded = true val q = params.alterPartial(f) Driver.compStack.push(this) Driver.parStack.push(q) - val res = init(c) + val res = Module.init(c) Driver.parStack.pop Driver.compStack.pop res } + + /** Add a submodule to this module */ def addModule[T <: Module](c: => T)(implicit p:Parameters = params) = { Driver.modStackPushed = true Driver.modAdded = true Driver.compStack.push(this) Driver.parStack.push(p.push) - val res = init(c) + val res = Module.init(c) res.markComponent Driver.parStack.pop Driver.compStack.pop res } + def addNode[T <: Node](node: T) = { + nodes += node.getNode + node.getNode.compOpt = Some(this) + node + } + + // TODO: should be private[Chisel]? + /** A breadth first search of the graph of nodes */ def bfs (visit: Node => Unit) = { // initialize BFS val queue = new ScalaQueue[Node] @@ -328,38 +356,27 @@ abstract class Module(var clock: Clock = null, private[Chisel] var _reset: Bool queue enqueue io for (child <- children ; (n, io) <- child.wires ; if io.isIo && io.dir == INPUT) queue enqueue io - if (!(defaultResetPin == null)) - queue enqueue defaultResetPin + for (pin <- resets.values) + queue enqueue pin // Do BFS - val walked = HashSet[Node]() + val _walked = HashSet[Node](queue:_*) + def walked(node: Node) = node == null || _walked(node) || node.isIo + def enqueueNode(node: Node) { queue enqueue node ; _walked += node } + def enqueueInputs(top: Node) { ListSet(top.inputs:_*) filterNot walked foreach enqueueNode } + def enqueueElems(agg: Data) { agg.flatten.unzip._2 filterNot walked foreach enqueueNode } while (!queue.isEmpty) { val top = queue.dequeue - walked += top visit(top) top match { - case v: Vec[_] => - for ((n, e) <- v.flatten; - if !(e == null) && !(walked contains e) && !e.isIo) { - queue enqueue e - walked += e - } - for (i <- top.inputs; - if !(i == null) && !(walked contains i) && !i.isIo) { - queue enqueue i - walked += i - } - case _ => { - for (i <- top.inputs; - if !(i == null) && !(walked contains i) && !i.isIo) { - queue enqueue i - walked += i - } - } + case b: Bundle => enqueueElems(b) + case v: Vec[_] => enqueueElems(v) ; enqueueInputs(v) + case _ => enqueueInputs(top) } } } + /** A depth first search of the graph of nodes */ def dfs(visit: Node => Unit): Unit = { val stack = new Stack[Node] // initialize DFS @@ -367,50 +384,56 @@ abstract class Module(var clock: Clock = null, private[Chisel] var _reset: Bool stack push io for (child <- children ; (n, io) <- child.wires ; if io.isIo && io.dir == INPUT) stack push io - if (!(defaultResetPin == null)) - stack push defaultResetPin + for (pin <- resets.values) + stack push pin for (a <- debugs) stack push a // Do DFS - val walked = HashSet[Node]() + val _walked = HashSet[Node](stack:_*) + def walked(node: Node) = node == null || _walked(node) || node.isIo + def pushNode(node: Node) { stack push node ; _walked += node } + def pushInputs(top: Node) { ListSet(top.inputs:_*) filterNot walked foreach pushNode } + def pushElems(agg: Data) { agg.flatten.unzip._2 filterNot walked foreach pushNode } while (!stack.isEmpty) { val top = stack.pop - walked += top visit(top) top match { - case v: Vec[_] => { - for ((n, e) <- v.flatten; - if !(e == null) && !(walked contains e) && !e.isIo) { - stack push e - walked += e - } - for (i <- top.inputs; - if !(i == null) && !(walked contains i) && !i.isIo) { - stack push i - walked += i - } - } - case _ => { - for (i <- top.inputs; - if !(i == null) && !(walked contains i) && !i.isIo) { - stack push i - walked += i - } - } + case b: Bundle => pushElems(b) + case v: Vec[_] => pushElems(v) ; pushInputs(v) + case _ => pushInputs(top) } } } + /** Add a default reset to the module*/ def addDefaultReset { - if (!(defaultResetPin == null)) { - addResetPin(_reset) - if (this != Driver.topComponent && hasExplicitReset) - defaultResetPin.inputs += _reset + _reset match { + case None => throwException("no default reset") + case Some(r) => resetPin match { + case None => + case Some(p) => + addResetPin(r) + if ((this ne Module.topMod) && hasExplicitReset) p := r + } } } - def getClassValNames(c: Class[_]): ArrayBuffer[String] = { + // This function sets the IO's component. + private def ownIo() { + for ((n, w) <- wires ; if this != w.component) { + // This assert is a sanity check to make sure static resolution + // of IOs didn't fail + val io_str = "<" + n + " (" + w.getClass.getName + ")>" + ChiselError.error("Statically resolved component(" + this + + ") differs from dynamically resolved component(" + w.component + + ") of IO: " + io_str + " crashing compiler") + } + // io naming + io nameIt ("io", true) + } + + private def getClassValNames(c: Class[_]): ArrayBuffer[String] = { val valnames = new ArrayBuffer[String]() for (v <- c.getDeclaredFields) { v.setAccessible(true) @@ -422,13 +445,13 @@ abstract class Module(var clock: Clock = null, private[Chisel] var _reset: Bool } // Allow checking if a method name is also the name of a val -- reveals accessors - def getValNames = { + private def getValNames = { val valnames = new ArrayBuffer[String]() valnames ++= getClassValNames(getClass) valnames } - object isValName { + private object isValName { val valnames = Module.this.getValNames def apply(name: String) = valnames.contains(name) } @@ -437,8 +460,9 @@ abstract class Module(var clock: Clock = null, private[Chisel] var _reset: Bool // 2) name the IO // 3) name and set the component of all statically declared nodes through introspection // 4) set variable names - def markComponent() { - ownIo(); + private[Chisel] def markComponent { + import Module.backend + ownIo() /* We are going through all declarations, which can return Nodes, ArrayBuffer[Node], BlackBox and Modules. Since we call invoke() to get a proper instance of the correct type, @@ -446,14 +470,14 @@ abstract class Module(var clock: Clock = null, private[Chisel] var _reset: Bool that will generate C++ or Verilog code must be made public. */ // get all super classes' methods def getMethods(c: Class[_]): Set[java.lang.reflect.Method] = { - if (c.toString.split('.').last == "Module") Set[java.lang.reflect.Method]() + if (c.toString.split('.').last == "Module") Set[java.lang.reflect.Method]() else c.getDeclaredMethods.toSet ++ getMethods(c.getSuperclass) } for (m <- getMethods(getClass).toList.sortWith(_.getName < _.getName)) { val name = m.getName(); val types = m.getParameterTypes(); if (types.length == 0 && isValName(name) // patch to avoid defs - && isPublic(m.getModifiers())) { + && java.lang.reflect.Modifier.isPublic(m.getModifiers())) { val o = m.invoke(this); o match { case node: Node => { @@ -500,7 +524,6 @@ abstract class Module(var clock: Clock = null, private[Chisel] var _reset: Bool backend.nameSpace += bb.name } case comp: Module => { - comp.pathParent = this if (!comp.named) { comp.name = backend.asValidName(name) comp.named = true @@ -517,23 +540,93 @@ abstract class Module(var clock: Clock = null, private[Chisel] var _reset: Bool They never get overridden yet it is called for each component (See Backend implementations). */ def stripComponent(s: String): String = s.split("__").last - - /** Returns the absolute path to a component instance from toplevel. */ - def getPathName: String = { - getPathName() - } + /** @return the absolute path to a component instance from toplevel */ + def getPathName: String = getPathName() + /** @param separator The separator to use for the path name + * @return the absolute path to a component instance from toplevel */ def getPathName(separator: String = "_"): String = { if ( parent == null ) name else parent.getPathName(separator) + separator + name; } - def isInput(node: Node): Boolean = - node match { case b:Bits => b.dir == INPUT; case o => false } - def keepInputs(nodes: Seq[Node]): Seq[Node] = - nodes.filter(isInput) - def removeInputs(nodes: Seq[Node]): Seq[Node] = - nodes.filter(n => !isInput(n)) - override val hashCode: Int = Driver.components.size override def equals(that: Any) = this eq that.asInstanceOf[AnyRef] -} + // Chisel3 + private[Chisel] val assignments = HashMap[Data, StackTraceElement]() + private[Chisel] def addAssignment(assignee: Data) = { + val stack = Thread.currentThread().getStackTrace + if (!assignments.contains(assignee)) { + assignments += ((assignee, ChiselError.findFirstUserLine(stack) getOrElse stack(0))) + } + } + /** verifyWireWrap (Chisel3) - verify assignment semantics (type-only nodes must be wire-wrapped) + * @return - HashMap of source lines (and associated nodes) requiring Wire() wrapping. + */ + type neededWireWraps = HashMap[StackTraceElement, ArrayBuffer[Data]] + private[Chisel] def verifyWireWrap: neededWireWraps = { + // Go through all assignments for this module and add those needing Wire()-wrap to a map. + val wireWrapLineToNode = new neededWireWraps() + def nodeNeedsWire(node: Data, errorLine: StackTraceElement) { + // Add this node to the list of nodes for this line + if (!wireWrapLineToNode.contains(errorLine)) { + wireWrapLineToNode(errorLine) = ArrayBuffer[Data]() + } + wireWrapLineToNode(errorLine) += node + } + for ((node, assignmentLine) <- assignments) { + // Is the node type-only (no data) and isn't io and hasn't been Wire() wrapped? + // NOTE: We deal with IO() wrapping elsewhere. + if (node.isTypeOnly && !(node.isWired || node.isIo)) { + // Do we have line numbers? + val errorLine = if (node.line != null) { + node.line + } else { + assignmentLine + } + nodeNeedsWire(node, errorLine) + } + } + wireWrapLineToNode + } + + /** reportWireWrap (Chisel3) - report type-only nodes requiring Wire() wrapping. + * @param - HashMap of source lines (and associated nodes) requiring Wire() wrapping. + */ + private[Chisel] def reportWireWrap(lineNodes: neededWireWraps) { + // For extra credit, sort the map keys (file and line number) + for ((errorLine, nodes) <- lineNodes) { + val nodeNames = nodes.map(_.name).mkString(", ") + val plural = if (nodes.length > 1) "s" else "" + val errorString = "Chisel3 compatibility: node%s %s should be wrapped in a Wire()".format(plural, nodeNames) + ChiselError.check(errorString, Version("3.0"), errorLine) + } + } + + /** verify module. + * @return - true means there are no issues with the module, false means there are issues and they have been reported. + */ + private[Chisel] def verify: Boolean = { + var result = true + // If we're verifying Chisel3 compatibility, verify Wire(), IO() wrapping. + if (Driver.minimumCompatibility > "2") { + // Verify that ios are wrapped in IO() + if (!isIOWrapped) { + val errorString = "Chisel3 compatibility: io's should be wrapped in IO()" + ChiselError.check(errorString, Version("3.0"), this.io.line) + } + val neededWireWraps = verifyWireWrap + if (!neededWireWraps.isEmpty) { + reportWireWrap(neededWireWraps) + result = false + } + } + result + } + + // Chisel3 compatibility - IO() wrapper. + private var isIOWrapped = false + def IO[T<:Data](iodef: T): iodef.type = { + isIOWrapped = true + iodef + } +} diff --git a/src/main/scala/Mux.scala b/src/main/scala/Mux.scala index 887b8680..f659fb64 100644 --- a/src/main/scala/Mux.scala +++ b/src/main/scala/Mux.scala @@ -1,5 +1,5 @@ /* - Copyright (c) 2011, 2012, 2013, 2014 The Regents of the University of + Copyright (c) 2011 - 2016 The Regents of the University of California (Regents). All Rights Reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: @@ -29,11 +29,15 @@ */ package Chisel -import Node._ -import scala.math._ +/** MuxLookup creates a cascade of n Muxs to search for a key value */ object MuxLookup { - def apply[S <: UInt, T <: Bits] (key: S, default: T, mapping: Seq[(S, T)]): T = { + /** @param key a key to search for + * @param default a default value if nothing is found + * @param mapping a sequence to search of keys and values + * @return the value found or the default if not + */ + def apply[S <: UInt, T <: Data] (key: S, default: T, mapping: Seq[(S, T)]): T = { var res = default; for ((k, v) <- mapping.reverse) res = Mux(key === k, v, res); @@ -42,8 +46,12 @@ object MuxLookup { } +/** MuxCase returns the first value that is enabled in a map of values */ object MuxCase { - def apply[T <: Bits] (default: T, mapping: Seq[(Bool, T)]): T = { + /** @param default the default value if none are enabled + * @param mapping a set of data values with associated enables + * @return the first value in mapping that is enabled */ + def apply[T <: Data] (default: T, mapping: Seq[(Bool, T)]): T = { var res = default; for ((t, v) <- mapping.reverse){ res = Mux(t, v, res); @@ -52,27 +60,29 @@ object MuxCase { } } -object Multiplex{ +/** A multiplexor which is a generalization of [[Chisel.Mux Mux]] to use nodes which aren't bools + * [[Chisel.Mux Mux]] uses this method internally + * If the values are not literals a [[Chisel.Mux Mux]] class is created and initialized */ +object Multiplex { + /** muliplex between nodes with if (t != 0) c else a */ def apply (t: Node, c: Node, a: Node): Node = { - if (t.litOf != null) { - return if (t.litOf.value == 0) a else c - } - if (a != null && a.isInstanceOf[Mux] && t._isComplementOf(a.inputs(0))) { - return Multiplex(t, c, a.inputs(1)) - } - if (c.litOf != null && a != null && a.litOf != null) { - if (c.litOf.value == a.litOf.value) { - return c - } - if (c.litOf.isKnownWidth && a.litOf.isKnownWidth - && c.litOf.widthW.needWidth() == 1 && a.litOf.widthW.needWidth() == 1) { - return if (c.litOf.value == 0) LogicalOp(t, Literal(0,1), "===") else t + t.litOpt match { + case Some(tl) => if (tl.value == 0) a else c + case None if a != null => (c.litOpt, a.litOpt) match { + case (_, Some(al)) if a.isInstanceOf[Mux] && t._isComplementOf(a.inputs(0)) => + Multiplex(t, c, a.inputs(1)) + case (Some(cl), Some(al)) if cl.value == al.value => c + case (Some(cl), Some(al)) if cl.isKnownWidth && al.isKnownWidth && + cl.widthW.needWidth() == 1 && al.widthW.needWidth() == 1 => + if (cl.value == 0) LogicalOp(t, Literal(0,1), "===") else t + case _ => new Mux().init("", Node.maxWidth _, t, c, a) } + case _ => new Mux().init("", Node.maxWidth _, t, c, a) } - new Mux().init("", maxWidth _, t, c, a); } } +/** Usefulness is questionable, remove? */ object isLessThan { def distFromData(x: java.lang.Class[_]): Int = { @@ -94,20 +104,35 @@ object isLessThan { } } +/** Implement a Multiplexor with a Bool + * A convienient wrapper for [[Chisel.Multiplex$ Multiplex]] */ object Mux { + /** Create a Mux + * @param cond a condition to determine which value to choose + * @param tc the value chosen when cond is true or 1 + * @param fc the value chosen when cond is false or 0 + * @example + * {{{ val muxOut = Mux(data_in === UInt(3), UInt(3, 4), UInt(0, 4)) }}} */ def apply[T<:Data](cond: Bool, tc: T, fc: T): T = { + // Chisel3 - Check version compatibility (args to Mux must be derived from the same UInt/SInt parent) + if (Driver.minimumCompatibility > "2") { + if (tc.isInstanceOf[UInt] != fc.isInstanceOf[UInt]) { + ChiselError.check("Chisel3 compatibility: Unable to have mixed type mux CON " + tc + " ALT " + fc, Version("3.0")) + } + } // TODO: Replace this runtime check with compiletime check using type classes and imports to add special cases - val target = if(tc.getClass.isAssignableFrom(fc.getClass)) tc.clone else - if(fc.getClass.isAssignableFrom(tc.getClass)) fc.clone else + val target = if(tc.getClass.isAssignableFrom(fc.getClass)) tc.cloneType else + if(fc.getClass.isAssignableFrom(tc.getClass)) fc.cloneType else if(classOf[Bits].isAssignableFrom(tc.getClass) && classOf[Bits].isAssignableFrom(fc.getClass)) { ChiselError.warning("Mux of Bits instantiated, emits SInt") SInt().asInstanceOf[T] } else - throw new Exception(s"For Mux, tc(${tc.getClass}) or fc(${fc.getClass}) must directly descend from the other. (Or both descend from Bits)") + throwException(s"For Mux, tc(${tc.getClass}) or fc(${fc.getClass}) must directly descend from the other. (Or both descend from Bits)") Mux[T,T,T](target, cond, tc, fc) } - // THIS IS THE MAIN MUX CONSTRUCTOR + /** The main Mux constructor, avoid using directly + * Try to use other apply method */ def apply[RT<:Data,TT<:Data,FT<:Data](result: RT, cond: Bool, tc: TT, fc: FT)( implicit evi_tc: TT <:< RT, evi_fc: FT <:< RT): RT = { // The implicit lines require evidence that TT and RT (the mux inputs) are subtypes of the return. @@ -135,17 +160,22 @@ object Mux { } } +/** Mux class defined as an operator + */ class Mux extends Op { val op = "Mux" override def toString: String = inputs(0) + " ? " + inputs(1) + " : " + inputs(2) + /** set last input to 'a' */ def ::(a: Node): Mux = { inputs(2) = a; this } + /** force the inputs to have the same width as this Mux */ override def forceMatchingWidths { if (inputs(1).widthW != widthW) inputs(1) = inputs(1).matchWidth(widthW) if (inputs(2).widthW != widthW) inputs(2) = inputs(2).matchWidth(widthW) } + /** Check for zero width cutting edge of the graph for all zero input nodes found */ override def W0Wtransform() { val w1 = inputs(1).widthW val w2 = inputs(2).widthW diff --git a/src/main/scala/Node.scala b/src/main/scala/Node.scala index 7292fa97..0cfc2970 100644 --- a/src/main/scala/Node.scala +++ b/src/main/scala/Node.scala @@ -1,5 +1,5 @@ /* - Copyright (c) 2011, 2012, 2013, 2014 The Regents of the University of + Copyright (c) 2011 - 2016 The Regents of the University of California (Regents). All Rights Reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: @@ -30,63 +30,68 @@ package Chisel -import scala.collection.immutable.Vector -import scala.collection.mutable.ArrayBuffer -import scala.collection.mutable.Stack -import scala.collection.mutable.LinkedHashSet -import java.io.PrintStream - -import Node._; -import ChiselError._; -import Width._; - -import java.lang.Double.longBitsToDouble -import java.lang.Float.intBitsToFloat +import scala.collection.mutable.{ArrayBuffer, Stack, LinkedHashSet} object Node { + /** print a message to stdout in c style printf + * @param message A string with c like chars in it (%d, %x etc) + * @param args Nodes whos values to fetch to print + */ def sprintf(message: String, args: Node*): Bits = { val s = Bits().fromNode(new Sprintf(message, args)) s.setIsTypeNode s } - def fixWidth(w: => Int): (=> Node) => Width = { (n) => { - if (n != null) { - assert(w != -1, ChiselError.error({"invalid width for fixWidth object"})); - Width(w) - } else { - Width() - } + /** @param w the bit width to set for this node */ + def fixWidth(w: => Int): (=> Node) => Width = { n => { + assert(w != -1, ChiselError.error({"invalid width for fixWidth object"})) + Width(w) }} + /** @param i an integer to convert to bits + * @return the number of bits needed to express the integer */ def widthOf(i: => Int): (=> Node) => Width = { (m) => { try { m.inputs(i).widthW } catch { case e: java.lang.IndexOutOfBoundsException => { - val error = new ChiselError(() => {m + " is unconnected ("+ i + " of " + m.inputs.length + "). Ensure that it is assigned."}, m.line) - if (!ChiselErrors.contains(error) && !Driver.isInGetWidth) { - ChiselErrors += error + val error = new ChiselError(() => {m + " is unconnected (" + i + " of " + m.inputs.length + "). Ensure that it is assigned."}, m.line) + if (!ChiselError.contains(error) && !Driver.isInGetWidth) { + ChiselError.error(error) } Width() } } }} - // Compute the maximum width required for a node, + /** Compute the maximum width required for a node + * @param m the node to get the max width for + * @return the max width required for the node based on its inputs + */ def maxWidth(m: => Node): Width = { var w = Width(0) - for (i <- m.inputs) - if (!(i == null || i == m)) { - w = w.max(i.widthW) - } + for (i <- m.inputs if i != m) + w = w.max(i.widthW) w } + /** Compute the minimum width allowed for the node + * @param m the node to get the min width for + * @return the minimum width of all input nodes + */ def minWidth(m: => Node): Width = m.inputs.map(_.widthW).min + /** Compute the maximum width required for a node + 1 + * @param m the node to get the max width + 1 for + * @return the max width + 1 required for the node based on its inputs + */ def maxWidthPlusOne(m: => Node): Width = maxWidth(m) + 1 + /** Compute the sum of the width for all inputs for a node + * @param m the node to sum the width of + * @return the max width + 1 required for the node based on its inputs + */ def sumWidth(m: => Node): Width = { var res = Width(0); for (i <- m.inputs) @@ -94,6 +99,11 @@ object Node { res } + /** Get the width of a node after a left shift + * @param i amount to shift by + * @param n the node that is being shifted + * @return A width function for the node + */ def lshWidthOf(i: => Int, n: => Node): (=> Node) => (Width) = { (m) => { val w0 = m.inputs(0).widthW @@ -110,11 +120,24 @@ object Node { // ChiselError.warning("lshWidthOf: child width not set - " + m.inputs(0)) Width() } else { - w0 + n.litValue((1 << w.needWidth)-1).toInt + val shiftWidth = { + val nWidth = w.needWidth + val mWidth = 31 + if (nWidth > mWidth) { +// ChiselError.warning("lshWidthOf: shiftWidth (%d) overflows Int (%d).".format(nWidth, mWidth)) + } + nWidth + } + w0 + n.litValue((1 << shiftWidth)-1).toInt } } } + /** Get the width of a node after a right shift + * @param i amount to shift by + * @param n the node that is being shifted + * @return A width function for the node + */ def rshWidthOf(i: => Int, n: => Node): (=> Node) => (Width) = { (m) => { val a = m.inputs(i).widthW @@ -133,36 +156,40 @@ object Node { are used to traverse the directed graph respectively backward (from output to input) and forward (from input to output). */ -abstract class Node extends nameable { - var sccIndex = -1 - var sccLowlink = -1 +abstract class Node extends Nameable { + private[Chisel] var sccIndex: Option[Int] = None + private[Chisel] var sccLowlink: Option[Int] = None + private[Chisel] var depth = 0 + var prune = false + var driveRand = false + var isTypeNode = false /* Assigned in Binding and Mod.reset */ - var component: Module = Module.getComponent - var isTypeNode = false; - var depth = 0; - def componentOf: Module = if (Driver.backend.isEmittingComponents && component != null) component else Driver.topComponent + private[Chisel] var compOpt: Option[Module] = Module.getComponent + /** Use the function componentOf instead*/ + private[Chisel] def component: Module = compOpt getOrElse { throwException("< " + this + " > doesn't have its component, yet.") } + /** Get the module that this node is a part of or the top module if not assigned yet + * @return The module that this node is a part of + */ + def componentOf = if (Driver.backend.isEmittingComponents && compOpt != None) component else Module.topMod // The semantics of width are sufficiently complicated that // it deserves its own class - var width_ = Width() - var inferWidth: (=> Node) => Width = maxWidth + private[Chisel] var width_ = Width() + private[Chisel] var inferWidth: (=> Node) => Width = Node.maxWidth + /** The clock for this node */ + var clock: Option[Clock] = None + /** The inputs that this node depends on */ val inputs = ArrayBuffer[Node]() - val consumers = LinkedHashSet[Node]() // nodes that consume one of my outputs - - var nameHolder: nameable = null; + /** nodes that consume one of my outputs */ + val consumers = LinkedHashSet[Node]() + /** The trace information for chisel for this node */ val line: StackTraceElement = if (Driver.getLineNumbers) { val trace = new Throwable().getStackTrace - findFirstUserLine(trace) getOrElse trace(0) + ChiselError.findFirstUserLine(trace) getOrElse trace(0) } else null - var prune = false - var driveRand = false - var clock: Clock = null - var cntrIdx = -1 + /** The unique id of this node */ + val _id = Driver.getNodeId - val _id = Driver.nodes.length - Driver.nodes += this - - def isByValue: Boolean = true; private[Chisel] def width: Int = { val w = widthW if (w.isKnown) @@ -171,13 +198,24 @@ abstract class Node extends nameable { throwException("Node.width for node " + this + " returns unknown width") } private[Chisel] def widthW: Width = { - if (Driver.isInGetWidth) inferWidth(this) else width_ + val selfresult = if (Driver.isInGetWidth) inferWidth(this) else width_ + if(!selfresult.isKnown && isTypeNode && !inputs.isEmpty) { + val gNode = getNode + if (gNode == this) { + ChiselError.error("unknown width cannot be inferred for node %s".format(gNode)) + selfresult + } else { + gNode.widthW + } + } else { + selfresult + } } /** Sets the width of a Node. */ private[Chisel] def width_=(w: Int) { width_.setWidth(w); - inferWidth = fixWidth(w); + inferWidth = Node.fixWidth(w); } private[Chisel] def width_=(w: Width) { @@ -186,7 +224,8 @@ abstract class Node extends nameable { // See the comments in infer } - def nameIt (path: String, isNamingIo: Boolean) { + /** An internal method to name nodes, use setName instead */ + private[Chisel] def nameIt (path: String, isNamingIo: Boolean) { try { if (!named && (!isIo || isNamingIo)) { /* If the name was set explicitly through *setName*, @@ -212,55 +251,86 @@ abstract class Node extends nameable { } lazy val chiselName = this match { - case l: Literal => ""; - case any => - if (named && (name != "reset") && !(component == null)) + case l: Literal => "" + case _ if named && compOpt != None => component.getPathName(".") + "." + name - else - "" + case _ => "" } // TODO: REMOVE WHEN LOWEST DATA TYPE IS BITS - def ##(b: Node): Node = Op("##", sumWidth _, this, b ); - final def isLit: Boolean = litOf ne null - def litOf: Literal = if (getNode != this) getNode.litOf else null - def litValue(default: BigInt = BigInt(-1)): BigInt = - if (isLit) litOf.value - else default - def floLitValue: Float = intBitsToFloat(litValue().toInt) - def dblLitValue: Double = longBitsToDouble(litValue().toLong) + /** The cat operator to combine two values + * {{{ 0x5 ## 0x3 => 0x53 }}} + * @param b Node to cat after + * @return a new node as the combination of both this node and b + */ + def ##(b: Node): Node = Op("##", Node.sumWidth _, this, b ); + /** This function determines if a node is a literal, a fixed value */ + final def isLit: Boolean = litOpt ne None + private[Chisel] def litOpt: Option[Literal] = if (getNode != this) getNode.litOpt else None + /** @return the literal value of a node + * @throws ChiselException if there is no literal value available + */ + def litOf: Literal = litOpt match { case Some(l) => l case None => throwException("no lit value for this node") } + /** @return the literal value of the node as a BigInt + * {{{ Bool(true).litValue() => BigInt(1) }}} + */ + def litValue(default: BigInt = BigInt(-1)): BigInt = litOpt match { + case None => default case Some(l) => l.value } + /** Convert the node literal to a Float */ + def floLitValue: Float = java.lang.Float.intBitsToFloat(litValue().toInt) + /** Convert the node literal to a Double */ + def dblLitValue: Double = java.lang.Double.longBitsToDouble(litValue().toLong) // TODO: MOVE TO WIRE - def assign(src: Node): Unit = throw new Exception("unimplemented assign") - def <>(src: Node): Unit = throw new Exception("unimplemented <>") + def assign(src: Node): Unit = throwException("unimplemented assign") + def <>(src: Node): Unit = throwException("unimplemented <>") def ^^(src: Node): Unit = src <> this - def getLit: Literal = this.asInstanceOf[Literal] private var _isIo = false + /** @return this node is an I/O Node for a module */ def isIo = _isIo - def isIo_=(isIo: Boolean) = _isIo = isIo - def isReg: Boolean = false + protected[Chisel] def isIo_=(isIo: Boolean) = _isIo = isIo + /** @return this node is a Register */ def isUsedByClockHi: Boolean = consumers.exists(_.usesInClockHi(this)) def usesInClockHi(i: Node): Boolean = false - def initOf (n: String, widthfunc: (=> Node) => Width, ins: Iterable[Node]): Node = { - name = n; - inferWidth = widthfunc; + // TODO: should be private[Chisel]? + /** Init the node and calculate its width and add inputs to the node + * @param n name of node + * @param widthfunc the function to use to calculate the width of the node + * @param ins Nodes that are inputs to this node + */ + def initOf (n: String, widthfunc: (=> Node) => Width, ins: Seq[Node]): Node = { + name = n + inferWidth = widthfunc inputs ++= ins this } + // TODO: should be private[Chisel]? + /** Init the node and calculate its width and add inputs to the node + * @param n name of node + * @param widthFunc the function to use to calculate the width of the node + * @param ins Nodes that are inputs to this node + */ def init (n: String, widthFunc: (=> Node) => Width, ins: Node*): Node = { initOf(n, widthFunc, ins.toList); } + // TODO: should be private[Chisel]? + /** Init the node and calculate its width and add inputs to the node + * @param n name of node + * @param w the bit width of the node + * @param ins Nodes that are inputs to this node + */ def init (n: String, w: Int, ins: Node*): Node = { width_ = Width(w) - initOf(n, fixWidth(w), ins.toList) + initOf(n, Node.fixWidth(w), ins.toList) } - // Called while we're walking the graph inferring the width of nodes. - // We return true if we should continue to walk the graph, - // either because there's a node whose width we don't know, - // or because we updated a node's width. + // TODO: should be private[Chisel]? + /** Called while we're walking the graph inferring the width of nodes. + We return true if we should continue to walk the graph, + either because there's a node whose width we don't know, + or because we updated a node's width. */ def infer: Boolean = { - val res = inferWidth(this); + val res = inferWidth(this) if (! res.isKnown) { true } else if (res != widthW) { @@ -272,60 +342,54 @@ abstract class Node extends nameable { false } } - - def isTopLevelIO: Boolean = isIo && (component == Driver.topComponent) - lazy val isInObject: Boolean = - (isIo && (Driver.isIoDebug || component == Driver.topComponent)) || - Driver.topComponent.debugs.contains(this) || - isReg || isUsedByClockHi || Driver.isDebug && named || - Driver.emitTempNodes || - Driver.backend.isInObject(this) + /** @return is this node I/O for the top level module */ + def isTopLevelIO = isIo && component == Module.topMod - lazy val isInVCD: Boolean = name != "reset" && needWidth() > 0 && + private[Chisel] lazy val isInObject = + (isIo && (Driver.isIoDebug || component == Module.topMod)) || + component.debugs(this) || (Driver.backend isInObject this) || + isUsedByClockHi || Driver.isDebug && named || Driver.emitTempNodes + + private[Chisel] lazy val isInVCD = Driver.isVCD && name != "reset" && needWidth() > 0 && (named || Driver.emitTempNodes) && - ((isIo && isInObject) || isReg || Driver.isDebug) + ((isIo && isInObject) || (this match {case _: Delay => true case _ => false}) || Driver.isDebug) - /** Prints all members of a node and recursively its inputs up to a certain - depth level. This method is purely used for debugging. */ - def printTree(writer: PrintStream, depth: Int = 4, indent: String = ""): Unit = { - if (depth < 1) return; - writer.println(indent + getClass + " width=" + getWidth + " #inputs=" + inputs.length); + /** Prints all members of a node and recursively its inputs up to a certain depth level + * This method is purely used for debugging */ + def printTree(writer: java.io.PrintStream, depth: Int = 4, indent: String = ""): Unit = { + if (depth < 1) return + writer.println(indent + getClass + " width=" + getWidth + " #inputs=" + inputs.length) this match { - case fix: SInt => { - if (!(fix.comp == null)) { - writer.println(indent + " (has comp " + fix.comp + " of type " + fix.comp.getClass + ")"); - } + case fix: SInt => fix.comp match { + case None => + case Some(p) => + writer.println(indent + " (has comp " + p + " of type " + p.getClass + ")") } - case bits: UInt => { - if (!(bits.comp == null)) { - writer.println(indent + "(has comp " + bits.comp + ")"); - } + case bits: UInt => bits.comp match { + case None => + case Some(p) => + writer.println(indent + "(has comp " + p + ")") } case any => writer.println(indent + this) } - writer.println("sccIndex: " + sccIndex) - writer.println("sccLowlink: " + sccLowlink) + writer.println("sccIndex: " + (sccIndex getOrElse -1)) + writer.println("sccLowlink: " + (sccLowlink getOrElse -1)) writer.println("component: " + component) writer.println("isTypeNode: " + isTypeNode) writer.println("depth: " + depth) writer.println("width: " + width_) writer.println("index: " + emitIndex) writer.println("consumers.size: " + consumers.size) - writer.println("nameHolder: " + nameHolder) writer.println("line: " + line) for (in <- inputs) { - if (in == null) { - writer.println("null"); - } else { - in.printTree(writer, depth-1, indent + " "); - } + in.printTree(writer, depth-1, indent + " "); } } - def forceMatchingWidths { } + private[Chisel] def forceMatchingWidths { } - def matchWidth(w: Width): Node = { + private[Chisel] def matchWidth(w: Width): Node = { val this_width = this.widthW if (w.isKnown && this_width.isKnown) { val my_width = this_width.needWidth() @@ -346,14 +410,7 @@ abstract class Node extends nameable { } } - def setName(n: String) { - name = n - named = true; - } - - var isWidthWalked = false; - - def getWidthW(): Width = { + private[Chisel] def getWidthW(): Width = { val oldDriverisInGetWidth = Driver.isInGetWidth Driver.isInGetWidth = true val w = widthW @@ -361,6 +418,8 @@ abstract class Node extends nameable { w } + /** @return the width or number of bits used by this node + * @throws ChiselException if the width of the node is unknown */ def getWidth(): Int = { val w = getWidthW() if (w.isKnown) @@ -369,76 +428,62 @@ abstract class Node extends nameable { throwException("Node.getWidth() for node " + this + " returns unknown width") } - def removeTypeNodes() { - for(i <- 0 until inputs.length) { - if(inputs(i) == null){ - val error = new ChiselError(() => {"NULL Input for " + this.getClass + " " + this + " in Module " + component}, this.line); - if (!ChiselErrors.contains(error)) { - ChiselErrors += error - } - } - else if(inputs(i).isTypeNode) { - inputs(i) = inputs(i).getNode; - } + private[Chisel] def removeTypeNodes() { + for ((input, i) <- inputs.zipWithIndex) { + inputs(i) = input.getNode } } + /** @return The root node input */ def getNode: Node = if (!isTypeNode || inputs.isEmpty) this else inputs(0).getNode + /** @return This node as a UInt */ def toBits(): UInt = chiselCast(this){UInt()} + def toSInt(): SInt = chiselCast(this){SInt()} + def toUInt(): UInt = chiselCast(this){UInt()} + + // Chisel3 - rename these to make the reinterpret cast more explicit + final def asUInt() = toUInt() + final def asSInt() = toSInt() + /** @return This node */ def toNode: Node = this - def addConsumers() { + private[Chisel] def addConsumers() { for ((i, off) <- inputs.zipWithIndex) { /* By construction we should not end-up with null inputs. */ - assert(i != null, ChiselError.error("input " + off + assert(i != null, ChiselError.error("Internal Error: input " + off + " of " + inputs.length + " for node " + this + " is null")) i.consumers += this } } - def extract (widths: Array[Int]): List[UInt] = { - var res: List[UInt] = Nil; - var off = 0; - for (w <- widths) { - res = this.asInstanceOf[UInt](off + w - 1, off) :: res; - off += w; - } - res.reverse - } - def extract (b: Bundle): List[Node] = { - var res: List[Node] = Nil; - var off = 0; - for ((n, io) <- b.flatten) { - if (io.dir == OUTPUT) { - val w = io.needWidth(); - res = NodeExtract(this,off + w - 1, off) :: res; - off += w; - } - } - res.reverse - } + /** Deprecated: Do not use */ def maybeFlatten: Seq[Node] = { this match { - case b: Bundle => - val buf = ArrayBuffer[Node](); - for ((n, e) <- b.flatten) buf += e.getNode; - buf - case o => - Array[Node](getNode); + case b: Bundle => b.flatten.unzip._2 map (_.getNode) + case _ => Array[Node](getNode) } } - lazy val emitIndex: Int = componentOf.nextIndex + private[Chisel] lazy val emitIndex: Int = componentOf.nextIndex + /** @return the unique hashCode for this node */ override def hashCode: Int = _id + /** Compare two nodes + * @param that the node to compare with + */ override def equals(that: Any): Boolean = that match { case n: Node => this eq n - case null => false - case _ => ChiselError.error("can't compare Node " + this + " and non-Node " + that); false + case _ => { + // Comparison against null is legal and returns false. + if (that != null) { + ChiselError.error("can't compare Node " + this + " and non-Node " + that) + } + false + } } def canCSE: Boolean = false @@ -452,27 +497,24 @@ abstract class Node extends nameable { } checkOne(this, x) || checkOne(x, this) } + /** Force the bit width of a node + * @param w the bit width to force*/ def setWidth(w: Int) = { width_.setWidth(w) - inferWidth = fixWidth(w); - } - // Return a value or raise an exception. - def needWidth(): Int = { - val w = widthW - w.needWidth() - } - - // Return true if the width of this node is known (set). - def isKnownWidth: Boolean = { - val w = widthW - w.isKnown + inferWidth = Node.fixWidth(w) } + /** @return the bitWidth of the node + * @throws ChiselException if the width is not yet defined + */ + def needWidth(): Int = widthW.needWidth + /** Return true if the width of this node is known (set). */ + private[Chisel] def isKnownWidth: Boolean = widthW.isKnown // The following are used for optimizations, notably, dealing with zero-width wires. /* If we've updated this node since our last visit. */ var modified = false - // Eliminate any zero-width wires attached to this node. - // Return true if we modified the node. + /** Eliminate any zero-width wires attached to this node + * @return if the node was modified */ def W0Wtransform() { // If we're just a type node, we're now a zero-width type node. if (isTypeNode) { @@ -481,27 +523,47 @@ abstract class Node extends nameable { } } - // Review a node for optimization possibilities if its children have been updated. + /** Review a node for optimization possibilities if its children have been updated */ def review() { } - // Parent nodes - used during optimization. - var parents = LinkedHashSet[Node]() - // Replace the subtree starting from this node with the indicated replacement. + /** Replace the subtree starting from this node with the indicated replacement + * @param newNode The node to start tree from */ def replaceTree(newNode: Node) { val oldNode = this /* We are no longer anyone's parent. */ for (c <- inputs) { - c.parents -= oldNode + c.consumers -= oldNode } /* Replace our role as input in our parent nodes with the replacement node. */ - for (p <- oldNode.parents; i <- 0 until p.inputs.length if p.inputs(i) == oldNode) { - newNode.parents += p + for (p <- oldNode.consumers; i <- 0 until p.inputs.length if p.inputs(i) == oldNode) { + newNode.consumers += p p.inputs(i) = newNode } oldNode.inputs.clear() - oldNode.parents.clear() + oldNode.consumers.clear() + } + + /** Chisel3 - type-only nodes (no data - no initialization or assignment) + This is used to determine which nodes must be Wire() wrapped, + and whether Wire() wrapping of the node is legal or not. */ + protected[Chisel] def isTypeOnly: Boolean = { + // If we're the last node in a type chain, the chain is type only. + // Nodes with real data will override this definition. + // NOTE: We don't look at this node's inputs, since if this is an assignment, + // they will be the source of the assignment, and they will most likely be data carrying nodes. + val gNode = getNode + if (gNode == this) { + true + } else { + gNode.isTypeOnly + } + } + + /** @return this node has zero-width */ + def isZeroWidth: Boolean = { + isKnownWidth && getWidth == 0 } } diff --git a/src/main/scala/Op.scala b/src/main/scala/Op.scala index d98897b4..a5775cb7 100644 --- a/src/main/scala/Op.scala +++ b/src/main/scala/Op.scala @@ -1,5 +1,5 @@ /* - Copyright (c) 2011, 2012, 2013, 2014 The Regents of the University of + Copyright (c) 2011 - 2016 The Regents of the University of California (Regents). All Rights Reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: @@ -29,12 +29,18 @@ */ package Chisel -import scala.math.max -import Node._ -import Literal._ import Op._ +import Node._ +/** Cast a node to be Bits */ object chiselCast { + /** @tparam S type of the node to cast + * @tparam T type of the Bits to cast to + * @param x the node to case + * @param gen the instantiation to cast to + * @example + * {{{ val myUInt = chiselCast[Data, UInt](myData, UInt(width=8)) }}} + */ def apply[S <: Node, T <: Bits](x: S)(gen: => T): T = { val res = gen res assign x.toNode @@ -42,6 +48,7 @@ object chiselCast { } } +// TODO: make private[Chisel]? object UnaryOp { val Op = OpGen1({ new UnaryOp(_: String) }) _ def apply(op: String, widthInfer: (=> Node) => Width, x: Node): Node = { @@ -68,11 +75,12 @@ object UnaryOp { case "dfloor" => Op("dfloor", fixWidth(doubleWidth), x) case "dceil" => Op("dceil", fixWidth(doubleWidth), x) case "dround" => Op("dround", fixWidth(doubleWidth), x) - case any => throw new Exception("Unrecognized operator " + op) + case any => throwException("Unrecognized operator " + op) } } } +// TODO: make private[Chisel]? object BinaryOp { val Op = OpGen2({ new BinaryOp(_)}) _ def apply(op: String, widthInfer: (=> Node) => Width, x: Node, y: Node): Node = { @@ -108,7 +116,9 @@ object BinaryOp { case "d/" => Op("d/", fixWidth(doubleWidth), x, y ) case "d%" => Op("d%", fixWidth(doubleWidth), x, y ) case "dpow" => Op("dpow", fixWidth(doubleWidth), x, y ) - case any => throw new Exception("Unrecognized operator " + op) + case "+&" => Op("+", maxWidthPlusOne _, x, y ) + case "-&" => Op("-", maxWidthPlusOne _, x, y ) + case any => throwException("Unrecognized operator " + op) } } @@ -119,12 +129,13 @@ object BinaryOp { private def modSUWidth(x: => Node) = x.inputs(0).needWidth().min(x.inputs(1).needWidth() - 1) } - +// TODO: make private[Chisel]? object LogicalOp { val Op = OpGen2({ new LogicalOp(_)}) _ def apply(x: Node, y: Node, op: String): Bool = { val node = op match { case "===" => Op("==", fixWidth(1), x, y) + case "=/=" => Op("!=", fixWidth(1), x, y) case "!=" => Op("!=", fixWidth(1), x, y) case "<" => Op("<", fixWidth(1), x, y) case "<=" => Op("<=", fixWidth(1), x, y) @@ -142,7 +153,7 @@ object LogicalOp { case "d<" => Op("d<", fixWidth(1), x, y) case "d<=" => Op("d<=", fixWidth(1), x, y) case "d>=" => Op("d>=", fixWidth(1), x, y) - case any => throw new Exception("Unrecognized operator " + op); + case any => throwException("Unrecognized operator " + op); } Bool(OUTPUT).fromNode(node) } @@ -153,7 +164,7 @@ object ReductionOp { def apply(x: Node, op: String): Node = { op match { case "^" => Op("^", fixWidth(1), x) - case any => throw new Exception("Unrecognized operator " + op) + case any => throwException("Unrecognized operator " + op) } } } @@ -162,6 +173,7 @@ object Op { val floatWidth = 32 val doubleWidth = 64 val logicalChars = """^([!=<>]=)|([<>])$""".r + def apply(name: String, widthInfer: (=> Node) => Width, a: Node, b: Node): Node = { // It's a binary operator. Is it a logical op? if (logicalChars.findFirstIn(name).nonEmpty) { @@ -170,258 +182,209 @@ object Op { OpGen2({ new BinaryOp(_)})(name, widthInfer, a, b) } } + def OpGen2(makeObj: String => Op)(name: String, widthInfer: (=> Node) => Width, a: Node, b: Node): Node = { - val (a_lit, b_lit) = (a.litOf, b.litOf) - if (a_lit != null) name match { - case "==" => if (a_lit.isZ) return zEquals(b, a) - case "!=" => if (a_lit.isZ) return !zEquals(b, a) - case "<<" | ">>" | "s>>" => if (a_lit.value == 0) return Literal(0) - case _ => ; - } - if (b_lit != null) name match { - case "==" => if (b_lit.isZ) return zEquals(a, b) - case "!=" => if (b_lit.isZ) return !zEquals(a, b) - case _ => ; + def error { + ChiselError.error("Operator " + name + " with inputs " + a + ", " + b + " does not support literals with ?") } - if (a_lit != null && b_lit != null && a_lit.isKnownWidth && b_lit.isKnownWidth) { - val (aw, bw) = (a_lit.needWidth(), b_lit.needWidth()); - val (av, bv) = (a_lit.value, b_lit.value); - name match { - case "==" => return Literal(if (av == bv) 1 else 0) - case "!=" => return Literal(if (av != bv) 1 else 0); - case "<" => return Literal(if (av < bv) 1 else 0); - case "<=" => return Literal(if (av <= bv) 1 else 0); - case "##" => return Literal(av << bw | bv, aw + bw); - // "+" and "-" may need to widen the result. - // Let the Literal code take care of it, unless an explicit width has been specified. - case "+" => return Literal(av + bv, List(aw, bw, Literal.bitLength((av + bv)).toInt).max) - case "-" => return Literal(av - bv, List(aw, bw, Literal.bitLength((av - bv)).toInt).max) - case "|" => return Literal(av | bv, max(aw, bw)); - case "&" => return Literal(av & bv, max(aw, bw)); - case "^" => return Literal(av ^ bv, max(aw, bw)); - case "<<" => return Literal(av << bv.toInt, aw + bv.toInt); - case ">>" => return Literal(av >> bv.toInt, aw - bv.toInt); - case _ => ; + def default = { + (a.litOpt, b.litOpt) match { + case (Some(al), Some(bl)) if al.isZ && bl.isZ => error + case _ => } + val res = makeObj(name) ; res.init("", widthInfer, a, b) ; res } - if (a.isInstanceOf[Flo] && b.isInstanceOf[Flo]) { - if (a_lit != null && b_lit != null) { - val (fa_val, fb_val) = (a_lit.floLitValue, b_lit.floLitValue) - name match { - case "f+" => return Flo(fa_val + fb_val); - case "f-" => return Flo(fa_val - fb_val); - case "f*" => return Flo(fa_val * fb_val); - case "f/" => return Flo(fa_val / fb_val); - case "f%" => return Flo(fa_val % fb_val); - case "f==" => return Bool(fa_val == fb_val); - case "f!=" => return Bool(fa_val != fb_val); - case "f>" => return Bool(fa_val > fb_val); - case "f<" => return Bool(fa_val < fb_val); - case "f>=" => return Bool(fa_val >= fb_val); - case "f<=" => return Bool(fa_val <= fb_val); - case _ => ; - } - } else if (a_lit != null) { - val fa_val = a_lit.floLitValue - if (fa_val == 0.0) { - name match { - case "f+" => return b; - case "f*" => return Flo(0.0.toFloat); - case "f/" => return Flo(0.0.toFloat); - case _ => ; - } - } else if (fa_val == 1.0) { - name match { - case "f*" => return b; - case _ => ; - } - } - } else if (b_lit != null) { - val fb_val = b_lit.floLitValue - if (fb_val == 0.0) { - name match { - case "f+" => return a; - case "f*" => return Flo(0.0.toFloat); - case _ => ; - } - } else if (fb_val == 1.0) { - name match { - case "f*" => return a; - case "f/" => return a; - case "f%" => return a; - case _ => ; - } - } - } + + def zEquals(a: Node, b: Literal) = { + val (bits, mask, swidth) = Literal.parseLit(b.name) + val Op = OpGen2({ new BinaryOp(_)}) _ + UInt(Op("==", fixWidth(1), Op("&", maxWidth _, a, Literal(BigInt(mask, 2))), Literal(BigInt(bits, 2)))) } - if (a.isInstanceOf[Dbl] && b.isInstanceOf[Dbl]) { - if (a_lit != null && b_lit != null) { - val (fa_val, fb_val) = (a_lit.dblLitValue, b_lit.dblLitValue) - // println(" FOLDING " + name + " " + fa_val + " " + fb_val); - name match { - case "d+" => return Dbl(fa_val + fb_val); - case "d-" => return Dbl(fa_val - fb_val); - case "d*" => return Dbl(fa_val * fb_val); - case "d/" => return Dbl(fa_val / fb_val); - case "d%" => return Dbl(fa_val % fb_val); - case "d==" => return Bool(fa_val == fb_val); - case "d!=" => return Bool(fa_val != fb_val); - case "d>" => return Bool(fa_val > fb_val); - case "d<" => return Bool(fa_val < fb_val); - case "d>=" => return Bool(fa_val >= fb_val); - case "d<=" => return Bool(fa_val <= fb_val); - case _ => ; - } - } else if (a_lit != null) { - val fa_val = a_lit.dblLitValue - // println("FA " + fa_val + " NAME " + name); - if (fa_val == 0.0) { - // println("FOLDING " + name); - name match { - case "d+" => return b; - case "d*" => return Dbl(0.0); - case "d/" => return Dbl(0.0); - case "d%" => return Dbl(0.0); - case _ => ; - } - } else if (fa_val == 1.0) { - // println("FOLDING " + name); + def LitOp = (a.litOpt, b.litOpt) match { + case (Some(al), _) if name == "==" && al.isZ => zEquals(b, al) + case (Some(al), _) if name == "!=" && al.isZ => !zEquals(b, al) + case (Some(al), _) if (name == "<<" || name == ">>" || name == "s>>") && al.value == 0 => Literal(0) + case (_, Some(bl)) if name == "==" && bl.isZ => zEquals(a, bl) + case (_, Some(bl)) if name == "!=" && bl.isZ => !zEquals(a, bl) + // isZ is unsupported for all other operators. + case (Some(al), _) if al.isZ => error ; Literal(0) + case (_, Some(bl)) if bl.isZ => error ; Literal(0) + + case (Some(al), Some(bl)) if al.isKnownWidth && bl.isKnownWidth => + val (aw, bw) = (al.needWidth(), bl.needWidth()) + val (av, bv) = (al.value, bl.value) name match { - case "d*" => return b; - case _ => ; + case "==" => Literal(if (av == bv) 1 else 0) + case "!=" => Literal(if (av != bv) 1 else 0) + case "<" => Literal(if (av < bv) 1 else 0) + case "<=" => Literal(if (av <= bv) 1 else 0) + case "##" => Literal(av << bw | bv, aw + bw) + // "+" and "-" should NOT widen the result. + case "+" => Literal(av + bv, math.max(aw, bw)) + case "-" => Literal(av - bv, math.max(aw, bw)) + case "|" => Literal(av | bv, math.max(aw, bw)) + case "&" => Literal(av & bv, math.max(aw, bw)) + case "^" => Literal(av ^ bv, math.max(aw, bw)) + case "<<" => Literal(av << bv.toInt, aw + bv.toInt) + case ">>" => Literal(av >> bv.toInt, aw - bv.toInt) + case _ => FloDblOp } + case _ => FloDblOp + } + + def FloDblOp = (a, b) match { + case (_: Flo, _: Flo) => (a.litOpt, b.litOpt) match { + case (Some(al), Some(bl)) if name == "f+" => Flo(al.floLitValue + bl.floLitValue) + case (Some(al), Some(bl)) if name == "f-" => Flo(al.floLitValue - bl.floLitValue) + case (Some(al), Some(bl)) if name == "f*" => Flo(al.floLitValue * bl.floLitValue) + case (Some(al) ,Some(bl)) if name == "f/" => Flo(al.floLitValue / bl.floLitValue) + case (Some(al), Some(bl)) if name == "f%" => Flo(al.floLitValue % bl.floLitValue) + case (Some(al), Some(bl)) if name == "f==" => Bool(al.floLitValue == bl.floLitValue) + case (Some(al), Some(bl)) if name == "f!=" => Bool(al.floLitValue != bl.floLitValue) + case (Some(al), Some(bl)) if name == "f>" => Bool(al.floLitValue > bl.floLitValue) + case (Some(al), Some(bl)) if name == "f<" => Bool(al.floLitValue < bl.floLitValue) + case (Some(al), Some(bl)) if name == "f>=" => Bool(al.floLitValue >= bl.floLitValue) + case (Some(al), Some(bl)) if name == "f<=" => Bool(al.floLitValue <= bl.floLitValue) + case (Some(al), _) if name == "f+" && al.floLitValue == 0.0 => b + case (Some(al), _) if name == "f*" && al.floLitValue == 0.0 => Flo(0.0.toFloat) + case (Some(al), _) if name == "f/" && al.floLitValue == 0.0 => Flo(0.0.toFloat) + case (Some(al), _) if name == "f%" && al.floLitValue == 0.0 => Flo(0.0.toFloat) + case (Some(al), _) if name == "f*" && al.floLitValue == 1.0 => b + case (_, Some(bl)) if name == "f+" && bl.floLitValue == 0.0 => a + case (_, Some(bl)) if name == "f*" && bl.floLitValue == 0.0 => Flo(0.0.toFloat) + case (_, Some(bl)) if name == "f*" && bl.floLitValue == 1.0 => a + case (_, Some(bl)) if name == "f/" && bl.floLitValue == 1.0 => a + case (_, Some(bl)) if name == "f%" && bl.floLitValue == 1.0 => a + case _ => CppFloOp } - } else if (b_lit != null) { - val fb_val = b_lit.dblLitValue - // println("FB " + fb_val + " NAME " + name); - if (fb_val == 0.0) { - // println("FOLDING " + name); - name match { - case "d+" => return a; - case "d*" => return Dbl(0.0); - case _ => ; - } - } else if (fb_val == 1.0) { - // println("FOLDING " + name); - name match { - case "d*" => return a; - case "d/" => return a; - case "d%" => return a; - case _ => ; - } + case (_: Dbl, _: Dbl) => (a.litOpt, b.litOpt) match { + case (Some(al), Some(bl)) if name == "d+" => Dbl(al.dblLitValue + bl.dblLitValue) + case (Some(al), Some(bl)) if name == "d-" => Dbl(al.dblLitValue - bl.dblLitValue) + case (Some(al), Some(bl)) if name == "d*" => Dbl(al.dblLitValue * bl.dblLitValue) + case (Some(al) ,Some(bl)) if name == "d/" => Dbl(al.dblLitValue / bl.dblLitValue) + case (Some(al), Some(bl)) if name == "d%" => Dbl(al.dblLitValue % bl.dblLitValue) + case (Some(al), Some(bl)) if name == "d==" => Bool(al.dblLitValue == bl.dblLitValue) + case (Some(al), Some(bl)) if name == "d!=" => Bool(al.dblLitValue != bl.dblLitValue) + case (Some(al), Some(bl)) if name == "d>" => Bool(al.dblLitValue > bl.dblLitValue) + case (Some(al), Some(bl)) if name == "d<" => Bool(al.dblLitValue < bl.dblLitValue) + case (Some(al), Some(bl)) if name == "d>=" => Bool(al.dblLitValue >= bl.dblLitValue) + case (Some(al), Some(bl)) if name == "d<=" => Bool(al.dblLitValue <= bl.dblLitValue) + case (Some(al), _) if name == "d+" && al.dblLitValue == 0.0 => b + case (Some(al), _) if name == "d*" && al.dblLitValue == 0.0 => Dbl(0.0) + case (Some(al), _) if name == "d/" && al.dblLitValue == 0.0 => Dbl(0.0) + case (Some(al), _) if name == "d%" && al.dblLitValue == 0.0 => Dbl(0.0) + case (Some(al), _) if name == "d*" && al.dblLitValue == 1.0 => b + case (_, Some(bl)) if name == "d+" && bl.dblLitValue == 0.0 => a + case (_, Some(bl)) if name == "d*" && bl.dblLitValue == 0.0 => Dbl(0.0) + case (_, Some(bl)) if name == "d*" && bl.dblLitValue == 1.0 => a + case (_, Some(bl)) if name == "d/" && bl.dblLitValue == 1.0 => a + case (_, Some(bl)) if name == "d%" && bl.dblLitValue == 1.0 => a + case _ => CppFloOp } + case _ => CppFloOp } + def signAbs(x: Node): (Bool, UInt) = { + val f = x.asInstanceOf[SInt] + val s = f < SInt(0) + (s, Mux(s, -f, f).toUInt) } - if (Driver.backend.isInstanceOf[CppBackend] || Driver.backend.isInstanceOf[FloBackend]) { - def signAbs(x: Node): (Bool, UInt) = { - val f = x.asInstanceOf[SInt] - val s = f < SInt(0) - (s, Mux(s, -f, f).toUInt) - } - name match { - case "s<" | "s<=" => - if (name != "s<" || b.litOf == null || b.litOf.value != 0) { - val fixA = a.asInstanceOf[SInt] - val fixB = b.asInstanceOf[SInt] - val msbA = fixA < SInt(0) - val msbB = fixB < SInt(0) - val ucond = Bool(OUTPUT).fromNode(LogicalOp(fixA, fixB, name.tail)) - return Mux(msbA === msbB, ucond, msbA) - } + def CppFloOp = Driver.backend match { + case _: CppBackend | _: FloBackend => name match { + case "s<" | "s<=" if name != "s<" || b.litOpt == None || b.litOf.value != 0 => + val fixA = a.asInstanceOf[SInt] + val fixB = b.asInstanceOf[SInt] + val msbA = fixA < SInt(0) + val msbB = fixB < SInt(0) + val ucond = Bool(OUTPUT).fromNode(LogicalOp(fixA, fixB, name.tail)) + Mux(msbA === msbB, ucond, msbA) case "s*s" | "s*u" => val (signA, absA) = signAbs(a) val (signB, absB) = signAbs(b) val prod = absA * absB - return Mux(signA ^ signB, -prod, prod) + Mux(signA ^ signB, -prod, prod) case "s/s" => val (signA, absA) = signAbs(a) val (signB, absB) = signAbs(b) val quo = absA / absB - return Mux(signA != signB, -quo, quo) + Mux(signA =/= signB, -quo, quo) case "s%s" => val (signA, absA) = signAbs(a) val (signB, absB) = signAbs(b) val rem = absA % absB - return Mux(signA, -rem, rem) + Mux(signA, -rem, rem) case "%" => val (au, bu) = (a.asInstanceOf[UInt], b.asInstanceOf[UInt]) - return Op("-", widthInfer, au, au/bu*bu) - case _ => + Op("-", widthInfer, au, au/bu*bu) + case _ => default } + case _ => default } - if (a.isLit && a.litOf.isZ || b.isLit && b.litOf.isZ) - ChiselError.error({"Operator " + name + " with inputs " + a + ", " + b + " does not support literals with ?"}); - val res = makeObj(name) - res.init("", widthInfer, a, b); - res + + LitOp } + def apply(name: String, widthInfer: (=> Node) => Width, a: Node): Node = { // It's a unary operator. OpGen1({ new UnaryOp(_)})(name, widthInfer, a) } def OpGen1(makeObj: String => Op)(name: String, widthInfer: (=> Node) => Width, a: Node): Node = { - if (a.litOf != null) { - if (a.litOf.isZ) - ChiselError.error({"Operator " + name + " with input " + a + " does not support literals with ?"}); - val wa = a.litOf.needWidth() - name match { - case "~" => return Literal((-a.litOf.value-1)&((BigInt(1) << wa)-1), wa); - case _ => ; - } - } - val a_lit = a.litOf - if (a.isInstanceOf[Dbl]) { - if (a_lit != null) { - val fa_val = a_lit.dblLitValue - name match { - case "dsin" => return Dbl(Math.sin(fa_val)); - case "dcos" => return Dbl(Math.cos(fa_val)); - case "dtan" => return Dbl(Math.tan(fa_val)); - case "dasin" => return Dbl(Math.asin(fa_val)); - case "dacos" => return Dbl(Math.acos(fa_val)); - case "datan" => return Dbl(Math.atan(fa_val)); - case "dsqrt" => return Dbl(Math.sqrt(fa_val)); - case "dlog" => return Dbl(Math.log(fa_val)); - case "dfloor" => return Dbl(Math.floor(fa_val)); - case "dceil" => return Dbl(Math.ceil(fa_val)); - case "dround" => return Dbl(Math.round(fa_val)); - case "dToFix" => return Literal(fa_val.toInt); - case _ => ; - } - } + def default = { val res = makeObj(name) ; res.init("", widthInfer, a) ; res } + a.litOpt match { + case Some(al) if al.isZ => + ChiselError.error("Operator " + name + " with input " + a + " does not support literals with ?") + case _ => } - if (a.isInstanceOf[Flo]) { - if (a_lit != null) { - val fa_val = a_lit.floLitValue - name match { - case "fsin" => return Flo(Math.sin(fa_val).toFloat); - case "fcos" => return Flo(Math.cos(fa_val).toFloat); - case "ftan" => return Flo(Math.tan(fa_val).toFloat); - case "fasin" => return Flo(Math.asin(fa_val).toFloat); - case "facos" => return Flo(Math.acos(fa_val).toFloat); - case "fatan" => return Flo(Math.atan(fa_val).toFloat); - case "fsqrt" => return Flo(Math.sqrt(fa_val).toFloat); - case "flog" => return Flo(Math.log(fa_val).toFloat); - case "ffloor" => return Dbl(Math.floor(fa_val).toFloat); - case "fceil" => return Dbl(Math.ceil(fa_val).toFloat); - case "fround" => return Dbl(Math.round(fa_val).toFloat); - case "fToFix" => return Literal(fa_val.toLong); - case _ => ; - } + a.litOpt match { + case Some(al) if name == "~" => + val wa = al.needWidth() + Literal((-al.value-1)&((BigInt(1) << wa)-1), wa) + case _ => a match { + case _: Flo => a.litOpt match { + case Some(al) => + val fa_val = al.floLitValue + name match { + case "fsin" => Flo(Math.sin(fa_val).toFloat) + case "fcos" => Flo(Math.cos(fa_val).toFloat) + case "ftan" => Flo(Math.tan(fa_val).toFloat) + case "fasin" => Flo(Math.asin(fa_val).toFloat) + case "facos" => Flo(Math.acos(fa_val).toFloat) + case "fatan" => Flo(Math.atan(fa_val).toFloat) + case "fsqrt" => Flo(Math.sqrt(fa_val).toFloat) + case "flog" => Flo(Math.log(fa_val).toFloat) + case "ffloor" => Dbl(Math.floor(fa_val).toFloat) + case "fceil" => Dbl(Math.ceil(fa_val).toFloat) + case "fround" => Dbl(Math.round(fa_val).toFloat) + case "fToFix" => Literal(fa_val.toLong) + case _ => default + } + case None => default + } + case _: Dbl => a.litOpt match { + case Some(al) => + val fa_val = al.dblLitValue + name match { + case "dsin" => Dbl(Math.sin(fa_val)) + case "dcos" => Dbl(Math.cos(fa_val)) + case "dtan" => Dbl(Math.tan(fa_val)) + case "dasin" => Dbl(Math.asin(fa_val)) + case "dacos" => Dbl(Math.acos(fa_val)) + case "datan" => Dbl(Math.atan(fa_val)) + case "dsqrt" => Dbl(Math.sqrt(fa_val)) + case "dlog" => Dbl(Math.log(fa_val)) + case "dfloor" => Dbl(Math.floor(fa_val)) + case "dceil" => Dbl(Math.ceil(fa_val)) + case "dround" => Dbl(Math.round(fa_val)) + case "dToFix" => Literal(fa_val.toInt) + case _ => default + } + case None => default + } + case _ => default } } - val res = makeObj(name) - res.init("", widthInfer, a); - res - } - - private def zEquals(a: Node, b: Node) = { - val (bits, mask, swidth) = parseLit(b.litOf.name) - val Op = OpGen2({ new BinaryOp(_)}) _ - UInt(Op("==", fixWidth(1), Op("&", maxWidth _, a, Literal(BigInt(mask, 2))), Literal(BigInt(bits, 2)))) } } @@ -442,7 +405,7 @@ abstract class Op extends Node { if (inputs(0).widthW != widthW) inputs(0) = inputs(0).matchWidth(widthW) if (inputs(1).widthW != widthW) inputs(1) = inputs(1).matchWidth(widthW) } else if (List("==", "!=", "<", "<=").contains(op)) { - val w = max(inputs(0).needWidth(), inputs(1).needWidth()) + val w = math.max(inputs(0).needWidth(), inputs(1).needWidth()) if (inputs(0).needWidth() != w) inputs(0) = inputs(0).matchWidth(Width(w)) if (inputs(1).needWidth() != w) inputs(1) = inputs(1).matchWidth(Width(w)) /* Issue #242 - This breaks Verilog simulation: @@ -462,7 +425,7 @@ abstract class Op extends Node { case _ => false } - def lower: Node = throw new Exception("lowering " + op + " is not supported") + def lower: Node = throwException("lowering " + op + " is not supported") def identityFromNode: Int = op match { case "<<" => 0 case ">>" => 0 @@ -492,7 +455,7 @@ abstract class Op extends Node { case "d/" => 1 case "d%" => 1 case "dpow" => 1 - case "==" | "!=" | "<" | ">" | "<=" | ">=" => 0 + case "==" | "!=" | "<" | ">" | "<=" | ">=" | "s<" | "s<=" => 0 } // Transform an operator with one or more zero-width children into an operator without. @@ -516,7 +479,10 @@ abstract class Op extends Node { * We need to create it with a non-zero-width (to avoid complaints from the constructor), * the force its width to zero. */ - val identity = UInt(identityFromNode, 1) + val identity = c match { + case s: SInt => SInt(identityFromNode, 2) // '2' is the smallest allowed width for a signed integer. We'll fix it up below. + case _ => UInt(identityFromNode, 1) + } identity.setWidth(0) inputs(i) = identity modified = true @@ -607,7 +573,7 @@ abstract class Op extends Node { } } /* A zero-width node is always less than a non-zero width node. */ - case "<" | "<=" => { + case "<" | "<=" | "s<" | "s<=" => { /* True if the zero-width child is the first operand. */ replaceTree(if (zeroChildId < nonzeroChildId) trueNode else falseNode) } @@ -628,6 +594,8 @@ abstract class Op extends Node { } } } + // Chisel3 - this node contains data - used for verifying Wire() wrapping + override def isTypeOnly = false } case class LogicalOp(val op: String) extends Op @@ -637,7 +605,7 @@ case class UnaryOp(val op: String) extends Op { /* Inherit the zero-width from our child. */ setWidth(0) /* remove our only child */ - inputs(0).parents -= this + inputs(0).consumers -= this inputs.remove(0, 1) modified = true } diff --git a/src/main/scala/Parameters.scala b/src/main/scala/Parameters.scala index d2d0ba06..e5760fe4 100644 --- a/src/main/scala/Parameters.scala +++ b/src/main/scala/Parameters.scala @@ -60,7 +60,6 @@ package Chisel -import scala.collection.immutable.{Seq=>Seq, Iterable=>Iterable} import scala.{collection=>readonly} import scala.collection.mutable @@ -127,7 +126,7 @@ object Dump { def apply[T](key:Any,value:T):T = {addToDump(key,value); value} def apply[T](knob:Knob[T]):Knob[T] = {knobList += knob.name; knob} def addToDump(key:Any,value:Any) = dump += ((key,value)) - def getDump:String = dump.map(_.toString).reduce(_+"\n"+_) + "\n" + def getDump:String = dump.map(_.toString).reduce(_ + "\n" + _) + "\n" } // objects given to the user in mask functions (site,here,up) @@ -516,7 +515,7 @@ case class BoolEx (expr:Ex[Boolean]) { def || (x:BoolEx):Ex[Boolean] = ExOr(expr,x.expr) def ^ (x:BoolEx):Ex[Boolean] = ExXor(expr,x.expr) def === (x:BoolEx):Ex[Boolean] = ExEq[Boolean](expr,x.expr) - def !== (x:BoolEx):Ex[Boolean] = ExEq[Boolean](expr,x.expr) + def =/= (x:BoolEx):Ex[Boolean] = ExEq[Boolean](expr,x.expr) } object Implicits { @@ -625,20 +624,20 @@ object Ex { import Implicits._ e match { case ExLit(v) => v.toString - case e:ExVar[_]=> "$"+e.name - case ExAnd(a,b) => term(a)+" && "+term(b) - case ExOr(a,b) => term(a)+" || "+term(b) - case ExXor(a,b) => term(a)+" ^ "+term(b) - case ExEq(a,b) => term(a)+" = "+term(b) - case ExNeq(a,b) => term(a)+" != "+term(b) - case ExLt(a,b) => term(a)+" < "+term(b) - case ExLte(a,b) => term(a)+" <= "+term(b) - case ExGt(a,b) => term(a)+" > "+term(b) - case ExGte(a,b) => term(a)+" >= "+term(b) - case ExAdd(a,b) => term(a)+" + "+term(b) - case ExSub(a,b) => term(a)+" - "+term(b) - case ExMul(a,b) => term(a)+" * "+term(b) - case ExMod(a,b) => term(a)+" % "+term(b) + case e:ExVar[_]=> "$" + e.name + case ExAnd(a,b) => term(a) + " && " + term(b) + case ExOr(a,b) => term(a) + " || " + term(b) + case ExXor(a,b) => term(a) + " ^ " + term(b) + case ExEq(a,b) => term(a) + " = " + term(b) + case ExNeq(a,b) => term(a) + " != " + term(b) + case ExLt(a,b) => term(a) + " < " + term(b) + case ExLte(a,b) => term(a) + " <= " + term(b) + case ExGt(a,b) => term(a) + " > " + term(b) + case ExGte(a,b) => term(a) + " >= " + term(b) + case ExAdd(a,b) => term(a) + " + " + term(b) + case ExSub(a,b) => term(a) + " - " + term(b) + case ExMul(a,b) => term(a) + " * " + term(b) + case ExMod(a,b) => term(a) + " % " + term(b) } } } diff --git a/src/main/scala/Params.scala b/src/main/scala/Params.scala index 3186e0ff..2cffa5f6 100644 --- a/src/main/scala/Params.scala +++ b/src/main/scala/Params.scala @@ -1,5 +1,5 @@ /* - Copyright (c) 2011, 2012, 2013, 2014 The Regents of the University of + Copyright (c) 2011 - 2016 The Regents of the University of California (Regents). All Rights Reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: @@ -30,18 +30,7 @@ /* Unfinished. Has 3 basic parameters available */ package Chisel - -import Node._ -import Module._ -import JHFormat._ - import scala.collection.mutable.HashMap -import scala.collection.mutable.ArrayBuffer - -import java.lang.reflect.{Type, ParameterizedType} - -import scala.io.Source -import java.io._ //>Params.scala: Implementation of parameter framework. Defines case class //containers for parameter types. Params object is what actually stores @@ -57,9 +46,9 @@ abstract class Param[+T] { def pname: String var index: Int = -2 var gID: Int = -1 - var register = Params.register(getComponent(), pname, this) + var register = Params.register(Module.getComponent, pname, this) //def register(pName: String) = { pname = pName; Params.register(jack.getComponent(), pname, this)} - def getValue: T = Params.getValue(getComponent(),this.pname,this).asInstanceOf[T] + def getValue: T = Params.getValue(Module.getComponent, pname, this).asInstanceOf[T] } case class ValueParam(pname:String, init: Any) extends Param[Any] { @@ -100,13 +89,13 @@ object Params { type Space = JHFormat.Space var space = new Space var design = new Space - var modules = new HashMap[String, Module] + var modules = new HashMap[String, Option[Module]] var gID: Int = 0 var buildingSpace = true - def getValue(module: Module, pname: String, p: Param[Any]) = { - val mname= if(module == null) "TOP" else {module.getClass.getName} + def getValue(module: Option[Module], pname: String, p: Param[Any]) = { + val mname= module match { case None => "TOP" case Some(p) => p.getClass.getName } if(buildingSpace) p.init else{ val x = design.find(t => (t._3) == (p.gID)) @@ -118,8 +107,8 @@ object Params { } } - def register(module: Module, pname: String, p: Param[Any]) = { - val mname= if(module == null) "TOP" else {module.getClass.getName} + def register(module: Option[Module], pname: String, p: Param[Any]) = { + val mname= module match { case None => "TOP" case Some(p) => p.getClass.getName } modules(mname) = module if(buildingSpace) { space += ((mname,p,gID)) @@ -131,7 +120,7 @@ object Params { def dump_file(filename: String, design: Space) = { val string = JHFormat.serialize(design) - val writer = new PrintWriter(new File(filename)) + val writer = new java.io.PrintWriter(new java.io.File(filename)) println("Dumping to " + filename + ":\n" + string) writer.write(string) writer.close() @@ -150,7 +139,7 @@ object Params { def toCxxStringParams : String = { var string = new StringBuilder("") for ((mname, p, gID) <- space) { - val rmname = if (mname == "TOP") "" else modules(mname).name + "__"; + val rmname = (modules(mname) map (_.name + "__")) getOrElse "" string ++= "const int " + rmname + p.pname + " = " + toCxxStringParam(p) + ";\n" } string.toString @@ -159,7 +148,7 @@ object Params { def toDotpStringParams : String = { var string = new StringBuilder("") for ((mname, p, gID) <- space) { - val rmname = if (mname == "TOP") "" else modules(mname).name + ":"; + val rmname = (modules(mname) map (_.name + ":")) getOrElse "" string ++= rmname + p.pname + " = " + toCxxStringParam(p) + "\n" } string.toString diff --git a/src/main/scala/PartitionIslands.scala b/src/main/scala/PartitionIslands.scala index 01e9ba26..92103d1a 100644 --- a/src/main/scala/PartitionIslands.scala +++ b/src/main/scala/PartitionIslands.scala @@ -1,5 +1,5 @@ /* - Copyright (c) 2011, 2012, 2013, 2014 The Regents of the University of + Copyright (c) 2011 - 2016 The Regents of the University of California (Regents). All Rights Reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: @@ -30,9 +30,7 @@ package Chisel -import scala.collection.mutable.{ArrayBuffer, Set, HashSet, HashMap, ListBuffer, Map, Queue=>ScalaQueue, Stack} -import collection.mutable -import scala.collection.mutable.Map +import scala.collection.mutable.{ArrayBuffer, Set, HashSet, Map, HashMap, Stack} object PartitionIslands { type IslandNodes = scala.collection.immutable.HashSet[Node] @@ -247,7 +245,7 @@ object PartitionIslands { } // Add all the real inputs to island 1 (just to give the dot backend a place to put them). val allNonDelayLeaves = (inputs ++ lits ++ barren ++ bogus) - val allNonDelayLeavesBuffer = allNonDelayLeaves.to[mutable.ArrayBuffer] + val allNonDelayLeavesBuffer = allNonDelayLeaves.to[ArrayBuffer] val allLeaves = allNonDelayLeaves ++ delays // First we mark all the "input" nodes. // This includes all the "true" input nodes, plus any Reg or Mem nodes, @@ -307,11 +305,11 @@ object PartitionIslands { val dstIsland = markedNodes(s.inputs(0)) // Ensure srcIsland and dstIsland exist. if (!res.contains(srcIsland)) { - ChiselError.error("islandHop: node "+ s + " - source island " + srcIsland + " not in results", s.line) + ChiselError.error("islandHop: node " + s + " - source island " + srcIsland + " not in results", s.line) return } if (!res.contains(dstIsland)) { - ChiselError.error("islandHop: node "+ s.inputs(0) + " - destination island " + dstIsland + " not in results", s.inputs(0).line) + ChiselError.error("islandHop: node " + s.inputs(0) + " - destination island " + dstIsland + " not in results", s.inputs(0).line) return } // Remove us from collection of nodes associated with this island. @@ -401,14 +399,14 @@ object PartitionIslands { resArrayBuffer.toArray } - // Generate a mapping from node to island, given an array of islands. + // Generate a mapping from node to islands, given an array of islands. def generateNodeToIslandArray(islands: Array[Island]): Array[NodeIdIslands] = { if (islands == null || islands.size == 0) { return null } else if (! islands.exists(_.nodes.size > 0)) { // No islands with nodes. // Construct an array with a single entry containing an empty set. - return Array[NodeIdIslands](scala.collection.immutable.HashSet.empty) + return Array[NodeIdIslands](new NodeIdIslands()) } // Find the maximum node _id val maxIslandId = islands.map(_.nodes.map(_._id).max).max diff --git a/src/main/scala/ROM.scala b/src/main/scala/ROM.scala index b1009554..696416d9 100644 --- a/src/main/scala/ROM.scala +++ b/src/main/scala/ROM.scala @@ -1,5 +1,5 @@ /* - Copyright (c) 2011, 2012, 2013, 2014 The Regents of the University of + Copyright (c) 2011 - 2016 The Regents of the University of California (Regents). All Rights Reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: @@ -29,22 +29,41 @@ */ package Chisel -import ChiselError._ -import Node._ import scala.collection.SortedMap +/** Read Only Memory object + * Optionally create in a map with integer addresses attached + * Create a [[Chisel.Vec Vec]] of literals rather than ROM directly + */ object ROM { + /** @param elt0 the first data object at address 0 in the ROM + * @param elts any number of data objects for the ROM */ def apply[T <: Data](elt0: T, elts: T*): ROM[T] = apply(elt0 +: elts.toSeq) - def apply[T <: Data](elts: Iterable[T]): ROM[T] = apply(elts.toSeq.zipWithIndex.map { case(z,i) => i -> z }) + /** @param elts any number of data objects for the ROM */ + def apply[T <: Data](elts: Seq[T]): ROM[T] = apply(elts.toSeq.zipWithIndex.map { case(z,i) => i -> z }) + /** @param elt0 the first data object at address 0 in the ROM + * @param elts any number of data objects for the ROM */ def apply[T <: Data](elt0: (Int, T), elts: (Int, T)*): ROM[T] = apply(elt0 +: elts.toSeq) - def apply[T <: Data](elts: Seq[(Int, T)], n: Option[Int]): ROM[T] = new ROM(SortedMap(elts:_*), n) - def apply[T <: Data](elts: Seq[(Int, T)], n: Int): ROM[T] = apply(elts, Some(n)) - def apply[T <: Data](elts: Seq[(Int, T)]): ROM[T] = apply(elts, None) + /** @param elts any number of data objects for the ROM + * @param n optionally force the size of the ROM */ + def apply[T <: Data](elts: Iterable[(Int, T)], n: Option[Int]): ROM[T] = new ROM(SortedMap(elts.toSeq:_*), n) + /** @param elts any number of data objects for the ROM + * @param n optionally force the size of the ROM */ + def apply[T <: Data](elts: Iterable[(Int, T)], n: Int): ROM[T] = apply(elts, Some(n)) + /** @param elts any number of data objects for the ROM */ + def apply[T <: Data](elts: Iterable[(Int, T)]): ROM[T] = apply(elts, None) + /** @param elts any number of data objects for the ROM */ def apply[T <: Data](elts: Array[(Int, T)]): ROM[T] = apply(elts.toSeq, None) + /** @param elts any number of data objects for the ROM + * @param n optionally force the size of the ROM */ def apply[T <: Data](elts: Array[(Int, T)], n: Int): ROM[T] = apply(elts.toSeq, Some(n)) } -class ROM[T <: Data](elts: SortedMap[Int, T], lengthIn: Option[Int] = None) extends Vec[T](i => elts.head._2.clone, Nil) { +/** Class defining a ROM + * Use the [[Chisel.ROM$ ROM]] object rather than instantiating the ROM directly + * @param elts any number of data elements combined with Integer address + * @param lengthIn optionally force the size of the ROM */ +class ROM[T <: Data](elts: SortedMap[Int, T], lengthIn: Option[Int] = None) extends Vec[T](i => elts.head._2.cloneType, Nil) { override val self = elts.unzip._2.toVector override val length: Int = lengthIn match { case Some(x) => require(x > elts.keySet.max); x @@ -52,33 +71,33 @@ class ROM[T <: Data](elts: SortedMap[Int, T], lengthIn: Option[Int] = None) exte } private lazy val data = new ROMData(elts, length) + /** Read data from the ROM at an address */ override def read(addr: UInt): T = { val res = gen(0) - val port = new ROMRead().init("", widthOf(1), addr, data) + val port = new ROMRead().init("", Node.widthOf(1), addr, data) res assign port res.setIsTypeNode res } + /** Illegal, cannot write to Read only memory */ override def write(addr: UInt, data: T): Unit = ChiselError.error("Can't write to ROM") } +/** ROMData stores the data for [[Chisel.ROM ROM]] */ class ROMData(elts: SortedMap[Int, Node], val n: Int) extends Node { - val w = elts.values.map(_.litOf.needWidth()).max + val w = elts.values.map(_.litOpt.get.needWidth()).max val sparseLits = { - inferWidth = fixWidth(w) + inferWidth = Node.fixWidth(w) elts.mapValues(_.matchWidth(Width(w)).litOf) } - val lits = { - val dc = UInt.DC(w).litOf - Array.tabulate(n)(i => sparseLits.getOrElse(i, dc)) - } override lazy val isInObject: Boolean = true override lazy val isInVCD: Boolean = Driver.isVCDMem } +/** Class to read from ROM - internal, do not use */ class ROMRead extends Node { def inputsTailMaxWidth: (=> Node) => Width = { (m) => { m.inputs.map(_.widthW).tail.max diff --git a/src/main/scala/Reg.scala b/src/main/scala/Reg.scala index 0c1ccf1b..4c826030 100644 --- a/src/main/scala/Reg.scala +++ b/src/main/scala/Reg.scala @@ -1,5 +1,5 @@ /* - Copyright (c) 2011, 2012, 2013, 2014 The Regents of the University of + Copyright (c) 2011 - 2016 The Regents of the University of California (Regents). All Rights Reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: @@ -29,10 +29,6 @@ */ package Chisel -import Node._ -import Reg._ -import ChiselError._ -import scala.reflect._ class GetWidthException(s: String) extends Exception(s) @@ -42,7 +38,7 @@ object Reg { if (Driver.isInGetWidth) { throw new GetWidthException("getWidth was called on a Register or on an object connected in some way to a Register that has a statically uninferrable width") } else { - maxWidth(m) + Node.maxWidth(m) } // Rule: If no width is specified, use max width. Otherwise, use the specified width. @@ -60,7 +56,7 @@ object Reg { if (! w.isKnown) { regMaxWidth _ ; } else { - fixWidth(w.needWidth()) // TODO 0WW + Node.fixWidth(w.needWidth()) // TODO 0WW } /** Rule: if r is using an inferred width, then don't enforce a width. If it is using a user inferred @@ -69,91 +65,79 @@ object Reg { XXX Can't specify return type. There is a conflict. It is either (Node) => (Int) or Int depending which execution path you believe. */ - def regWidth(r: => Node) = { - val rLit = r.litOf - if (rLit != null && rLit.hasInferredWidth) { - regMaxWidth _ - } else { - fixWidth(r.getWidth) - } + def regWidth(r: => Node) = r.litOpt match { + case Some(rl) if rl.hasInferredWidth => regMaxWidth _ + case _ => Node.fixWidth(r.getWidth) } def validateGen[T <: Data](gen: => T) { - for ((n, i) <- gen.flatten) - if (!i.inputs.isEmpty) - throwException("Invalid Type Specifier for Reg") + for ((n, i) <- gen.flatten if !i.inputs.isEmpty) + throwException("Invalid Type Specifier for Reg: element \"%s\" has %d inputs (possibly an initial value?)".format(n, i.inputs.size)) } /** *type_out* defines the data type of the register when it is read. *update* and *reset* define the update and reset values respectively. */ - def apply[T <: Data](outType: T = null, next: T = null, init: T = null, - clock: Clock = null): T = { - var mType = outType - if(mType == null) { - mType = next - } - if(mType == null) { - mType = init - } - if(mType == null) { - throw new Exception("cannot infer type of Reg.") - } - - val gen = mType.clone + def apply[T <: Data](outType: T = null, next: T = null, init: T = null, clock: Clock = null): T = + apply(Option(outType), Option(next), Option(init), Option(clock)) + + def apply[T <: Data](outType: Option[T], next: Option[T], init: Option[T], clock: Option[Clock]): T = { + val gen = (outType match {case Some(t) => t case None => + next match { case Some(t) => t case None => + init match { case Some(t) => t case None => + throwException("cannot infer type of Reg.")}}}).cloneType validateGen(gen) // asOutput flip the direction and returns this. val res = gen.asOutput - - if (init != null) for (((res_n, res_i), (rval_n, rval_i)) <- res.flatten zip init.flatten) { - if (rval_i.getWidth < 0) ChiselError.error("Negative width to wire " + res_i) - res_i.comp = new RegReset - res_i.comp.init("", regWidth(rval_i), res_i.comp, rval_i) - res_i.inputs += res_i.comp - } else for ((res_n, res_i) <- res.flatten) { - res_i.comp = new Reg - val w = res_i.getWidthW() - res_i.comp.init("", regWidth(w), res_i.comp) - res_i.inputs += res_i.comp + init match { + case None => for (r <- res.flatten.unzip._2) { + val p = new Reg + val w = r.getWidthW() + p.init("", regWidth(w), p) + r.inputs += p + r.comp = Some(p) + } + case Some(p) => for ((r, i) <- res.flatten.unzip._2 zip p.flatten.unzip._2) { + if (i.getWidth < 0) ChiselError.error("Negative width to wire " + res) + val p = new RegReset + p.init("", regWidth(i), p, i) + r.inputs += p + r.comp = Some(p) + } } - - if (next != null) for (((res_n, res_i), (next_n, next_i)) <- res.flatten zip next.flatten) { - res_i.comp.doProcAssign(next_i, Bool(true)) + next match { + case None => + case Some(p) => for ((r, n) <- res.flatten.unzip._2 zip p.flatten.unzip._2) { + r.comp match { + case None => // Todo: Error! + case Some(p) => p doProcAssign (n, Bool(true)) + } + } } - res.setIsTypeNode - // set clock - for ((name, sig) <- res.flatten) { - if (sig.comp != null) - sig.comp.clock = clock - else - sig.clock = clock - } - + res.flatten.unzip._2 foreach (sig => sig.comp match { + case None => sig.clock = clock + case Some(p) => p.clock = clock + }) res } /* Without this method, the scala compiler is not happy when we declare registers as Reg(signal). */ - def apply[T <: Data](outType: T): T = Reg[T](outType, null.asInstanceOf[T], null.asInstanceOf[T]) + def apply[T <: Data](outType: T): T = Reg[T](Some(outType), None, None, None) } object RegNext { - - def apply[T <: Data](next: T): T = Reg[T](next, next, null.asInstanceOf[T]) - - def apply[T <: Data](next: T, init: T): T = Reg[T](next, next, init) - + def apply[T <: Data](next: T): T = Reg[T](Some(next), Some(next), None, None) + def apply[T <: Data](next: T, init: T): T = Reg[T](Some(next), Some(next), Some(init), None) } object RegInit { - - def apply[T <: Data](init: T): T = Reg[T](init, null.asInstanceOf[T], init) - + def apply[T <: Data](init: T): T = Reg[T](Some(init), None, Some(init), None) } class RegReset extends Reg { @@ -171,8 +155,16 @@ class Reg extends Delay with proc { override def usesInClockHi(n: Node) = n eq next + override def doProcAssign(src: Node, cond: Bool) { + if (procAssigned || isEnable) inputs(0) = Multiplex(cond, src, inputs(0)) + else super.doProcAssign(src, cond) + } + // these are used to infer read enables on Mems - protected[Chisel] def isEnable: Boolean = next.isInstanceOf[Mux] && (next.inputs(2) eq this) - protected[Chisel] def enableSignal: Node = if (isEnable) next.inputs(0) else Bool(true) - protected[Chisel] def updateValue: Node = if (isEnable) next.inputs(1) else next + // also useful for custom transforms + def isEnable: Boolean = next.isInstanceOf[Mux] && (next.inputs(2).getNode eq this) + def enableSignal: Node = if (isEnable) next.inputs(0) else Bool(true) + def updateValue: Node = if (isEnable) next.inputs(1) else next + // Chisel3 - this node contains data - used for verifying Wire() wrapping + override def isTypeOnly = false } diff --git a/src/main/scala/SCWrapper.scala b/src/main/scala/SCWrapper.scala index 32f42e06..c5e69ff4 100644 --- a/src/main/scala/SCWrapper.scala +++ b/src/main/scala/SCWrapper.scala @@ -1,5 +1,5 @@ /* - Copyright (c) 2011, 2012, 2013, 2014 The Regents of the University of + Copyright (c) 2011 - 2016 The Regents of the University of California (Regents). All Rights Reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: @@ -30,12 +30,8 @@ package Chisel -import scala.collection.mutable.ArrayBuffer -import scala.collection.mutable.HashMap -import scala.io.Source._ -//import java.util._ +import scala.collection.mutable.{ArrayBuffer, HashMap} import java.io._ -import java.lang.String.format object SCWrapper { type ReplacementMap = HashMap[String, String] @@ -169,7 +165,15 @@ object SCWrapper { init += "%s %s;\n ".format(ctype, data) init += "int %s = 0;\n ".format(filled) fill += "if(!%s){%s = %s->nb_read(%s);}\n "format(filled, filled, in, data) - fill += "c->%s = %s;\n "format(in_data, data) + // Is this a structured data-type? + if (ctype == in_data) { + // Unpack and distribute the inputs. + for((name, bits) <- c.structs(ctype).fields) { + fill += "c->%s = %s.%s;\n "format(name, data, name) + } + } else { + fill += "c->%s = %s;\n "format(in_data, data) + } fill += "c->%s = LIT<1>(%s);\n "format(valid, filled) check += "if(c->%s.values[0]) %s = 0;\n "format(ready, filled) } @@ -190,17 +194,37 @@ object SCWrapper { var check = "" var valid_output = ""; for(i <- 0 until fifos.size) { + val ctype = fifos(i).ctype val valid = fifos(i).valid val data = fifos(i).data val ready = fifos(i).ready val out = fifos(i).name check += "c->%s = LIT<1>(%s->num_free() > 0);\n "format(ready, out) - valid_output += "if(c->%s.values[0]) %s->nb_write(c->%s);\n "format(valid, out, data) + // Is this a structured data-type? + if (ctype == data) { + // Pack and distribute the inputs. + val indent = " " + valid_output += "if(c->%s.values[0]) {\n%s"format(valid, indent) + valid_output += " %s dato;\n%s".format(ctype, indent) + for((name, bits) <- c.structs(ctype).fields) { + valid_output += " dato.%s = c->%s;\n%s"format(name, name, indent) + } + valid_output += " %s->nb_write(dato);\n%s}\n "format(out, indent) + } else { + valid_output += "if(c->%s.values[0]) %s->nb_write(c->%s);\n "format(valid, out, data) + } } replacements += (("check_output", check)) replacements += (("valid_output", valid_output)) } + // If we have structured FIFO elements, we need to generate the struct definitions + // and the ostream "<<" definition to keep SystemC happy. + val ostream_lsh = ArrayBuffer[String]() + for((name, struct) <- c.structs) { + ostream_lsh += struct.toString + "inline ostream& operator << (ostream& os, const %s& arg){ return os; }\n".format(name) + } + replacements += (("ostream_lsh", ostream_lsh.mkString("\n"))) replacements } @@ -307,6 +331,7 @@ class ComponentDef(a_type: String, a_name: String) { val ctype: String = a_type val name: String = a_name val entries = ArrayBuffer[CEntry]() + val structs = scala.collection.mutable.LinkedHashMap[String, CStruct]() override def toString(): String = { var accum: String = ":[" @@ -317,3 +342,12 @@ class ComponentDef(a_type: String, a_name: String) { "Component " + ctype + " " + name + accum } } + +case class CStruct(val name: String, val fields: Array[(String, Bits)]) { + override def toString(): String = { + "struct " + name + + " {\n" + + fields.map { case (name, bits) => " dat_t<" + bits.width + "> " + name + ";" }.mkString("\n") + + "\n};\n" + } +} diff --git a/src/main/scala/SInt.scala b/src/main/scala/SInt.scala index 020177d8..b1f53295 100644 --- a/src/main/scala/SInt.scala +++ b/src/main/scala/SInt.scala @@ -1,5 +1,5 @@ /* - Copyright (c) 2011, 2012, 2013, 2014 The Regents of the University of + Copyright (c) 2011 - 2016 The Regents of the University of California (Regents). All Rights Reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: @@ -29,25 +29,27 @@ */ package Chisel -import Node._ -import ChiselError._ object SInt { - def apply(x: Int): SInt = Lit(x){SInt()}; - def apply(x: Int, width: Int): SInt = Lit(x, width){SInt()}; - def apply(x: BigInt): SInt = Lit(x){SInt()}; - def apply(x: BigInt, width: Int): SInt = Lit(x, width){SInt()}; - - def apply(dir: IODirection = null, width: Int = -1): SInt = { - val res = new SInt(); + /** Create a SInt from an Int */ + def apply(x: Int): SInt = Lit(x){SInt()} + /** Create a SInt from an Int specifying the width */ + def apply(x: Int, width: Int): SInt = Lit(x, width){SInt()} + /** Create a SInt from an BigInt */ + def apply(x: BigInt): SInt = Lit(x){SInt()} + /** Create a SInt from an BigInt specifying the width */ + def apply(x: BigInt, width: Int): SInt = Lit(x, width){SInt()} + /** Create a SInt for I/O specifying the width */ + def apply(dir: IODirection = NODIR, width: Int = -1): SInt = { + val res = new SInt() res.create(dir, width) res } } class SInt extends Bits with Num[SInt] { - type T = SInt; + type T = SInt /** Factory method to create and assign a *SInt* type to a Node *n*. */ @@ -59,57 +61,67 @@ class SInt extends Bits with Num[SInt] { res } + /** Set the value of this SInt to a value */ override def fromInt(x: Int): this.type = { SInt(x).asInstanceOf[this.type] } override def matchWidth(w: Width): Node = { - val this_width = this.getWidthW() + val this_width = this.widthW if (w.isKnown && this_width.isKnown) { val my_width = this_width.needWidth() val match_width = w.needWidth() if (match_width > my_width) { if (my_width == 1) { - val res = NodeFill(match_width, this); res.infer + val res = NodeFill(match_width, this) ; res.infer res } else { - val topBit = NodeExtract(this, my_width-1); topBit.infer - val fill = NodeFill(match_width - my_width, topBit); fill.infer - val res = Concatenate(fill, this); res.infer + val topBit = NodeExtract(this, my_width-1) ; topBit.infer + val fill = NodeFill(match_width - my_width, topBit) ; fill.infer + val res = Concatenate(fill, this) ; res.infer res } } else if (match_width < my_width) { - val res = NodeExtract(this, match_width-1,0); res.infer + val res = NodeExtract(this, match_width-1,0) ; res.infer res } else { this } } else { - ChiselError.error("SInt.matchWidth with unknown width: " + w + ", node " + this); + ChiselError.error("SInt.matchWidth with unknown width: " + w + ", node " + this) this } } /** casting from UInt followed by assignment. */ override protected def colonEquals(that: Bits): Unit = that match { - case u: UInt => this := u.zext + case u: UInt => + ChiselError.check("Chisel3 compatibility: Connections between UInt and SInt are illegal.", Version("3.0")) + this := u.zext case _ => super.colonEquals(that) } - def gen[T <: Bits](): T = SInt().asInstanceOf[T]; + def gen[T <: Bits](): T = SInt().asInstanceOf[T] // arithmetic operators def unary_-(): SInt = SInt(0) - this def unary_!(): Bool = this === SInt(0) - def >> (b: UInt): SInt = newBinaryOp(b, "s>>"); + def >> (b: UInt): SInt = newBinaryOp(b, "s>>") def ? (b: SInt): SInt = fromNode(Multiplex(this.toBool, b, null)) + def >> (i: Int): SInt = newBinaryOp(UInt(i), "s>>") // chisel3 + def << (i: Int): SInt = newBinaryOp(UInt(i), "<<") // chisel3 // order operators - def < (b: SInt): Bool = newLogicalOp(b, "s<"); + def < (b: SInt): Bool = newLogicalOp(b, "s<") def > (b: SInt): Bool = b < this - def <= (b: SInt): Bool = newLogicalOp(b, "s<="); + def <= (b: SInt): Bool = newLogicalOp(b, "s<=") def >= (b: SInt): Bool = b <= this - def != (b: UInt): Bool = this != b.zext + @deprecated("Use =/= rather than !=", "3") + def != (b: UInt): Bool = { + ChiselError.check("Chisel3 compatibility: != is deprecated, use =/= instead", Version("3.0")) + this =/= b.zext + } + def =/= (b: UInt): Bool = this =/= b.zext def > (b: UInt): Bool = this > b.zext def < (b: UInt): Bool = this < b.zext def >= (b: UInt): Bool = this >= b.zext @@ -117,21 +129,37 @@ class SInt extends Bits with Num[SInt] { override def ===[T <: Data](right: T): Bool = { right match { - case b: UInt => this === b.zext; + case b: UInt => this === b.zext case _ => super.===(right) } } //SInt to SInt arithmetic - def + (b: SInt): SInt = newBinaryOp(b, "+"); - def * (b: SInt): SInt = newBinaryOp(b, "s*s"); - def / (b: SInt): SInt = newBinaryOp(b, "s/s"); - def % (b: SInt): SInt = newBinaryOp(b, "s%s"); - def - (b: SInt): SInt = newBinaryOp(b, "-"); + def + (b: SInt): SInt = newBinaryOp(b, "+") + def * (b: SInt): SInt = newBinaryOp(b, "s*s") + def / (b: SInt): SInt = newBinaryOp(b, "s/s") + def % (b: SInt): SInt = newBinaryOp(b, "s%s") + def - (b: SInt): SInt = newBinaryOp(b, "-") + /** chisel3 add-wrap operator */ + def +% (b: SInt): SInt = newBinaryOp(b, "+") + /** chisel3 add (width + 1) operator */ + def +& (b: SInt): SInt = newBinaryOp(b, "+&") + /** chisel3 sub-wrap operator */ + def -% (b: SInt): SInt = newBinaryOp(b, "-") + /** chisel3 sub (width + 1) operator */ + def -& (b: SInt): SInt = newBinaryOp(b, "-&") //SInt to UInt arithmetic - def * (b: UInt): SInt = newBinaryOp(b.zext, "s*u") + def * (b: UInt): SInt = { + // We need to detect a zero-width operand early, due to the assumptions about "s*u" width manipulation in Op.c (see mulSUWidth()) + val opType = if (b.isZeroWidth) { + "s*s" + } else { + "s*u" + } + newBinaryOp(b.zext, opType) + } def + (b: UInt): SInt = this + b.zext def - (b: UInt): SInt = this - b.zext def / (b: UInt): SInt = this / b.zext diff --git a/src/main/scala/SysC.scala b/src/main/scala/SysC.scala index 8f0767e5..880da7bd 100644 --- a/src/main/scala/SysC.scala +++ b/src/main/scala/SysC.scala @@ -1,5 +1,5 @@ /* - Copyright (c) 2011, 2012, 2013, 2014 The Regents of the University of + Copyright (c) 2011 - 2016 The Regents of the University of California (Regents). All Rights Reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: @@ -29,20 +29,10 @@ */ package Chisel -import scala.collection.mutable.ArrayBuffer -import scala.math._ -import java.io.InputStream -import java.io.OutputStream -import java.io.PrintStream -import scala.sys.process._ -import sys.process.stringSeqToProcess -import Node._ -import Reg._ -import ChiselError._ -import Literal._ -import scala.collection.mutable.HashSet -import scala.collection.mutable.HashMap +/** If we have structured/aggregate types as top-level ports, we define suitable structures + * for encapsulating their components, in order to treat them as sc_fifo elements. + */ class SysCBackend extends CppBackend { override def elaborate(c: Module): Unit = { super.elaborate(c) @@ -50,33 +40,62 @@ class SysCBackend extends CppBackend { println(c.name) //Create component definition for System C - val top_bundle = c.io.asInstanceOf[Bundle] //Is this safe? - // No, but it will throw an exception that should explain the issue reasonably - val cdef = new ComponentDef(c.name + "_t", c.name) - for ((name, elt) <- top_bundle.elements) { - elt match { - case delt:DecoupledIO[_] => - delt.bits match { - case bits: Bits => { - val is_input = bits.dir == INPUT - val vtype = "dat_t<" + bits.width + ">" // direct use of width here? - val entry = new CEntry(name, is_input, vtype, bits.name, delt.ready.name, delt.valid.name) - cdef.entries += (entry) - } - case _ => - throw new RuntimeException("SystemC requires that all top-level wires are decoupled bits!") - } - case _ => - throw new RuntimeException("SystemC requires that all top-level wires are decoupled bits!") - } + val top_bundle = c.io.asInstanceOf[Bundle] //Is this safe? + // No, but it will throw an exception that should explain the issue reasonably + val cdef = new ComponentDef(c.name + "_t", c.name) + val badElements = scala.collection.mutable.HashMap[String, Data]() + for ((name, elt) <- top_bundle.elements) { + elt match { + case delt:DecoupledIO[_] => { + delt.bits match { + case bits: Bits => { + val is_input = bits.dir == INPUT + val vtype = "dat_t<" + bits.width + ">" // direct use of width here? + val entry = new CEntry(name, is_input, vtype, bits.name, delt.ready.name, delt.valid.name) + cdef.entries += (entry) + } + case aggregate: Aggregate => { + // Collect all the inputs and outputs. + val inputs = aggregate.flatten.filter(_._2.dir == INPUT) + if (inputs.length > 0) { + val aName = "cs_" + aggregate.name + "_i" + cdef.structs(aName)= new CStruct(aName, inputs) + val entry = new CEntry(name, true, aName, aName, delt.ready.name, delt.valid.name) + cdef.entries += (entry) + } + val outputs = aggregate.flatten.filter(_._2.dir == OUTPUT) + if (outputs.length > 0) { + val aName = "cs_" + aggregate.name + "_o" + cdef.structs(aName) = new CStruct(aName, outputs) + val entry = new CEntry(name, false, aName, aName, delt.ready.name, delt.valid.name) + cdef.entries += (entry) + } + } + case _ => badElements(name) = elt + } + } + case _ => badElements(name) = elt } + } - //Print out component definition + if (badElements.size > 0) { + val invalidIOMessage = "SystemC requires that all top-level wires are decoupled bits - <%s>" + for ((name, elt) <- badElements) { + // If we have a line number for the element, use it. + if (elt.line != null) { + ChiselError.error(invalidIOMessage.format(name), elt.line) + } else { + ChiselError.error(invalidIOMessage.format(name)) + } + } + } else { + + //Print out the component definition. println(cdef) - //Generate file + //Generate the file. val out_p = createOutputFile("SCWrapped" + c.name + ".cpp"); SCWrapper.genwrapper(cdef, out_p) - } + } + } } - diff --git a/src/main/scala/Tester.scala b/src/main/scala/Tester.scala index cb600c6e..3c0a6dc2 100644 --- a/src/main/scala/Tester.scala +++ b/src/main/scala/Tester.scala @@ -1,5 +1,5 @@ /* - Copyright (c) 2011, 2012, 2013, 2014 The Regents of the University of + Copyright (c) 2011 - 2016 The Regents of the University of California (Regents). All Rights Reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: @@ -29,405 +29,903 @@ */ package Chisel -import Chisel._ -import scala.math._ -import scala.collection.mutable.ArrayBuffer -import scala.collection.mutable.HashMap +import scala.collection.mutable.{ArrayBuffer, HashSet, HashMap, Stack, Queue => ScalaQueue} +import scala.collection.immutable.ListSet import scala.util.Random -import java.io.{File, IOException, InputStream, OutputStream, PrintStream} -import scala.sys.process._ -import scala.io.Source._ -import Literal._ +import java.nio.channels.FileChannel +import java.lang.Double.{longBitsToDouble, doubleToLongBits} +import java.lang.Float.{intBitsToFloat, floatToIntBits} +import scala.sys.process.{Process, ProcessLogger} +import scala.concurrent._ +import scala.concurrent.duration._ +import ExecutionContext.Implicits.global + +// Provides a template to define tester transactions +trait Tests { + def t: Long + def delta: Int + def rnd: Random + def setClocks(clocks: Iterable[(Clock, Int)]): Unit + def peek(data: Bits): BigInt + def peek(data: Aggregate): Array[BigInt] + def peek(data: Flo): Float + def peek(data: Dbl): Double + def peekAt[T <: Bits](data: Mem[T], off: Int): BigInt + def poke(data: Bits, x: Boolean): Unit + def poke(data: Bits, x: Int): Unit + def poke(data: Bits, x: Long): Unit + def poke(data: Bits, x: BigInt): Unit + def poke(data: Aggregate, x: Array[BigInt]): Unit + def poke(data: Flo, x: Float): Unit + def poke(data: Dbl, x: Double): Unit + def pokeAt[T <: Bits](data: Mem[T], value: BigInt, off: Int): Unit + def reset(n: Int = 1): Unit + def step(n: Int): Unit + def int(x: Boolean): BigInt + def int(x: Int): BigInt + def int(x: Long): BigInt + def int(x: Bits): BigInt + def expect (good: Boolean, msg: => String): Boolean + def expect (data: Bits, expected: BigInt): Boolean + def expect (data: Aggregate, expected: Array[BigInt]): Boolean + def expect (data: Bits, expected: Int): Boolean + def expect (data: Bits, expected: Long): Boolean + def expect (data: Bool, expected: Boolean): Boolean + def expect (data: Flo, expected: Float): Boolean + def expect (data: Dbl, expected: Double): Boolean + def newTestOutputString: String + def expect (data: Bits, expected: BigInt, msg: => String): Boolean + def expect (data: Bits, expected: Int, msg: => String): Boolean + def expect (data: Bits, expected: Long, msg: => String): Boolean + def expect (data: Bool, expected: Boolean, msg: => String): Boolean + def expect (data: Flo, expected: Float, msg: => String): Boolean + def expect (data: Dbl, expected: Double, msg: => String): Boolean + def printfs: Vector[String] + def run(s: String): Boolean +} -case class Poke(val node: Node, val index: Int, val value: BigInt); +case class TestApplicationException(exitVal: Int, lastMessage: String) extends RuntimeException(lastMessage) -class Snapshot(val t: Int) { - val pokes = new ArrayBuffer[Poke]() +object Tester { + private[Chisel] val processes = HashSet[Process]() + implicit def strToOption(s: String) = if (s.isEmpty) None else Option(s) + def close { + processes foreach (_.destroy) + processes.clear + } } -class ManualTester[+T <: Module] - (val c: T, val isT: Boolean = true) { - var testIn: InputStream = null - var testOut: OutputStream = null - var testErr: InputStream = null - val sb = new StringBuilder() - var delta = 0 - var t = 0 - var isTrace = isT - - /** - * Waits until the emulator streams are ready. This is a dirty hack related - * to the way Process works. TODO: FIXME. - */ - def waitForStreams() = { - var waited = 0 - while (testOut == null || testIn == null || testErr == null) { - Thread.sleep(100) - if (waited % 10 == 0 && waited > 30) { - println("waiting for emulator process treams to be valid ...") - } +/** This class is the super class for test cases + * @param c The module under test + * @param isTrace print the all I/O operations and tests to stdout, default true + * @param _base base for prints, default 16 (hex) + * @param testCmd command to run the emulator + * @param dumpFile vcd/vpd file name + * @example + * {{{ class myTest(c : TestModule) extends Tester(c) { ... } }}} + */ +class Tester[+T <: Module](c: T, isTrace: Boolean = true, _base: Int = 16, + testCmd: Option[String] = Driver.testCommand, + dumpFile: Option[String] = None) extends FileSystemUtilities { + // Define events + abstract class Event + case class StartEvent(seed: Long, cmd: String) extends Event + case class FinishEvent(t: Long, pass: Boolean, fail_t: Long) extends Event + case class MuteEvent() extends Event + case class UnmuteEvent() extends Event + case class ResetEvent(n: Int) extends Event + case class StepEvent(n: Int, t: Long) extends Event + case class PokeEvent(b: Bits, v: BigInt, good: Boolean = true) extends Event + case class PokeMemEvent[T <: Data](m: Mem[T], off: Int, v: BigInt) extends Event + case class PokeFloEvent(b: Flo, v: Float) extends Event + case class PokeDblEvent(b: Dbl, v: Double) extends Event + case class PeekEvent(b: Bits, v: Option[BigInt]) extends Event + case class PeekMemEvent[T <: Data](m: Mem[T], off: Int, v: BigInt) extends Event + case class PeekFloEvent(b: Flo, v: Float) extends Event + case class PeekDblEvent(b: Dbl, v: Double) extends Event + case class ExpectMsgEvent(good: Boolean, msg: String) extends Event + case class ExpectEvent(b: Bits, got: BigInt, expected: BigInt, msg: String) extends Event + case class ExpectFloEvent(b: Bits, got: Float, expected: Float, msg: String) extends Event + case class ExpectDblEvent(b: Dbl, got: Double, expected: Double, msg: String) extends Event + case class DumpEvent(msg: String) extends Event + case class NoIdEvent(path: String) extends Event + // Define observer + class Observer(base: Int = _base, file: java.io.PrintStream = System.out) { + private var lock = false + protected def convt(x: BigInt) = base match { + case 2 if x < 0 => s"-0b${(-x).toString(base)}" + case 16 if x < 0 => s"-0x${(-x).toString(base)}" + case 2 => s"0b${x.toString(base)}" + case 16 => s"0x${x.toString(base)}" + case _ => x.toString(base) + } + def locked = lock + def apply(event: Event): Unit = event match { + case StartEvent(seed, cmd) => + file.println(s"SEED ${seed}") + file.println(s"STARTING ${cmd}") + case FinishEvent(t, pass, fail_t) => + file.println(s"""RAN ${t} CYCLES ${if (pass) "PASSED" else s"FAILED FIRST AT CYCLE ${fail_t}"}""") + case MuteEvent() => lock = true + case UnmuteEvent() => lock = false + case StepEvent(n, t) if !locked => file.println(s"STEP ${n} -> ${t+n}") + case ResetEvent(n) if !locked => file.println(s"RESET ${n}") + case PokeEvent(b, v, good) if !locked => + val value = if (good) convt(v) else "NOT ALLOWED" + file.println(s" POKE ${dumpName(b)} <- ${value}") + case PokeMemEvent(m, off, v) if !locked => + file.println(s" POKE ${dumpName(m)}[${off}] <- ${convt(v)}") + case PokeFloEvent(b, v) if !locked => + file.println(s" POKE ${dumpName(b)} <- ${v}") + case PokeDblEvent(b, v) if !locked => + file.println(s" POKE ${dumpName(b)} <- ${v}") + case PeekEvent(b, None) if !locked => + file.println(s" PEEK ${dumpName(b)} -> No initial values") + case PeekEvent(b, Some(v)) if !locked => + file.println(s" PEEK ${dumpName(b)} <- ${convt(v)}") + case PeekMemEvent(m, off, v) if !locked => + file.println(s" PEEK ${dumpName(m)}[${off}] -> ${convt(v)}") + case PeekFloEvent(b, v) if !locked => + file.println(s" PEEK ${dumpName(b)} -> ${v}") + case PeekDblEvent(b, v) if !locked => + file.println(s" PEEK ${dumpName(b)} -> ${v}") + case ExpectMsgEvent(good, msg) if !locked => + file.println(s"""${msg} ${if (good) "PASS" else "FAIL"}""") + case ExpectEvent(b, got, exp, msg) if !locked => apply(new ExpectMsgEvent(got == exp, + s"${msg} EXPECT ${dumpName(b)} -> ${convt(got)} == ${convt(exp)}")) + case ExpectFloEvent(b, got, exp, msg) if !locked => apply(new ExpectMsgEvent(got == exp, + s"${msg} EXPECT ${dumpName(b)} -> ${got} == ${exp}")) + case ExpectDblEvent(b, got, exp, msg) if !locked => apply(new ExpectMsgEvent(got == exp, + s"${msg} EXPECT ${dumpName(b)} -> ${got} == ${exp}")) + case DumpEvent(msg) if !msg.isEmpty => + file.println(msg) + case NoIdEvent(path) => file.println(s"Can't find id for '${path}'") + case _ => // silent } } - - // TODO: MOVE TO SOMEWHERE COMMON TO BACKEND - def ensureDir(dir: String): String = { - val d = dir + (if (dir == "" || dir(dir.length-1) == '/') "" else "/") - new File(d).mkdirs() - d + class BasicObserver extends Observer // defulat: prints hex to the screen + private val observers = ArrayBuffer[Observer]() + def addObserver(o: Observer) { observers += o } + def addEvent(e: Event) { observers foreach (_(e)) } + if (isTrace) addObserver(new BasicObserver) + + implicit def longToInt(x: Long) = x.toInt + def incTime(n: Int) { _t += n } + def t = _t + var _t = 0L // simulation time + var delta = 0 + private val _pokeMap = HashMap[Bits, BigInt]() + private val _peekMap = HashMap[Bits, BigInt]() + private val _signalMap = HashMap[String, Int]() + private val _chunks = HashMap[String, Int]() + private val _clocks = Driver.clocks map (clk => clk -> clk.period.round.toInt) + private val _clockLens = HashMap(_clocks:_*) + private val _clockCnts = HashMap(_clocks:_*) + val (_inputs: ListSet[Bits], _outputs: ListSet[Bits]) = ListSet(c.wires.unzip._2: _*) partition (_.dir == INPUT) + private var isStale = false + // Return any accumulated module printf output since the last call. + private var _lastLogIndex = 0 + def newTestOutputString: String = { + val result = _logs.slice(_lastLogIndex, _logs.length) mkString("\n") + _lastLogIndex = _logs.length + result } - def createOutputFile(name: String): java.io.FileWriter = { - val baseDir = ensureDir(Driver.targetDir) - new java.io.FileWriter(baseDir + name) + private val _logs = new ArrayBuffer[String]() + def printfs = _logs.toVector + + def throwExceptionIfDead(exitValue: Future[Int]) { + if (exitValue.isCompleted) { + val exitCode = Await.result(exitValue, Duration(-1, SECONDS)) + // We assume the error string is the last log entry. + val errorString = if (_logs.size > 0) { + _logs.last + } else { + "test application exit" + } + " - exit code %d".format(exitCode) + addEvent(new DumpEvent(newTestOutputString)) + throw new TestApplicationException(exitCode, errorString) + } } - def puts(str: String) = { - while (testOut == null) { Thread.sleep(100) } - for (e <- str) testOut.write(e); + // A busy-wait loop that monitors exitValue so we don't loop forever if the test application exits for some reason. + private def mwhile(block: => Boolean)(loop: => Unit) { + while (!exitValue.isCompleted && block) { + loop + } + // If the test application died, throw a run-time error. + throwExceptionIfDead(exitValue) } - - /** - * Sends a command to the emulator and returns the reply. - * The standard protocol treats a single line as a command, which always - * returns a single line of reply. - */ - def emulatorCmd(str: String): String = { - // validate cmd - if (str contains "\n") { - System.err.print(s"emulatorCmd($str): command should not contain newline") - return "error" - } - - waitForStreams() - - // send command to emulator - for (e <- str) testOut.write(e); - testOut.write('\n'); - testOut.flush() - - // read output from emulator - var c = testIn.read - sb.clear() - while (c != '\n' && c != -1) { - if (c == 0) { - Thread.sleep(100) - } - sb += c.toChar - // Look for a "PRINT" command. - if (sb.length == 6 && sb.startsWith("PRINT ")) { - do { - c = testIn.read - sb += c.toChar - } while (c != ' ') - // Get the PRINT character count. - val printCommand = """^PRINT (\d+) """.r - val printCommand(nChars) = sb.toString - sb.clear() - for (i <- 0 until nChars.toInt) { - c = testIn.read - sb += c.toChar - } - System.out.print(sb.toString()) - sb.clear() - } - c = testIn.read + private object SIM_CMD extends Enumeration { + val RESET, STEP, UPDATE, POKE, PEEK, FORCE, GETID, GETCHK, SETCLK, FIN = Value } + implicit def cmdToId(cmd: SIM_CMD.Value) = cmd.id + + private class Channel(name: String) { + private lazy val file = new java.io.RandomAccessFile(name, "rw") + private lazy val channel = file.getChannel + @volatile private lazy val buffer = { + /* We have seen runs where buffer.put(0,0) fails with: +[info] java.lang.IndexOutOfBoundsException: +[info] at java.nio.Buffer.checkIndex(Buffer.java:532) +[info] at java.nio.DirectByteBuffer.put(DirectByteBuffer.java:300) +[info] at Chisel.Tester$Channel.release(Tester.scala:148) +[info] at Chisel.Tester.start(Tester.scala:717) +[info] at Chisel.Tester.(Tester.scala:743) +[info] at ArbiterSuite$ArbiterTests$8.(ArbiterTest.scala:396) +[info] at ArbiterSuite$$anonfun$testStableRRArbiter$1.apply(ArbiterTest.scala:440) +[info] at ArbiterSuite$$anonfun$testStableRRArbiter$1.apply(ArbiterTest.scala:440) +[info] at Chisel.Driver$.apply(Driver.scala:65) +[info] at Chisel.chiselMain$.apply(hcl.scala:63) +[info] ... + */ + val size = channel.size + assert(size > 16, "channel.size is bogus: %d".format(size)) + channel map (FileChannel.MapMode.READ_WRITE, 0, size) } - - // drain errors - try { - while(testErr.available() > 0) { - System.err.print(Character.toChars(testErr.read())) - } - } catch { - case e : IOException => testErr = null; println("ERR EXCEPTION") + implicit def intToByte(i: Int) = i.toByte + val channel_data_offset_64bw = 4 // Offset from start of channel buffer to actual user data in 64bit words. + def aquire { + buffer put (0, 1) + buffer put (2, 0) + while((buffer get 1) == 1 && (buffer get 2) == 0) {} } - - if (sb == "error") { - System.err.print(s"FAILED: emulatorCmd($str): returned error") - ok = false + def release { buffer put (0, 0) } + def ready = (buffer get 3) == 0 + def valid = (buffer get 3) == 1 + def produce { buffer put (3, 1) } + def consume { buffer put (3, 0) } + def update(idx: Int, data: Long) { buffer putLong (8 * idx + channel_data_offset_64bw, data) } + def update(base: Int, data: String) { + data.zipWithIndex foreach {case (c, i) => buffer put (base + i + channel_data_offset_64bw, c) } + buffer put (base + data.size + channel_data_offset_64bw, 0) } - return sb.toString + def apply(idx: Int): Long = buffer getLong (8 * idx + channel_data_offset_64bw) + def close { file.close } + buffer order java.nio.ByteOrder.nativeOrder + new java.io.File(name).delete } - def setClocks(clocks: HashMap[Clock, Int]) { - var cmd = "set_clocks" - for (clock <- Driver.clocks) { - if (clock.srcClock == null) { - val s = BigInt(clocks(clock)).toString(16) - cmd = cmd + " " + s - } - } - emulatorCmd(cmd) - // TODO: check for errors in return + def dumpName(data: Node): String = Driver.backend match { + case _: FloBackend => data.getNode.name + case _ => data.getNode.chiselName } - def dumpName(data: Node): String = { - if (Driver.backend.isInstanceOf[FloBackend]) { - data.name - } else - data.chiselName + def setClock(clk: Clock, len: Int) { + _clockLens(clk) = len + _clockCnts(clk) = len + mwhile(!sendCmd(SIM_CMD.SETCLK)) { } + mwhile(!sendCmd(clk.name)) { } + mwhile(!sendValue(len, 1)) { } } - def peekBits(data: Node, off: Int = -1): BigInt = { - if (dumpName(data) == "") { - println("Unable to peek data " + data) - -1 - } else { - var cmd = "" - if (off != -1) { - cmd = "mem_peek " + dumpName(data) + " " + off; - } else { - cmd = "wire_peek " + dumpName(data); - } - val s = emulatorCmd(cmd) - val rv = toLitVal(s) - if (isTrace) println(" PEEK " + dumpName(data) + " " + (if (off >= 0) (off + " ") else "") + "-> " + s) - rv - } + def setClocks(clocks: Iterable[(Clock, Int)]) { + clocks foreach { case (clk, len) => setClock(clk, len) } } def signed_fix(dtype: Bits, rv: BigInt): BigInt = { val w = dtype.needWidth() dtype match { /* Any "signed" node */ - case _: SInt | _ : Flo | _: Dbl => (if(rv >= (BigInt(1) << w - 1)) (rv - (BigInt(1) << w)) else rv) + case _: SInt | _ : Flo | _: Dbl | _: Fixed => (if(rv >= (BigInt(1) << w - 1)) (rv - (BigInt(1) << w)) else rv) /* anything else (i.e., UInt) */ case _ => (rv) } } + private def peek(id: Int, chunk: Int) = { + mwhile(!sendCmd(SIM_CMD.PEEK)) { } + mwhile(!sendCmd(id)) { } + if (exitValue.isCompleted) { + BigInt(0) + } else { + (for { + _ <- Stream.from(1) + data = recvValue(chunk) + if data != None + } yield data.get).head + } + } + /** Peek at the value of a node based on the path + */ + def peekPath(path: String): BigInt = { + val id = _signalMap getOrElseUpdate (path, getId(path)) + if (id == -1) { + addEvent(new NoIdEvent(path)) + id + } else { + peek(id, _chunks getOrElseUpdate (path, getChunk(id))) + } + } + /** Peek at the value of a node + * @param node Node to peek at + * @param off The index or offset to inspect */ + def peekNode(node: Node, off: Option[Int] = None) = { + val i = off match { case Some(p) => s"[${p}]" case None => "" } + peekPath(s"${dumpName(node)}${i}") + } + /** Peek at the value of some memory at an index + * @param data Memory to inspect + * @param off Offset in memory to look at */ def peekAt[T <: Bits](data: Mem[T], off: Int): BigInt = { - // signed_fix(data(1), peekBits(data, off)) - peekBits(data, off) + val value = peekNode(data, Some(off)) + addEvent(new PeekMemEvent(data, off, value)) + value } - + /** Peek at the value of some bits + * @return a BigInt representation of the bits */ def peek(data: Bits): BigInt = { - signed_fix(data, peekBits(data.getNode)) + if (isStale) update + val value = if (data.isLit) Some(data.litValue()) + else if (data.isTopLevelIO && data.dir == INPUT) _pokeMap get data + else Some(signed_fix(data, _peekMap getOrElse (data, peekNode(data.getNode)))) + addEvent(new PeekEvent(data, value)) + value getOrElse BigInt(rnd.nextInt) + } + /** Peek at Aggregate data + * @return an Array of BigInts representing the data */ + def peek(data: Aggregate): Array[BigInt] = { + data.flatten map (x => peek(x._2)) + } + /** Interpret data as a single precision float */ + def peek(data: Flo): Float = { + addEvent(new MuteEvent()) + val value = intBitsToFloat(peek(data.asInstanceOf[Bits]).toInt) + addEvent(new UnmuteEvent()) + addEvent(new PeekFloEvent(data, value)) + value + } + /** Interpret the data as a double precision float */ + def peek(data: Dbl): Double = { + addEvent(new MuteEvent()) + val value = longBitsToDouble(peek(data.asInstanceOf[Bits]).toLong) + addEvent(new UnmuteEvent()) + addEvent(new PeekDblEvent(data, value)) + value } - def peek(data: Aggregate /*, off: Int = -1 */): Array[BigInt] = { - data.flatten.map(x => x._2).map(peek(_)) + private def poke(id: Int, chunk: Int, v: BigInt, force: Boolean = false) { + val cmd = if (!force) SIM_CMD.POKE else SIM_CMD.FORCE + mwhile(!sendCmd(cmd)) { } + mwhile(!sendCmd(id)) { } + mwhile(!sendValue(v, chunk)) { } + } + /** set the value of a node with its path + * @param path The unique path of the node to set + * @param v The BigInt representing the bits to set + * @example {{{ poke(path, BigInt(63) << 60, 2) }}} + */ + def pokePath(path: String, v: BigInt, force: Boolean = false) { + val id = _signalMap getOrElseUpdate (path, getId(path)) + if (id == -1) { + addEvent(new NoIdEvent(path)) + } else { + poke(id, _chunks getOrElseUpdate (path, getChunk(id)), v, force) + } + } + /** set the value of a node + * @param node The node to set + * @param v The BigInt representing the bits to set + * @param off The offset or index + */ + def pokeNode(node: Node, v: BigInt, off: Option[Int] = None, force: Boolean = false) { + val i = off match { case Some(p) => s"[${p}]" case None => "" } + pokePath(s"${dumpName(node)}${i}", v, force) + } + /** set the value of some memory + * @param data The memory to write to + * @param value The BigInt representing the bits to set + * @param off The offset representing the index to write to memory + */ + def pokeAt[T <: Bits](data: Mem[T], value: BigInt, off: Int): Unit = { + addEvent(new PokeMemEvent(data, off, value)) + pokeNode(data, value, Some(off)) + } + /** Set the value of some 'data' Node */ + def poke(data: Bits, x: Boolean) { this.poke(data, int(x)) } + /** Set the value of some 'data' Node */ + def poke(data: Bits, x: Int) { this.poke(data, int(x)) } + /** Set the value of some 'data' Node */ + def poke(data: Bits, x: Long) { this.poke(data, int(x)) } + /** Set the value of some 'data' Node */ + def poke(data: Bits, x: BigInt) { + val value = if (x >= 0) x else { + val cnt = (data.needWidth() - 1) >> 6 + ((0 to cnt) foldLeft BigInt(0))((res, i) => res | (int((x >> (64 * i)).toLong) << (64 * i))) + } + data.getNode match { + case _: Delay => + addEvent(new PokeEvent(data, value)) + pokeNode(data.getNode, value) + isStale = true + case _ if data.isTopLevelIO && data.dir == INPUT => + addEvent(new PokeEvent(data, value)) + _pokeMap(data) = value + isStale = true + case _ => + addEvent(new PokeEvent(data, value, false)) + } + } + /** Set the value of Aggregate data */ + def poke(data: Aggregate, x: Array[BigInt]): Unit = { + val kv = (data.flatten.map(x => x._2), x.reverse).zipped + for ((x, y) <- kv) poke(x, y) + } + /** Set the value of a hardware single precision floating point representation */ + def poke(data: Flo, x: Float): Unit = { + addEvent(new PokeFloEvent(data, x)) + addEvent(new MuteEvent()) + poke(data.asInstanceOf[Bits], BigInt(floatToIntBits(x))) + addEvent(new UnmuteEvent()) + } + /** Set the value of a hardware double precision floating point representation */ + def poke(data: Dbl, x: Double): Unit = { + addEvent(new PokeDblEvent(data, x)) + addEvent(new MuteEvent()) + poke(data.asInstanceOf[Bits], BigInt(doubleToLongBits(x))) + addEvent(new UnmuteEvent()) } - def reset(n: Int = 1) = { - emulatorCmd("reset " + n) - // TODO: check for errors in return - if (isTrace) println("RESET " + n) + private def sendCmd(data: Int) = { + cmdChannel.aquire + val ready = cmdChannel.ready + if (ready) { + cmdChannel(0) = data + cmdChannel.produce + } + cmdChannel.release + ready } - def doPokeBits(data: Node, x: BigInt, off: Int = -1): Unit = { - if (dumpName(data) == "") { - println("Unable to poke data " + data) - } else { + private def sendCmd(data: String) = { + cmdChannel.aquire + val ready = cmdChannel.ready + if (ready) { + cmdChannel(0) = data + cmdChannel.produce + } + cmdChannel.release + ready + } - var cmd = "" - if (off != -1) { - cmd = "mem_poke " + dumpName(data) + " " + off; - } else { - cmd = "wire_poke " + dumpName(data); - } - // Don't prefix negative numbers with "0x" - val radixPrefix = if (x < 0) " -0x" else " 0x" - val xval = radixPrefix + x.abs.toString(16) - cmd = cmd + xval - if (isTrace) { - println(" POKE " + dumpName(data) + " " + (if (off >= 0) (off + " ") else "") + "<- " + xval) + private def recvResp = { + outChannel.aquire + val valid = outChannel.valid + val resp = if (!valid) None else { + outChannel.consume + Some(outChannel(0).toInt) + } + outChannel.release + resp + } + + private def sendValue(value: BigInt, chunk: Int) = { + inChannel.aquire + val ready = inChannel.ready + if (ready) { + (0 until chunk) foreach (i => inChannel(i) = (value >> (64*i)).toLong) + inChannel.produce + } + inChannel.release + ready + } + + private def recvValue(chunk: Int) = { + outChannel.aquire + val valid = outChannel.valid + val value = if (!valid) None else { + outChannel.consume + Some(((0 until chunk) foldLeft BigInt(0))( + (res, i) => res | (int(outChannel(i)) << (64*i)))) + } + outChannel.release + value + } + + private def sendInputs = { + inChannel.aquire + val ready = inChannel.ready + if (ready) { + (_inputs.toList foldLeft 0){case (off, in) => + val chunk = _chunks(dumpName(in)) + val value = _pokeMap getOrElse (in, BigInt(0)) + (0 until chunk) foreach (i => inChannel(off + i) = (value >> (64 * i)).toLong) + off + chunk } - val rtn = emulatorCmd(cmd) - if (rtn != "ok") { - System.err.print(s"FAILED: poke(${dumpName(data)}) returned false") - ok = false + inChannel.produce + } + inChannel.release + ready + } + + private def recvOutputs = { + _peekMap.clear + outChannel.aquire + val valid = outChannel.valid + if (valid) { + (_outputs.toList foldLeft 0){case (off, out) => + val chunk = _chunks(dumpName(out)) + _peekMap(out) = ((0 until chunk) foldLeft BigInt(0))( + (res, i) => res | (int(outChannel(off + i)) << (64 * i))) + off + chunk } + outChannel.consume } + outChannel.release + valid } - def pokeBits(data: Node, x: BigInt, off: Int = -1): Unit = { - doPokeBits(data, x, off) + /** Send reset to the hardware + * @param n number of cycles to hold reset for, default 1 */ + def reset(n: Int = 1) { + addEvent(new ResetEvent(n)) + for (i <- 0 until n) { + mwhile(!sendCmd(SIM_CMD.RESET)) { } + mwhile(!recvOutputs) { } + } } - def pokeAt[T <: Bits](data: Mem[T], x: BigInt, off: Int): Unit = { - pokeBits(data, x, off) + protected def update { + mwhile(!sendCmd(SIM_CMD.UPDATE)) { } + mwhile(!sendInputs) { } + mwhile(!recvOutputs) { } + isStale = false } - def poke(data: Bits, x: BigInt): Unit = { - pokeBits(data.getNode, x) + private def calcDelta = { + val min = (_clockCnts.values foldLeft Int.MaxValue)(math.min(_, _)) + _clockCnts.keys foreach (_clockCnts(_) -= min) + (_clockCnts filter (_._2 == 0)).keys foreach (k => _clockCnts(k) = _clockLens(k)) + min } - def poke(data: Aggregate, x: Array[BigInt]): Unit = { - val kv = (data.flatten.map(x => x._2), x.reverse).zipped; - for ((x, y) <- kv) - poke(x, y) + protected def takeStep { + mwhile(!sendCmd(SIM_CMD.STEP)) { } + mwhile(!sendInputs) { } + delta += calcDelta + mwhile(!recvOutputs) { } + // dumpLogs + observers map (_(new DumpEvent(newTestOutputString))) + isStale = false } - def step(n: Int) = { - val target = t + n - val s = emulatorCmd("step " + n) - delta += s.toInt - if (isTrace) println("STEP " + n + " -> " + target) - t += n + protected def getId(path: String) = { + mwhile(!sendCmd(SIM_CMD.GETID)) { } + mwhile(!sendCmd(path)) { } + if (exitValue.isCompleted) { + 0 + } else { + (for { + _ <- Stream.from(1) + data = recvResp + if data != None + } yield data.get).head + } } - def int(x: Boolean): BigInt = if (x) 1 else 0 - def int(x: Int): BigInt = x - def int(x: Bits): BigInt = x.litValue() + protected def getChunk(id: Int) = { + mwhile(!sendCmd(SIM_CMD.GETCHK)) { } + mwhile(!sendCmd(id)) { } + if (exitValue.isCompleted){ + 0 + } else { + (for { + _ <- Stream.from(1) + data = recvResp + if data != None + } yield data.get).head + } + } - var ok = true; - var failureTime = -1 + /** Step time by the smallest amount to the next rising clock edge + * @note this is defined based on the period of the clock + * See [[Chisel.Clock$ Clock]] + */ + def step(n: Int) { + addEvent(new StepEvent(n, t)) + (0 until n) foreach (_ => takeStep) + incTime(n) + } - def expect (good: Boolean, msg: String): Boolean = { - if (isTrace) - println(msg + " " + (if (good) "PASS" else "FAIL")) - if (!good) { ok = false; if (failureTime == -1) failureTime = t; } + /** Convert a Boolean to BigInt */ + def int(x: Boolean): BigInt = if (x) 1 else 0 + /** Convert an Int to BigInt */ + def int(x: Int): BigInt = (BigInt(x >>> 1) << 1) | x & 1 + /** Convert a Long to BigInt */ + def int(x: Long): BigInt = (BigInt(x >>> 1) << 1) | x & 1 + /** Convert Bits to BigInt */ + def int(x: Bits): BigInt = x.litValue() + + /** Indicate a failure has occurred. */ + private var failureTime = -1L + private var ok = true + def fail = if (ok) { + failureTime = t + ok = false + } + + /** Expect a value to be true printing a message if it passes or fails + * @param good If the test passed or not + * @param msg The message to print out + */ + def expect (good: Boolean, msg: => String): Boolean = { + addEvent(new ExpectMsgEvent(good, msg)) + if (!good) fail good } - def expect (data: Bits, expected: BigInt): Boolean = { + /** Expect the value of data to have the same bits as a BigInt */ + def expect (data: Bits, expected: BigInt, msg: => String): Boolean = { + addEvent(new MuteEvent()) val mask = (BigInt(1) << data.needWidth) - 1 - val got = peek(data) - - expect((got & mask) == (expected & mask), - "EXPECT " + dumpName(data) + " <- " + got + " == " + expected) + val got = peek(data) & mask + val exp = expected & mask + val good = got == exp + addEvent(new UnmuteEvent()) + addEvent(new ExpectEvent(data, got, exp, msg)) + if (!good) fail + good + } + def expect (data: Bits, expected: BigInt): Boolean = { + expect(data, expected, "") } + /** Expect the value of Aggregate data to be have the values as passed in with the array */ def expect (data: Aggregate, expected: Array[BigInt]): Boolean = { - val kv = (data.flatten.map(x => x._2), expected.reverse).zipped; - var allGood = true - for ((d, e) <- kv) - allGood = expect(d, e) && allGood - allGood + val kv = (data.flatten.map(x => x._2), expected.reverse).zipped + kv forall {case (d, e) => expect(d, e)} } - /* We need the following so scala doesn't use our "tolerant" Float version of expect. - */ + /** Expect the value of 'data' to be 'expected' + * @return the test passed */ + def expect (data: Bits, expected: Int, msg: => String): Boolean = { + expect(data, int(expected), msg) + } def expect (data: Bits, expected: Int): Boolean = { - expect(data, BigInt(expected)) + expect(data, expected, "") + } + + /** Expect the value of 'data' to be 'expected' + * @return the test passed */ + def expect (data: Bits, expected: Long, msg: => String): Boolean = { + expect(data, int(expected), msg) } def expect (data: Bits, expected: Long): Boolean = { - expect(data, BigInt(expected)) + expect(data, expected, "") + } + + /** Expect the value of 'data' to be 'expected' + * @return the test passed */ + def expect (data: Bool, expected: Boolean, msg: => String): Boolean = { + expect(data, { if (expected) 1 else 0 }, msg) + } + def expect (data: Bool, expected: Boolean): Boolean = { + expect(data, expected, "") + } + + /* We need the following so scala doesn't use our "tolerant" Float version of expect. + */ + /** Expect the value of 'data' to be 'expected' + * @return the test passed */ + def expect (data: Flo, expected: Float, msg: => String): Boolean = { + addEvent(new MuteEvent()) + val got = peek(data) + val good = got == expected + addEvent(new UnmuteEvent()) + addEvent(new ExpectFloEvent(data, got, expected, msg)) + if (!good) fail + good + } + def expect (data: Flo, expected: Float): Boolean = { + expect(data, expected, "") + } + + /** Expect the value of 'data' to be 'expected' + * @return the test passed */ + def expect (data: Dbl, expected: Double, msg: => String): Boolean = { + addEvent(new MuteEvent()) + val got = peek(data) + val good = got == expected + addEvent(new UnmuteEvent()) + addEvent(new ExpectDblEvent(data, got, expected, msg)) + if (!good) fail + good + } + def expect (data: Dbl, expected: Double): Boolean = { + expect(data, expected, "") } /* Compare the floating point value of a node with an expected floating point value. * We will tolerate differences in the bottom bit. */ - def expect (data: Bits, expected: Float): Boolean = { + /** A tolerant expect for Float + * Allows for a single least significant bit error in the floating point representation */ + def expect (data: Bits, expected: Float, msg: => String): Boolean = { + addEvent(new MuteEvent()) val gotBits = peek(data).toInt - val expectedBits = java.lang.Float.floatToIntBits(expected) var gotFLoat = java.lang.Float.intBitsToFloat(gotBits) + val expectedBits = java.lang.Float.floatToIntBits(expected) var expectedFloat = expected if (gotFLoat != expectedFloat) { val gotDiff = gotBits - expectedBits // Do we have a single bit difference? - if (abs(gotDiff) <= 1) { + if (scala.math.abs(gotDiff) <= 1) { expectedFloat = gotFLoat } } - expect(gotFLoat == expectedFloat, - "EXPECT " + dumpName(data) + " <- " + gotFLoat + " == " + expectedFloat) + val good = gotFLoat == expectedFloat + addEvent(new UnmuteEvent()) + addEvent(new ExpectFloEvent(data, gotFLoat, expected, msg)) + if (!good) fail + good + } + def expect (data: Bits, expected: Float): Boolean = { + expect(data, expected, "") } - val rnd = if (Driver.testerSeedValid) new Random(Driver.testerSeed) else new Random() - var process: Process = null + _signalMap ++= Driver.signalMap flatMap { + case (m: Mem[_], id) => + (0 until m.n) map (idx => "%s[%d]".format(dumpName(m), idx) -> (id + idx)) + case (node, id) => Seq(dumpName(node) -> id) + } - def start(): Process = { - val n = Driver.appendString(Some(c.name),Driver.chiselConfigClassName) - val target = Driver.targetDir + "/" + n - val cmd = - (if (Driver.backend.isInstanceOf[FloBackend]) { - val dir = Driver.backend.asInstanceOf[FloBackend].floDir - val command = ArrayBuffer(dir + "fix-console", ":is-debug", "true", ":filename", target + ".hex", ":flo-filename", target + ".mwe.flo") - if (Driver.isVCD) { command ++= ArrayBuffer(":is-vcd-dump", "true") } - if (Driver.emitTempNodes) { command ++= ArrayBuffer(":emit-temp-nodes", "true") } - command ++= ArrayBuffer(":target-dir", Driver.targetDir) - command.mkString(" ") - } else { - target + (if (Driver.backend.isInstanceOf[VerilogBackend]) " -q +vcs+initreg+0 " else "") - }) - println("SEED " + Driver.testerSeed) - println("STARTING " + cmd) + Driver.dfs { + case m: Mem[_] => (0 until m.n) foreach {idx => + val name = s"${dumpName(m)}[${idx}]" + _chunks(name) = (m.needWidth-1)/64 + 1 + } + case node if node.isInObject => + _chunks(dumpName(node)) = (node.needWidth-1)/64 + 1 + case _ => + } + + // Always use a specific seed so results (whenever) are reproducible. + val rnd = new Random(Driver.testerSeed) + val targetSubDir = Driver.appendString(Some(c.name),Driver.chiselConfigClassName) + val target = s"${Driver.targetDir}/${targetSubDir}" + // If the caller has provided a specific command to execute, use it. + val cmd = testCmd match { + case Some(cmd) => cmd + case None => Driver.backend match { + case b: FloBackend => + val command = ArrayBuffer(b.floDir + "fix-console", ":is-debug", "true", + ":filename", target + ".hex", ":flo-filename", target + ".mwe.flo") + if (Driver.isVCD) { command ++= ArrayBuffer(":is-vcd-dump", "true") } + if (Driver.emitTempNodes) { command ++= ArrayBuffer(":emit-temp-nodes", "true") } + command ++= ArrayBuffer(":target-dir", Driver.targetDir) + command.mkString(" ") + case b: VerilogBackend => + val vpd = dumpFile getOrElse s"${Driver.targetDir}/${c.name}.vpd" + List(target, "-q", "+vcs+initreg+0", + if (Driver.isVCD) s"+vpdfile=${vpd}" else "", + if (Driver.isVCDMem) "+vpdmem" else "") mkString " " + case c: CppBackend => + List(target, dumpFile map (vcd => s"+vcdfile=${vcd}") getOrElse "") mkString " " + case _ => target + } + } + private val (process: Process, exitValue: Future[Int], inChannel, outChannel, cmdChannel) = { val processBuilder = Process(cmd) - val pio = new ProcessIO(in => testOut = in, out => testIn = out, err => testErr = err) - process = processBuilder.run(pio) - waitForStreams() - t = 0 - reset(5) - // Skip vpd message - if (Driver.backend.isInstanceOf[VerilogBackend] && Driver.isDebug) { - var vpdmsg = testIn.read - while (vpdmsg != '\n' && vpdmsg != -1) - vpdmsg = testIn.read - } - process - } - - def finish(): Boolean = { - if (process != null) { - emulatorCmd("quit") - - if (testOut != null) { - testOut.flush() - testOut.close() - } - if (testIn != null) { - testIn.close() - } - if (testErr != null) { - testErr.close() + val processLogger = ProcessLogger(println, _logs += _) // don't log stdout + val process = processBuilder run processLogger + + // Set up a Future to wait for (and signal) the test process exit. + val exitValue: Future[Int] = Future { + blocking { + process.exitValue } + } + // Wait for the startup message + // NOTE: There may be several messages before we see our startup message. + val simStartupMessageStart = "sim start on " + while (!_logs.exists(_ startsWith simStartupMessageStart) && !exitValue.isCompleted) { Thread.sleep(100) } + // Remove the startup message (and any precursors). + while (!_logs.isEmpty && !_logs.head.startsWith(simStartupMessageStart)) { + println(_logs.remove(0)) + } + if (!_logs.isEmpty) println(_logs.remove(0)) else println("") + while (_logs.size < 3) { + // If the test application died, throw a run-time error. + throwExceptionIfDead(exitValue) + Thread.sleep(100) + } + val in_channel_name = _logs.remove(0) + val out_channel_name = _logs.remove(0) + val cmd_channel_name = _logs.remove(0) + val in_channel = new Channel(in_channel_name) + val out_channel = new Channel(out_channel_name) + val cmd_channel = new Channel(cmd_channel_name) + + println(s"inChannelName: ${in_channel_name}") + println(s"outChannelName: ${out_channel_name}") + println(s"cmdChannelName: ${cmd_channel_name}") + + in_channel.consume + cmd_channel.consume + in_channel.release + out_channel.release + cmd_channel.release + _t = 0 + + Tester.processes += process + (process, exitValue, in_channel, out_channel, cmd_channel) + } - process.destroy() + private def start { + mwhile(!recvOutputs) { } + addEvent(new StartEvent(Driver.testerSeed, cmd)) + // reset(5) + for (i <- 0 until 5) { + mwhile(!sendCmd(SIM_CMD.RESET)) { } + mwhile(!recvOutputs) { } } - println("RAN " + t + " CYCLES " + (if (ok) "PASSED" else { "FAILED FIRST AT CYCLE " + failureTime })) - ok } -} -class Tester[+T <: Module](c: T, isTrace: Boolean = true) extends ManualTester(c, isTrace) { - start() -} + def close { + Tester.processes -= process + process.destroy + } -class MapTester[+T <: Module](c: T, val testNodes: Array[Node]) extends Tester(c, false) { - def splitFlattenNodes(args: Seq[Node]): (Seq[Node], Seq[Node]) = { - if (args.length == 0) { - (Array[Node](), Array[Node]()) - } else { - val testNodes = args.map(i => i.maybeFlatten).reduceLeft(_ ++ _).map(x => x.getNode); - (c.keepInputs(testNodes), c.removeInputs(testNodes)) + /** Complete the simulation and inspect all tests */ + def finish: Boolean = { + try { + mwhile(!sendCmd(SIM_CMD.FIN)) { } + while(!exitValue.isCompleted) { } + } + catch { + // Depending on load and timing, we may get a TestApplicationException + // when the test application exits. + // Check the exit value. + // Anything other than 0 is an error. + case e: TestApplicationException => if (e.exitVal != 0) fail } + addEvent(new DumpEvent(newTestOutputString)) + addEvent(new FinishEvent(t, ok, failureTime)) + _logs.clear + inChannel.close + outChannel.close + cmdChannel.close + Tester.processes -= process + ok } - val (ins, outs) = splitFlattenNodes(testNodes) - val testInputNodes = ins.toArray; - val testNonInputNodes = outs.toArray + + // Once everything has been prepared, we can start the communications. + start +} + +/** A tester to check a node graph from INPUTs to OUTPUTs directly */ +class MapTester[+T <: Module](c: T, val testNodes: Seq[Node]) extends Tester(c, false) { + val (ins, outs) = testNodes partition { case b: Bits => b.dir == INPUT case _ => false } def step(svars: HashMap[Node, Node], - ovars: HashMap[Node, Node] = new HashMap[Node, Node], + ovars: HashMap[Node, Node] = HashMap.empty, isTrace: Boolean = true): Boolean = { - if (isTrace) { println("---"); println("INPUTS") } - for (n <- testInputNodes) { - val v = svars.getOrElse(n, null) - val i = if (v == null) BigInt(0) else v.litValue() // TODO: WARN - pokeBits(n, i) + if (isTrace) println("---\nINPUTS") + ins foreach { in => + val value = (svars get in) match { case None => BigInt(0) case Some(v) => v.litValue() } + in match { + case io: Bits if io.isTopLevelIO => poke(io, value) + case _ => pokeNode(in, value) + } + if (isTrace) println(" WRITE " + dumpName(in) + " = " + value) } - if (isTrace) println("OUTPUTS") - var isSame = true step(1) - for (o <- testNonInputNodes) { - val rv = peekBits(o) - if (isTrace) println(" READ " + o + " = " + rv) - if (!svars.contains(o)) { - ovars(o) = Literal(rv) - } else { - val tv = svars(o).litValue() - if (isTrace) println(" EXPECTED: " + o + " = " + tv) - if (tv != rv) { - isSame = false - if (isTrace) println(" *** FAILURE ***") - } else { - if (isTrace) println(" SUCCESS") - } + if (isTrace) println("OUTPUTS") + outs forall { out => + val value = out match { + case io: Bits if io.isTopLevelIO => peek(io) + case _ => peekNode(out) + } + (ovars get out) match { + case None => + ovars(out) = Literal(value) + if (isTrace) println(" READ " + dumpName(out) + " = " + value) + true + case Some(e) => + val expected = e.litValue() + val pass = expected == value + if (isTrace) println(" EXPECTED %s: %x == %x -> %s".format(value, expected, if (pass) "PASS" else "FAIL")) + pass } } - isSame } var tests: () => Boolean = () => { println("DEFAULT TESTS"); true } def defTests(body: => Boolean) = body - } - diff --git a/src/main/scala/UInt.scala b/src/main/scala/UInt.scala index c3b06767..9344a8db 100644 --- a/src/main/scala/UInt.scala +++ b/src/main/scala/UInt.scala @@ -1,5 +1,5 @@ /* - Copyright (c) 2011, 2012, 2013, 2014 The Regents of the University of + Copyright (c) 2011 - 2016 The Regents of the University of California (Regents). All Rights Reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: @@ -29,8 +29,6 @@ */ package Chisel -import Node._ -import ChiselError._ object UInt { /* Implementation Note: scalac does not allow multiple overloaded @@ -38,23 +36,63 @@ object UInt { methods to create UInt from litterals (with implicit and explicit widths) and reserve the default parameters for the "direction" method. */ + /** Create a UInt from an Int */ def apply(x: Int): UInt = apply(BigInt(x)) + /** Create a UInt from an Int with specified width */ def apply(x: Int, width: Int): UInt = apply(BigInt(x), width) - def apply(x: BigInt): UInt = Lit(checkSign(x)){UInt()}; - def apply(x: BigInt, width: Int): UInt = Lit(checkSign(x), width){UInt()}; - def apply(x: String): UInt = Lit(x, -1){UInt()}; - def apply(x: String, width: Int): UInt = Lit(x, width){UInt()}; - def apply(x: String, base: Char): UInt = Lit(x, base, -1){UInt()}; - def apply(x: String, base: Char, width: Int): UInt = Lit(x, base, width){UInt()}; + /** Create a UInt from a BigInt */ + def apply(x: BigInt): UInt = Lit(checkSign(x)){UInt()} + /** Create a UInt from a BigInt with specified width */ + def apply(x: BigInt, width: Int): UInt = Lit(checkSign(x), width){UInt()} + /** Create a UInt from a string of the format Bxxxx + * where B is the base and can be: + * - h for hex + * - d for decimal + * - o for octal + * - b for binary + */ + def apply(x: String): UInt = Lit(x, -1){UInt()} + /** Create a UInt from a string of the format Bxxxx + * where B is the base and can be: + * - h for hex + * - d for decimal + * - o for octal + * - b for binary + * with an enforced 'width' + */ + def apply(x: String, width: Int): UInt = Lit(x, width){UInt()} + /** Create a UInt from a string + * @param x is a String in the specified base + * @param base is: + * - h for hex + * - d for decimal + * - o for octal + * - b for binary + */ + def apply(x: String, base: Char): UInt = Lit(x, base, -1){UInt()} + /** Create a UInt from a string + * @param x is a String in the specified base + * @param base is: + * - h for hex + * - d for decimal + * - o for octal + * - b for binary + * @param width enforced bitwidth + */ + def apply(x: String, base: Char, width: Int): UInt = Lit(x, base, width){UInt()} + /** Create a UInt from a Node */ def apply(x: Node): UInt = UInt(x, -1) + /** Create a UInt from a Node with specified width */ def apply(x: Node, width: Int): UInt = UInt(width = width).asTypeFor(x) - - def apply(dir: IODirection = null, width: Int = -1): UInt = { - val res = new UInt(); + /** Create a UInt for I/O with optional width */ + def apply(dir: IODirection = NODIR, width: Int = -1): UInt = { + val res = new UInt() res.create(dir, width) res } +// FIXME: This should return a BitPat, not a UInt +// def DC(width: Int): BitPat = BitPat.DC(width) def DC(width: Int): UInt = Lit("b" + "?"*width, width){UInt()} private def checkSign(x: BigInt) = { @@ -75,33 +113,62 @@ class UInt extends Bits with Num[UInt] { // NOTE: we do not inherit/clone the width. // Doing so breaks code in NodeFill() // res.width_ = n.width_.clone() + n match { + case l: Literal => + if (l.isZ) { + // Chisel3 compatibility - generic don't care UInts/Bits are deprecated. + ChiselError.check("General don't care UInts are deprecated. Please use BitPat().", Version("3.0")) + } + case _ => + } res } + /** Set the value of this UInt */ override def fromInt(x: Int): this.type = { UInt(x).asInstanceOf[this.type] } override def toBits: UInt = this - // to support implicit convestions + // to support implicit conversions def ===(b: UInt): Bool = LogicalOp(this, b, "===") // arithmetic operators - def zext(): SInt = Cat(UInt(0,1), this).toSInt + /** Convert a UInt to an SInt by added a MSB zero */ + def zext(): SInt = { + // Don't sign-extend a zero-width node. + val result = if (isZeroWidth) { + this + } else { + Cat(UInt(0,1), this) + } + result.toSInt + } + def unary_-(): UInt = UInt(0) - this def unary_!(): Bool = this === UInt(0) - def >> (b: UInt): UInt = newBinaryOp(b, ">>"); - def + (b: UInt): UInt = newBinaryOp(b, "+"); - def * (b: UInt): UInt = newBinaryOp(b, "*"); - def / (b: UInt): UInt = newBinaryOp(b, "/"); - def % (b: UInt): UInt = newBinaryOp(b, "%"); + def >> (b: UInt): UInt = newBinaryOp(b, ">>") + def + (b: UInt): UInt = newBinaryOp(b, "+") + def * (b: UInt): UInt = newBinaryOp(b, "*") + def / (b: UInt): UInt = newBinaryOp(b, "/") + def % (b: UInt): UInt = newBinaryOp(b, "%") def ? (b: UInt): UInt = fromNode(Multiplex(this.toBool, b, null)) - def - (b: UInt): UInt = newBinaryOp(b, "-"); + def - (b: UInt): UInt = newBinaryOp(b, "-") + def >> (i: Int): UInt = newBinaryOp(UInt(i), ">>") // chisel3 + def << (i: Int): UInt = newBinaryOp(UInt(i), "<<") // chisel3 + /** chisel3 add-wrap operator */ + def +% (b: UInt): UInt = newBinaryOp(b, "+") + /** chisel3 add (width +1) operator */ + def +& (b: UInt): UInt = newBinaryOp(b, "+&") + /** chisel3 sub-wrap operator */ + def -% (b: UInt): UInt = newBinaryOp(b, "-") + /** chisel3 sub (width +1) operator */ + def -& (b: UInt): UInt = newBinaryOp(b, "-&") // order operators - def < (b: UInt): Bool = newLogicalOp(b, "<"); - def <= (b: UInt): Bool = newLogicalOp(b, "<="); + def < (b: UInt): Bool = newLogicalOp(b, "<") + def <= (b: UInt): Bool = newLogicalOp(b, "<=") def > (b: UInt): Bool = b < this def >= (b: UInt): Bool = b <= this diff --git a/src/main/scala/Vcd.scala b/src/main/scala/Vcd.scala index e677f30e..5063c42d 100644 --- a/src/main/scala/Vcd.scala +++ b/src/main/scala/Vcd.scala @@ -1,5 +1,5 @@ /* - Copyright (c) 2011, 2012, 2013, 2014 The Regents of the University of + Copyright (c) 2011 - 2016 The Regents of the University of California (Regents). All Rights Reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: @@ -29,17 +29,8 @@ */ package Chisel -import Node._ -import Reg._ -import Literal._ -import ChiselError._ -import scala.collection.mutable.HashMap -import scala.collection.mutable.HashSet -import scala.collection.mutable.ArrayBuffer class VcdBackend(top: Module) extends Backend { - val keywords = Set[String]() - override def emitTmp(node: Node): String = emitRef(node) override def emitRef(node: Node): String = @@ -47,228 +38,287 @@ class VcdBackend(top: Module) extends Backend { case _: Literal => node.name case _: Reg => - if (node.named) node.name else "R" + node.emitIndex + if (node.named) node.name else s"R${node.emitIndex}" case _ => - if (node.named) node.name else "T" + node.emitIndex + if (node.named) node.name else s"T${node.emitIndex}" } + private def emitDefUnconditional(index: Int) = + s"dat_dump<1>(f, reset, 0x%x);".format(varNumber(index)) + private def emitDefUnconditional(node: Node, index: Int) = - " dat_dump<" + varNameLength(index) + ">(f, " + emitRef(node) + ", 0x" + varNumber(index).toHexString + ");\n" + s"dat_dump<${varNameLength(index)}>(f, ${emitRef(node)}, 0x%x);".format(varNumber(index)) private def emitDefUnconditional(node: Node, offset: Int, index: Int) = - " dat_dump<" + varNameLength(index) + ">(f, " + emitRef(node) + ".get(0x" + offset.toHexString +"), 0x" + varNumber(index).toHexString + ");\n" + s"dat_dump<${varNameLength(index)}>(f, ${emitRef(node)}.get(0x%x), 0x%x);".format(offset, varNumber(index)) - private def emitDef1(node: Node, index: Int) = - " if (" + emitRef(node) + " != " + emitRef(node) + "__prev)\n" + - " goto L" + index + ";\n" + - "K" + index + ":\n" + private def emitDef1(clk: Clock, index: Int, toZero: Boolean) = List( + s" if (${emitRef(clk)}.cnt == 0) goto ${if (toZero) "Z" else "L"}${index};", + s"${if (toZero) "C" else "K"}${index}:") mkString "\n" - private def emitDef1(node: Node, offset: Int, index: Int) = - " if (" + emitRef(node) + ".get(0x" + offset.toHexString +") != " + emitRef(node) + - "__prev.get(0x" + offset.toHexString + "))\n" + - " goto L" + index + ";\n" + - "K" + index + ":\n" + private def emitDef1(index: Int) = List( + s" if (reset != reset__prev) goto L${index};", + s"K${index}:") mkString "\n" - private def emitDef2(node: Node, index: Int) = - "L" + index + ":\n" + - " " + emitRef(node) + "__prev = " + emitRef(node) + ";\n" + - emitDefUnconditional(node, index) + - " goto K" + index + ";\n" + private def emitDef1(node: Node, index: Int) = List( + s" if (${emitRef(node)} != ${emitRef(node)}__prev) goto L${index};", + s"K${index}:") mkString "\n" - private def emitDef2(node: Node, offset: Int, index: Int) = - "L" + index + ":\n" + - " " + emitRef(node) + "__prev.get(0x" + offset.toHexString + ") = " + - emitRef(node) + ".get(0x" + offset.toHexString + ");\n" + - emitDefUnconditional(node, offset, index) + - " goto K" + index + ";\n" + private def emitDef1(node: Node, offset: Int, index: Int) = List( + s" if (${emitRef(node)}.get(0x%x) != ${emitRef(node)}__prev.get(0x%x)) goto L${index};".format(offset, offset), + s"K${index}:") mkString "\n" - private def emitDefInline(node: Node, index: Int) = - " if (" + emitRef(node) + " != " + emitRef(node) + "__prev) {\n" + - " " + emitRef(node) + "__prev = " + emitRef(node) + ";\n" + - " " + emitDefUnconditional(node, index) + - " }\n" + private def emitDef2(clk: Clock, index: Int, isZero: Boolean) = List( + s"${if (isZero) "Z" else "L"}${index}:", + s" ${emitRef(clk)}.values[0] = ${if (isZero) 0 else 1};", + s" ${emitDefUnconditional(clk, index)}", + s" goto ${if (isZero) "C" else "K"}${index};\n") mkString "\n" - private def emitDefInline(node: Node, offset: Int, index: Int) = - " if (" + emitRef(node) + ".get(0x" + offset.toHexString +") != " + emitRef(node) + - "__prev.get(0x" + offset.toHexString + ")) {\n" + - " " + emitRef(node) + "__prev.get(0x" + offset.toHexString + ") = " + - " " + emitRef(node) + ".get(0x" + offset.toHexString + ");\n" + - " " + emitDefUnconditional(node, offset, index) + - " }\n" + private def emitDef2(index: Int) = List( + s"L${index}:", + " reset__prev = reset;", + s" ${emitDefUnconditional(index)}", + s" goto K${index};\n") mkString "\n" - override def emitDec(node: Node): String = - if (Driver.isVCD && node.isInVCD) { - node match { - case m: Mem[_] => - " mem_t<" + m.needWidth() + "," + m.n + "> " + emitRef(node) + "__prev" + ";\n" - case r: ROMData => - " mem_t<" + r.needWidth() + "," + r.lits.size + "> " + emitRef(node) + "__prev" + ";\n" - case _ => - " dat_t<" + node.needWidth() + "> " + emitRef(node) + "__prev" + ";\n" - } - } - else "" + private def emitDef2(node: Node, index: Int) = List( + s"L${index}:", + s" ${emitRef(node)}__prev = ${emitRef(node)};", + s" ${emitDefUnconditional(node, index)}", + s" goto K${index};\n") mkString "\n" + + private def emitDef2(node: Node, offset: Int, index: Int) = List( + s"L${index}:", + s" ${emitRef(node)}__prev.put(0x%x, ${emitRef(node)}.get(0x%x));".format(offset, offset), + s" ${emitDefUnconditional(node, offset, index)}", + s" goto K${index};\n") mkString "\n" + + private def emitDefInline(clk: Clock, index: Int, isZero: Boolean) = List( + s" if (${emitRef(clk)}.cnt == 0) {", + s" ${emitRef(clk)}.values[0] = ${if (isZero) 0 else 1};", + s" ${emitDefUnconditional(clk, index)}", " }\n") mkString "\n" + + private def emitDefInline(index: Int) = List( + " if (reset != reset__prev) {", + " reset__prev = reset;", + s" ${emitDefUnconditional(index)}", " }\n") mkString "\n" + + private def emitDefInline(node: Node, index: Int) = List( + s" if (${emitRef(node)} != ${emitRef(node)}__prev) {", + s" ${emitRef(node)}__prev = ${emitRef(node)};", + s" ${emitDefUnconditional(node, index)}", " }\n") mkString "\n" + + private def emitDefInline(node: Node, offset: Int, index: Int) = List( + s" if (${emitRef(node)}.get(0x${offset.toHexString}) != ${emitRef(node)}__prev.get(0x${offset.toHexString})) {", + s" ${emitRef(node)}__prev.put(0x${offset.toHexString}, ${emitRef(node)}.get(0x${offset.toHexString}));", + s" ${emitDefUnconditional(node, offset, index)}", " }\n") mkString "\n" + + override def emitDec(node: Node): String = node match { + case m: Mem[_] => + s" mem_t<${m.needWidth},${m.n}> ${emitRef(node)}__prev;\n" + case r: ROMData => + s" mem_t<${r.needWidth},${r.n}> ${emitRef(node)}__prev;\n" + case _ => + s" dat_t<${node.needWidth}> ${emitRef(node)}__prev;\n" + } def dumpVCDScope(c: Module, write: String => Unit): Unit = { - write(" fputs(\"" + "$scope module " + c.name + " $end" + "\\n\", f);\n") - for (i <- 0 until sortedMods.length) { - val mod = sortedMods(i) - if (mod.component == c && !mod.name.isEmpty) - write(" fputs(\"$var wire " + mod.needWidth() + " " + varName(i) + " " + top.stripComponent(emitRef(mod)) + " $end\\n\", f);\n") + write(" fputs(\"$scope module %s $end\\n\", f);\n".format(c.name)) + if (c == topMod) { + for ((clk, i) <- Driver.clocks.zipWithIndex) { + write(" fputs(\"$var wire 1 %s %s $end\\n\", f);\n".format(varName(i), clk.name)) + } + } + var baseIdx = Driver.clocks.size + if (c == topMod) write(" fputs(\"$var wire 1 %s reset $end\\n\", f);\n".format(varName(baseIdx))) + baseIdx += 1 + for ((node, i) <- sortedNodes.zipWithIndex if c == node.component && !node.name.isEmpty) { + write(" fputs(\"$var wire %d %s %s $end\\n\", f);\n".format( + node.needWidth, varName(baseIdx + i), top.stripComponent(emitRef(node)))) } - var baseIdx = sortedMods.length + baseIdx += sortedNodes.size for (mem <- sortedMems) { if (mem.component == c && !mem.name.isEmpty) { for (offset <- 0 until mem.n) { - write(" fputs(\"$var wire " + mem.needWidth() + " " + varName(baseIdx + offset) + " " + - top.stripComponent(emitRef(mem)) + "[%d] $end\\n\", f);\n".format(offset)) + write(" fputs(\"$var wire %d %s %s[%d] $end\\n\", f);\n".format( + mem.needWidth, varName(baseIdx + offset), top.stripComponent(emitRef(mem)), offset)) } } baseIdx += mem.n } for (rom <- sortedROMs) { if (rom.component == c && !rom.name.isEmpty) { - for (offset <- 0 until rom.lits.size) { - write(" fputs(\"$var wire " + rom.needWidth() + " " + varName(baseIdx + offset) + " " + - top.stripComponent(emitRef(rom)) + "[%d] $end\\n\", f);\n".format(offset)) + for (offset <- 0 until rom.n) { + write(" fputs(\"$var wire %d %s %s[%d] $end\\n\", f);\n".format( + rom.needWidth, varName(baseIdx + offset), top.stripComponent(emitRef(rom)), offset)) } } - baseIdx += rom.lits.size - } - for (child <- c.children) { - dumpVCDScope(child, write) + baseIdx += rom.n } + for (child <- c.children) dumpVCDScope(child, write) write(" fputs(\"$upscope $end\\n\", f);\n") } def dumpScopeForTemps(write: String => Unit): Unit = { - write(" fputs(\"" + "$scope module _chisel_temps_ $end" + "\\n\", f);\n") - for (i <- 0 until sortedMods.length) { - val mod = sortedMods(i) - if (mod.name.isEmpty) - write(" fputs(\"$var wire " + mod.needWidth() + " " + varName(i) + " " + top.stripComponent(emitRef(mod)) + " $end\\n\", f);\n") + write(" fputs(\"$scope module _chisel_temps_ $end\\n\", f);\n") + var baseIdx = Driver.clocks.size + 1 + for ((node, i) <- sortedNodes.zipWithIndex if node.name.isEmpty) { + write(" fputs(\"$var wire %d %s %s $end\\n\", f);\n".format( + node.needWidth, varName(baseIdx + i), top.stripComponent(emitRef(node)))) } - var baseIdx = sortedMods.length + baseIdx += sortedNodes.size for (mem <- sortedMems) { if (mem.name.isEmpty) { for (offset <- 0 until mem.n) { - write(" fputs(\"$var wire " + mem.needWidth() + " " + varName(baseIdx + offset) + " " + - top.stripComponent(emitRef(mem)) + "[%d] $end\\n\", f);\n".format(offset)) + write(" fputs(\"$var wire %d %s %s[%d] $end\\n\", f);\n".format( + mem.needWidth, varName(baseIdx + offset), top.stripComponent(emitRef(mem)), offset)) } } baseIdx += mem.n } for (rom <- sortedROMs) { if (rom.name.isEmpty) { - for (offset <- 0 until rom.lits.size) { - write(" fputs(\"$var wire " + rom.needWidth() + " " + varName(baseIdx + offset) + " " + - top.stripComponent(emitRef(rom)) + "[%d] $end\\n\", f);\n".format(offset)) + for (offset <- 0 until rom.n) { + write(" fputs(\"$var wire %d %s %s[%d] $end\\n\", f);\n".format( + rom.needWidth, varName(baseIdx + offset), top.stripComponent(emitRef(rom)), offset)) } } - baseIdx += rom.lits.size + baseIdx += rom.n } write(" fputs(\"$upscope $end\\n\", f);\n") } - def dumpVCDInit(write: String => Unit): Unit = { - if (Driver.isVCD) { - write(" fputs(\"$timescale 1ps $end\\n\", f);\n") - dumpVCDScope(top, write) - if (Driver.emitTempNodes) - dumpScopeForTemps(write) - write(" fputs(\"$enddefinitions $end\\n\", f);\n") - write(" fputs(\"$dumpvars\\n\", f);\n") - write(" fputs(\"$end\\n\", f);\n") - write(" fputs(\"#0\\n\", f);\n") - for (i <- 0 until sortedMods.length) { - write(emitDefUnconditional(sortedMods(i), i)) - val ref = emitRef(sortedMods(i)) - write(" " + ref + "__prev = " + ref +";\n"); - } - var baseIdx = sortedMods.length - for (mem <- sortedMems) { - for (offset <- 0 until mem.n) - write(emitDefUnconditional(mem, offset, baseIdx + offset)) - baseIdx += mem.n - } - for (rom <- sortedROMs) { - for (offset <- 0 until rom.lits.size) - write(emitDefUnconditional(rom, offset, baseIdx + offset)) - baseIdx += rom.lits.size - } + def dumpVCDInit(write: String => Unit): Unit = if (Driver.isVCD) { + write(" fputs(\"$timescale %dps $end\\n\", f);\n".format(Driver.implicitClock.period.round)) + dumpVCDScope(top, write) + if (Driver.emitTempNodes) dumpScopeForTemps(write) + write(" fputs(\"$enddefinitions $end\\n\", f);\n") + write(" fputs(\"$dumpvars\\n\", f);\n") + write(" fputs(\"$end\\n\", f);\n") + write(" fputs(\"#0\\n\", f);\n") + for ((clk, i) <- Driver.clocks.zipWithIndex) { + write(emitDefInline(clk, i, false)) + } + var baseIdx = Driver.clocks.size + write( " dat_t<1> reset = LIT<1>(1);\n") + write(s" ${emitDefUnconditional(baseIdx)}\n") + baseIdx += 1 + for ((node, i) <- sortedNodes.zipWithIndex) { + write(s" ${emitDefUnconditional(node, baseIdx + i)}\n") + write(s" ${emitRef(node)}__prev = ${emitRef(node)};\n") + } + baseIdx += sortedNodes.size + for (mem <- sortedMems) { + for (offset <- 0 until mem.n) + write(s" ${emitDefUnconditional(mem, offset, baseIdx + offset)}\n") + baseIdx += mem.n + } + for (rom <- sortedROMs) { + for (offset <- 0 until rom.n) + write(s" ${emitDefUnconditional(rom, offset, baseIdx + offset)}\n") + baseIdx += rom.n + } + write(" fputs(\"#1\\n\", f);\n") + for ((clk, i) <- Driver.clocks.zipWithIndex) { + write(emitDefInline(clk, i, true)) } } - def dumpModsInline(write: String => Unit) { - for (i <- 0 until sortedMods.length) - write(emitDefInline(sortedMods(i), i)) - var baseIdx = sortedMods.length + def dumpNodesInline(write: String => Unit) { + for ((clk, i) <- Driver.clocks.zipWithIndex) { + write(emitDefInline(clk, i, false)) + } + // reset + var baseIdx = Driver.clocks.size + write(emitDefInline(baseIdx)) + baseIdx += 1 + for ((node, i) <- sortedNodes.zipWithIndex) + write(emitDefInline(node, baseIdx + i)) + baseIdx += sortedNodes.size for (mem <- sortedMems) { for (offset <- 0 until mem.n) write(emitDefInline(mem, offset, baseIdx + offset)) baseIdx += mem.n } for (rom <- sortedROMs) { - for (offset <- 0 until rom.lits.size) + for (offset <- 0 until rom.n) write(emitDefInline(rom, offset, baseIdx + offset)) - baseIdx += rom.lits.size + baseIdx += rom.n + } + write(" fprintf(f, \"#%lu\\n\", (t << 1) + 1);\n") + for ((clk, i) <- Driver.clocks.zipWithIndex) { + write(emitDefInline(clk, i, true)) } write(" return;\n") } - def dumpModsGoTos(write: String => Unit) { - for (i <- 0 until sortedMods.length) - write(emitDef1(sortedMods(i), i)) - var baseIdx = sortedMods.length + def dumpNodesGoTos(write: String => Unit) { + for ((clk, i) <- Driver.clocks.zipWithIndex) { + write(emitDef1(clk, i, false)) + } + var baseIdx = Driver.clocks.size + write(emitDef1(baseIdx)) + baseIdx += 1 + for ((node, i) <- sortedNodes.zipWithIndex) + write(emitDef1(node, baseIdx + i)) + baseIdx += sortedNodes.size for (mem <- sortedMems) { for (offset <- 0 until mem.n) write(emitDef1(mem, offset, baseIdx + offset)) baseIdx += mem.n } for (rom <- sortedROMs) { - for (offset <- 0 until rom.lits.size) + for (offset <- 0 until rom.n) write(emitDef1(rom, offset, baseIdx + offset)) - baseIdx += rom.lits.size + baseIdx += rom.n + } + write(" fprintf(f, \"#%lu\\n\", (t << 1) + 1);\n") + for ((clk, i) <- Driver.clocks.zipWithIndex) { + write(emitDef1(clk, i, true)) } write(" return;\n") - for (i <- 0 until sortedMods.length) - write(emitDef2(sortedMods(i), i)) - baseIdx = sortedMods.length + for ((clk, i) <- Driver.clocks.zipWithIndex) { + write(emitDef2(clk, i, false)) + } + baseIdx = Driver.clocks.size + write(emitDef2(baseIdx)) + baseIdx += 1 + for ((node, i) <- sortedNodes.zipWithIndex) + write(emitDef2(node, baseIdx + i)) + baseIdx += sortedNodes.size for (mem <- sortedMems) { for (offset <- 0 until mem.n) write(emitDef2(mem, offset, baseIdx + offset)) baseIdx += mem.n } for (rom <- sortedROMs) { - for (offset <- 0 until rom.lits.size) + for (offset <- 0 until rom.n) write(emitDef2(rom, offset, baseIdx + offset)) - baseIdx += rom.lits.size + baseIdx += rom.n + } + for ((clk, i) <- Driver.clocks.zipWithIndex) { + write(emitDef2(clk, i, true)) } } def dumpVCD(write: String => Unit): Unit = { if (Driver.isVCDinline) { - dumpModsInline(write) + dumpNodesInline(write) } else { - dumpModsGoTos(write) + dumpNodesGoTos(write) } } - private val sortedMods = (Driver.orderedNodes foldLeft Array[Node]()){ - case (array: Array[Node], mem: Mem[_]) => array - case (array: Array[Node], rom: ROMData) => array - case (array: Array[Node], node: Node) => if (node.isInVCD) array ++ Array(node) else array - } sortWith (_.width < _.width) - - private val sortedMems = (Driver.orderedNodes foldLeft Array[Mem[_]]()){ - case (array: Array[Mem[_]], mem: Mem[_]) => if (mem.isInVCD) array ++ Array(mem) else array - case (array: Array[Mem[_]], node: Node) => array + private lazy val sortedNodes = Driver.orderedNodes filter { + case _: Mem[_] => false case _: ROMData => false case node => node.isInVCD } sortWith (_.widthW < _.widthW) - private val sortedROMs = (Driver.orderedNodes foldLeft Array[ROMData]()){ - case (array: Array[ROMData], rom: ROMData) => if (rom.isInVCD) array ++ Array(rom) else array - case (array: Array[ROMData], node: Node) => array - } sortWith (_.width < _.width) + private lazy val sortedMems: Seq[Mem[_]] = Driver.orderedNodes filter { + case m: Mem[_] => m.isInVCD case _ => false + } map (_.asInstanceOf[Mem[_]]) sortWith (_.widthW < _.widthW) + + private lazy val sortedROMs: Seq[ROMData] = Driver.orderedNodes filter { + case r: ROMData => r.isInVCD case _ => false + } map (_.asInstanceOf[ROMData]) sortWith (_.widthW < _.widthW) private val (lo, hi) = ('!'.toInt, '~'.toInt) private val range = hi - lo + 1 diff --git a/src/main/scala/Vec.scala b/src/main/scala/Vec.scala index 23d1d5bb..d34366de 100644 --- a/src/main/scala/Vec.scala +++ b/src/main/scala/Vec.scala @@ -1,5 +1,5 @@ /* - Copyright (c) 2011, 2012, 2013, 2014 The Regents of the University of + Copyright (c) 2011 - 2016 The Regents of the University of California (Regents). All Rights Reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: @@ -30,14 +30,8 @@ package Chisel -import ChiselError._ -import scala.collection.mutable.ArrayBuffer -import scala.collection.mutable.HashMap -import scala.collection.mutable.BufferProxy -import scala.collection.mutable.Stack -import scala.math._ -import Vec._ -import Node._ +import scala.collection.mutable.{ArrayBuffer, HashMap} +import scala.util.{Try,Success,Failure} object VecMux { def apply(addr: UInt, elts: Seq[Data]): Data = { @@ -54,54 +48,92 @@ object VecMux { } object Vec { + @deprecated("Vec(gen: => T, n:Int) is deprecated. Please use Vec(n:Int, gen: => T) instead.", "2.29") + def apply[T <: Data](gen: => T, n: Int): Vec[T] = { + ChiselError.check("Chisel3 compatibility: Vec(gen: => T, n:Int) is deprecated. Please use Vec(n:Int, gen: => T) instead.", Version("3.0")) + apply(n, gen) + } + + def checkCloneType[T <: Data](element: T): Option[element.type] = { + // Clone or complain. + Try(element.checkClone(Array("cloneType"))) match { + case Success(c) => Some(c.get.asInstanceOf[element.type]) + case Failure(e) => + ChiselError.check(s"Chisel3 compatibility: " + e, Version("3.0")) + None + } + } /** Returns a new *Vec* from a sequence of *Data* nodes. */ - def apply[T <: Data](elts: Iterable[T]): Vec[T] = { + def apply[T <: Data](elts: Seq[T]): Vec[T] = { val res = if (!elts.isEmpty && elts.forall(_.isLit)) ROM(elts) - else new Vec[T](i => elts.head.clone, elts) + else new Vec[T](i => elts.head.cloneType, elts) res } /** Returns a new *Vec* from the concatenation of a *Data* node and a sequence of *Data* nodes. */ - def apply[T <: Data](elt0: T, elts: T*): Vec[T] = - apply(elt0 +: elts.toSeq) + def apply[T <: Data](elt0: T, elts: T*): Vec[T] = apply(elt0 +: elts.toSeq) /** Returns an array that contains the results of some element computation a number of times. Note that this means that elem is computed a total of n times. */ - def fill[T <: Data](n: Int)(gen: => T): Vec[T] = - tabulate(n){ i => gen } + def fill[T <: Data](n: Int)(gen: => T): Vec[T] = tabulate(n){ i => gen } /** Returns an array containing values of a given function over a range of integer values starting from 0. */ - def tabulate[T <: Data](n: Int)(gen: (Int) => T): Vec[T] = - apply((0 until n).map(i => gen(i))) + def tabulate[T <: Data](n: Int)(gen: (Int) => T): Vec[T] = { + // If we aren't going to put any elements in the vector, + // ensure the type is cloneable while we know what it is. + // Chisel3 - compatibility checks + if (Driver.minimumCompatibility > "2" && n == 0) { + // We need to treat empty Vec's here since apply can't deal with an empty sequence. + checkCloneType(gen(0)) + // In any case, return an empty Vec. + new Vec[T](i => gen(0), Seq[T]()) + } else { + apply((0 until n).map(i => gen(i))) + } + } def tabulate[T <: Data](n1: Int, n2: Int)(f: (Int, Int) => T): Vec[Vec[T]] = tabulate(n1)(i1 => tabulate(n2)(f(i1, _))) + def apply[T <: Data](n: Int, gen: => T): Vec[T] = fill(n)(gen) } -class VecProc(enables: Iterable[Bool], elms: Iterable[Data]) extends proc { +class VecProc(enables: Seq[Bool], elms: Seq[Data]) extends proc { override def procAssign(src: Node): Unit = { for ((en, elm) <- enables zip elms) when (en) { - if(elm.comp != null) elm.comp procAssign src - else elm.asInstanceOf[Bits] procAssign src + elm.comp match { + case None => elm.asInstanceOf[Bits] procAssign src + case Some(p) => p procAssign src + } } } } -class Vec[T <: Data](val gen: (Int) => T, elts: Iterable[T]) extends Aggregate with VecLike[T] with Cloneable { +class Vec[T <: Data](val gen: (Int) => T, elts: Seq[T]) extends Aggregate with VecLike[T] with Cloneable { val self = elts.toVector + if (self != null && !self.isEmpty && self(0).getNode.isInstanceOf[Reg]) { + ChiselError.check("Chisel3 compatibility: Vec(Reg) is deprecated. Please use Reg(Vec)", Version("3.0")) + } + // Chisel3 - compatibility checks + if (Driver.minimumCompatibility > "2") { + if (self != null && !self.isEmpty) { + if (self(0).getNode.isInstanceOf[Reg]) { + ChiselError.check("Chisel3 compatibility: Vec(Reg) is deprecated. Please use Reg(Vec)", Version("3.0")) + } + Vec.checkCloneType(self(0)) + } + } val readPorts = new HashMap[UInt, T] - override def apply(idx: Int): T = self(idx) // TODO: better way to generated this structure? @@ -109,8 +141,8 @@ class Vec[T <: Data](val gen: (Int) => T, elts: Iterable[T]) extends Aggregate w // create buckets for each elm in data type val buckets = (for (i <- 0 until this(0).flatten.length) yield (new ArrayBuffer[Data])).toArray // fill out buckets - for (elm <- this ; ((n, io), i) <- elm.flatten.zipWithIndex) buckets(i) += io - + for (elm <- this ; ((n, io), i) <- elm.flatten.zipWithIndex) buckets(i) += io + buckets } @@ -125,23 +157,25 @@ class Vec[T <: Data](val gen: (Int) => T, elts: Iterable[T]) extends Aggregate w readPorts(addr) } else { val iaddr = UInt(width = log2Up(length)) + iaddr.setIsWired(true) iaddr assign addr val enables = (UInt(1) << iaddr).toBools - val res = this(0).clone + val res = this(0).cloneType for(((n, io), sortedElm) <- res.flatten zip sortedElements) { io assign VecMux(iaddr, sortedElm) // setup the comp for writes - io.comp = new VecProc(enables, sortedElm) + io.comp = Some(new VecProc(enables, sortedElm)) } readPorts(addr) = res res.setIsTypeNode + res.setIsWired(true) res } } override def flatten: Array[(String, Bits)] = { // Todo: why reverse? - (self.zipWithIndex.reverse foldLeft Array[(String, Bits)]()){(res, x) => + (self.zipWithIndex.reverse foldLeft Array[(String, Bits)]()){(res, x) => val (elm, idx) = x res ++ (if (elm.name != "") elm.flatten else elm match { case b: Bits => Array((idx.toString, b)) @@ -152,69 +186,40 @@ class Vec[T <: Data](val gen: (Int) => T, elts: Iterable[T]) extends Aggregate w override def <>(src: Node) { src match { - case other: Vec[T] => { - for((b, o) <- self zip other.self) - b <> o - } + case other: Vec[T] => (self zip other.self) foreach {case (s, o) => s <> o} case _ => } } + def <>(src: Vec[T]) { (self zip src) foreach {case (s, o) => s <> o} } + def <>(src: Seq[T]) { (self zip src) foreach {case (s, o) => s <> o} } - def <>(src: Vec[T]) { - for((b, e) <- self zip src) - b <> e - } - - def <>(src: Iterable[T]) { - for((b, e) <- self zip src) - b <> e - } - - override protected def colonEquals[T <: Data](that: Iterable[T]): Unit = { - if (comp != null) { - comp procAssign Vec(that) - } else { + override protected def colonEquals[T <: Data](that: Seq[T]): Unit = comp match { + case Some(p) => p procAssign Vec(that) + case None => { def unidirectional[U <: Data](who: Iterable[(String, Bits)]) = who.forall(_._2.dir == who.head._2.dir) - assert(size == that.size, { - ChiselError.error("Can't wire together Vecs of mismatched lengths") - }) - - assert(unidirectional(flatten), { - ChiselError.error("Cannot mix directions on left hand side of :=") - }) - - assert(unidirectional(that.flatMap(_.flatten)), { - ChiselError.error("Cannot mix directions on left hand side of :=") - }) - + assert(size == that.size, + ChiselError.error("Can't wire together Vecs of mismatched lengths")) + assert(unidirectional(flatten), + ChiselError.error("Cannot mix directions on left hand side of :=")) + assert(unidirectional(that.flatMap(_.flatten)), + ChiselError.error("Cannot mix directions on left hand side of :=")) for ((me, other) <- this zip that) me := other } } override protected def colonEquals(that: Bits): Unit = { - for (i <- 0 until length) - this(i) := that(i) - } - - // We need this special := because Iterable[T] is not a Data. - def :=[T <: Data](that: Iterable[T]): Unit = colonEquals(that) - - override def removeTypeNodes { - self foreach (_.removeTypeNodes) - } - - override def flip(): this.type = { - self foreach (_.flip) - this + for (i <- 0 until length) this(i) := that(i) } + // We need this special := because Seq[T] is not a Data. + def :=[T <: Data](that: Seq[T]): Unit = colonEquals(that) + override def removeTypeNodes { self foreach (_.removeTypeNodes) } + override def flip: this.type = { self foreach (_.flip) ; this } override def nameIt (path: String, isNamingIo: Boolean) { - if( !named - && (name.isEmpty - || (!path.isEmpty && name != path)) ) { + if( !named && (name.isEmpty || (!path.isEmpty && name != path)) ) { val prevPrefix = if (name.length > 0) name + "_" else "" name = path val prefix = if (name.length > 0) name + "_" else "" @@ -234,32 +239,13 @@ class Vec[T <: Data](val gen: (Int) => T, elts: Iterable[T]) extends Aggregate w } } - override def clone(): this.type = - Vec.tabulate(size)(gen).asInstanceOf[this.type] - //Vec(this: Seq[T]).asInstanceOf[this.type] - - override def asDirectionless(): this.type = { - self.foreach(_.asDirectionless) - this - } - - override def asOutput(): this.type = { - self.foreach(_.asOutput) - this - } - - override def asInput(): this.type = { - self.foreach(_.asInput) - this - } - - override def setIsTypeNode() { - isTypeNode = true - self foreach (_.setIsTypeNode) - } + override def cloneType: this.type = Vec.tabulate(size)(gen).asInstanceOf[this.type] //Vec(this: Seq[T]).asInstanceOf[this.type] + override def asDirectionless: this.type = { self.foreach(_.asDirectionless) ; this } + override def asOutput: this.type = { self.foreach(_.asOutput) ; this } + override def asInput: this.type = { self.foreach(_.asInput) ; this } + override def setIsTypeNode { isTypeNode = true ; self foreach (_.setIsTypeNode) } def length: Int = self.size - override val hashCode: Int = _id override def equals(that: Any): Boolean = this eq that.asInstanceOf[AnyRef] @@ -267,6 +253,8 @@ class Vec[T <: Data](val gen: (Int) => T, elts: Iterable[T]) extends Aggregate w // Return the sum of our constituent widths. override def getWidth(): Int = self.map(_.getWidth).foldLeft(0)(_ + _) + // Chisel3 - type-only nodes (no data - initialization or assignment) - used for verifying Wire() wrapping + override def isTypeOnly: Boolean = { self forall (_.isTypeOnly) } } trait VecLike[T <: Data] extends collection.IndexedSeq[T] { diff --git a/src/main/scala/Verilog.scala b/src/main/scala/Verilog.scala index 7e6bcd33..0475351b 100644 --- a/src/main/scala/Verilog.scala +++ b/src/main/scala/Verilog.scala @@ -1,5 +1,5 @@ /* - Copyright (c) 2011, 2012, 2013, 2014 The Regents of the University of + Copyright (c) 2011 - 2016 The Regents of the University of California (Regents). All Rights Reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: @@ -29,45 +29,10 @@ */ package Chisel -import Node._ -import java.io.File; -import java.io.InputStream -import java.io.OutputStream -import java.io.PrintStream -import scala.sys.process._ -import Reg._ -import ChiselError._ -import scala.collection.mutable.ArrayBuffer -import scala.collection.mutable.HashSet -import scala.collection.mutable.HashMap -import scala.collection.mutable.LinkedHashMap +import scala.collection.mutable.{ArrayBuffer, HashSet, HashMap, LinkedHashMap} import scala.collection.immutable.ListSet -object VerilogBackend { - - val keywords = Set[String]( - "always", "and", "assign", "attribute", "begin", "buf", "bufif0", "bufif1", - "case", "casex", "casez", "cmos", "deassign", "default", "defparam", - "disable", "edge", "else", "end", "endattribute", "endcase", "endfunction", - "endmodule", "endprimitive", "endspecify", "endtable", "endtask", "event", - "for", "force", "forever", "fork", "function", "highz0", "highz1", "if", - "ifnone", "initial", "inout", "input", "integer", "initvar", "join", - "medium", "module", "large", "macromodule", "nand", "negedge", "nmos", - "nor", "not", "notif0", "notif1", "or", "output", "parameter", "pmos", - "posedge", "primitive", "pull0", "pull1", "pulldown", "pullup", "rcmos", - "real", "realtime", "reg", "release", "repeat", "rnmos", "rpmos", "rtran", - "rtranif0", "rtranif1", "scalared", "signed", "small", "specify", - "specparam", "strength", "strong0", "strong1", "supply0", "supply1", - "table", "task", "time", "tran", "tranif0", "tranif1", "tri", "tri0", - "tri1", "triand", "trior", "trireg", "unsigned", "vectored", "wait", - "wand", "weak0", "weak1", "while", "wire", "wor", "xnor", "xor", - "SYNTHESIS", "PRINTF_COND", "VCS") - - var traversalIndex = 0 -} - class VerilogBackend extends Backend { - val keywords = VerilogBackend.keywords override val needsLowering = Set("PriEnc", "OHToUInt", "Log2") override def isEmittingComponents: Boolean = true @@ -84,15 +49,11 @@ class VerilogBackend extends Backend { if (!memConfs.contains(configStr)) { /* Generates memory that are different in (depth, width, ports). All others, we return the previously generated name. */ - val compName = if (mem.component != null) { - (if( !mem.component.moduleName.isEmpty ) { - Backend.moduleNamePrefix + mem.component.moduleName - } else { - extractClassName(mem.component) - } + "_") + val compName = (if( !mem.component.moduleName.isEmpty ) { + Driver.moduleNamePrefix + mem.component.moduleName } else { - Backend.moduleNamePrefix - } + extractClassName(mem.component) + }) + "_" // Generate a unique name for the memory module. val candidateName = compName + emitRef(mem) val memModuleName = if( compIndices contains candidateName ) { @@ -110,7 +71,7 @@ class VerilogBackend extends Backend { def emitWidth(node: Node): String = { val w = node.needWidth() - if (w == 1) "" else "[" + (w-1) + ":0]" + if (w == 1) "" else s"[${w-1}:0]" } override def emitTmp(node: Node): String = @@ -128,250 +89,226 @@ class VerilogBackend extends Backend { private def emitLit(x: BigInt): String = emitLit(x, x.bitLength + (if (x < 0) 1 else 0)) - private def emitLit(x: BigInt, w: Int): String = { - val unsigned = if (x < 0) (BigInt(1) << w) + x else x - require(unsigned >= 0) - w + "'h" + unsigned.toString(16) + private def emitLit(x: BigInt, w: Int, base10: Boolean = false): String = { + val unsigned = if (x < 0) (BigInt(1) << w) + x else x // drop leading 1's on negative numbers to get the necessary width + require(unsigned >= 0) // only positive numbers are used for constants + if (base10) unsigned.toString(10) else w + "'h" + unsigned.toString(16) // write base 10 or hex constant } // $random only emits 32 bits; repeat its result to fill the Node private def emitRand(node: Node): String = - "{" + ((node.needWidth()+31)/32) + "{$random}}" + "{" + ((node.needWidth() + 31)/32) + "{$random}}" def emitPortDef(m: MemAccess, idx: Int): String = { - def str(prefix: String, ports: (String, String)*): String = - ports.toList.filter(_._2 != null) - .map(p => " ." + prefix + idx + p._1 + "(" + p._2 + ")") - .reduceLeft(_ + ",\n" + _) + def str(prefix: String, ports: (String, Option[String])*): String = + ports.toList filter (_._2 != None) map { + case (x, y) => List(" .", prefix, idx, x, "(", y.get, ")").mkString + } mkString ",\n" m match { case r: MemSeqRead => - val addr = ("A", emitRef(r.addr)) - val en = ("E", emitRef(r.cond)) - val out = ("O", emitTmp(r)) + val addr = ("A", Some(emitRef(r.addr))) + val en = ("E", Some(emitRef(r.cond))) + val out = ("O", Some(emitTmp(r))) str("R", addr, en, out) case w: MemWrite => - val addr = ("A", emitRef(w.addr)) - val en = ("E", emitRef(w.cond)) - val data = ("I", emitRef(w.data)) - val mask = ("M", if (w.isMasked) emitRef(w.mask) else null) + val addr = ("A", Some(emitRef(w.addr))) + val en = ("E", Some(emitRef(w.cond))) + val data = ("I", Some(emitRef(w.data))) + val mask = ("M", if (w.isMasked) Some(emitRef(w.mask)) else None) str("W", addr, en, data, mask) case rw: MemReadWrite => val (r, w) = (rw.read, rw.write) - val addr = ("A", emitRef(w.cond) + " ? " + emitRef(w.addr) + " : " + emitRef(r.addr)) - val en = ("E", emitRef(r.cond) + " || " + emitRef(w.cond)) - val write = ("W", emitRef(w.cond)) - val data = ("I", emitRef(w.data)) - val mask = ("M", if (w.isMasked) emitRef(w.mask) else null) - val out = ("O", emitTmp(r)) + val addr = ("A", Some(emitRef(w.cond) + " ? " + emitRef(w.addr) + " : " + emitRef(r.addr))) + val en = ("E", Some(emitRef(r.cond) + " || " + emitRef(w.cond))) + val write = ("W", Some(emitRef(w.cond))) + val data = ("I", Some(emitRef(w.data))) + val mask = ("M", if (w.isMasked) Some(emitRef(w.mask)) else None) + val out = ("O", Some(emitTmp(r))) str("RW", addr, en, write, data, mask, out) } } - def emitDef(c: Module): String = { - val spacing = (if(c.verilog_parameters != "") " " else ""); - var res = " " + c.moduleName + " " + c.verilog_parameters + spacing + c.name + "("; - if (c.clocks.length > 0) { - res = res + (c.clocks).map(x => "." + emitRef(x) + "(" + emitRef(x) + ")").reduceLeft(_ + ", " + _) - } - if (c.resets.size > 0 ) { - if (c.clocks.length > 0) res = res + ", " - res = res + (c.resets.values.toList).map(x => "." + emitRef(x) + "(" + emitRef(x.inputs(0)) + ")").reduceLeft(_ + ", " + _) + // Add trailing comma to port declarations. + def delimitUncommentedPortDecls(portDecls: ArrayBuffer[StringBuilder]) { + val uncommentedPorts = portDecls.filter(!_.result.contains("//")) + if (!uncommentedPorts.isEmpty) { + uncommentedPorts.init map (_ append ",") } - var isFirst = true; - val portDecs = new ArrayBuffer[StringBuilder] - for ((n, w) <- c.wires) { - if(n != "reset" && n != Driver.implicitReset.name) { - var portDec = "." + n + "( "; - w match { - case io: Bits => - if (io.dir == INPUT) { // if reached, then input has consumers - if (io.inputs.length == 0) { - // if (Driver.saveConnectionWarnings) { - // ChiselError.warning("" + io + " UNCONNECTED IN " + io.component); - // } removed this warning because pruneUnconnectedIOs should have picked it up - portDec = "//" + portDec - } else if (io.inputs.length > 1) { - if (Driver.saveConnectionWarnings) { - ChiselError.warning("" + io + " CONNECTED TOO MUCH " + io.inputs.length); - } - portDec = "//" + portDec - /* } else if (!c.isWalked.contains(w)){ - if (Driver.saveConnectionWarnings) { - ChiselError.warning(" UNUSED INPUT " + io + " OF " + c + " IS REMOVED"); - } - portDec = "//" + portDec // I don't think this is necessary */ - } else { - portDec += emitRef(io.inputs(0)); - } - } else if(io.dir == OUTPUT) { - if (io.consumers.size == 0) { - // if (Driver.saveConnectionWarnings) { - // ChiselError.warning("" + io + " UNCONNECTED IN " + io.component + " BINDING " + c.findBinding(io)); - // } removed this warning because pruneUnconnectedsIOs should have picked it up - portDec = "//" + portDec - } else { - c.parent.findBinding(io) match { - case None => { - if (Driver.saveConnectionWarnings) { - ChiselError.warning("" + io + "(" + io.component + ") OUTPUT UNCONNECTED (" + - io.consumers.size + ") IN " + c.parent) - } - portDec = "//" + portDec - } - case Some(consumer) => { - if (io.prune) - portDec = "//" + portDec + emitRef(consumer) - else - portDec += emitRef(consumer); // TODO: FIX THIS? - } - } - } - } - } - portDec += " )" - portDecs += new StringBuilder(portDec) - } - } - val uncommentedPorts = portDecs.filter(!_.result.contains("//")) - uncommentedPorts.slice(0, uncommentedPorts.length-1).map(_.append(",")) - portDecs.map(_.insert(0, " ")) - if (c.clocks.length > 0 || c.resets.size > 0) res += ",\n" else res += "\n" - res += portDecs.map(_.result).reduceLeft(_ + "\n" + _) - res += "\n );\n"; - if (c.wires.map(_._2.driveRand).reduceLeft(_ || _)) { - res += if_not_synthesis - for ((n, w) <- c.wires) { - if (w.driveRand) { - res += " assign " + c.name + "." + n + " = " + emitRand(w) + ";\n" + } + + def emitDef(c: Module): StringBuilder = { + val spacing = (if(c.verilog_parameters != "") " " else "") + var res = new StringBuilder + List(" ", c.moduleName, " ", c.verilog_parameters, spacing, c.name, "(") addString res + def getMapClk(x : Clock) : String = if ( c.isInstanceOf[BlackBox] ) c.asInstanceOf[BlackBox].mapClock(emitRef(x)) else emitRef(x) + c.clocks map (x => "." + getMapClk(x) + "(" + emitRef(x) + ")") addString (res, ", ") + if (!c.clocks.isEmpty && !c.resets.isEmpty) res append ", " + c.resets.values map (x => "." + emitRef(x) + "(" + emitRef(x.inputs(0)) + ")") addString (res, ", ") + var isFirst = true + val portDecs = ArrayBuffer[StringBuilder]() + for ((n, io) <- c.wires if n != "reset" && n != Driver.implicitReset.name) { + val portDec = new StringBuilder("." + n + "( ") + io.dir match { + case INPUT if io.inputs.isEmpty => + // if (Driver.saveConnectionWarnings) { + // ChiselError.warning("" + io + " UNCONNECTED IN " + io.component) + // } removed this warning because pruneUnconnectedIOs should have picked it up + portDec insert (0, "//") + case INPUT if io.inputs.size > 1 => + if (Driver.saveConnectionWarnings) { + ChiselError.warning("" + io + " CONNECTED TOO MUCH " + io.inputs.length) + } + portDec insert (0, "//") + /* case INPUT if !(c.isWalked conatins io) => + if (Driver.saveConnectionWarnings) { + ChiselError.warning(" UNUSED INPUT " + io + " OF " + c + " IS REMOVED") + } + portDec = "//" + portDec // I don't think this is necessary */ + case INPUT => + portDec append emitRef(io.inputs(0)) + case OUTPUT if io.consumers.isEmpty => + // if (Driver.saveConnectionWarnings) { + // ChiselError.warning("" + io + " UNCONNECTED IN " + io.component + " BINDING " + c.findBinding(io)) + // } removed this warning because pruneUnconnectedsIOs should have picked it up + portDec insert (0, "//") + case OUTPUT => c.parent.findBinding(io) match { + case None => + if (Driver.saveConnectionWarnings) { + ChiselError.warning("" + io + "(" + io.component + ") OUTPUT UNCONNECTED (" + + io.consumers.size + ") IN " + c.parent) } + portDec insert (0, "//") + case Some(consumer) => + if (io.prune) portDec insert (0, "//") + portDec append emitRef(consumer) } } - res += endif_not_synthesis - } + portDec append " )" + portDecs += portDec + } + // Add trailing ',' to uncommented portDecs + delimitUncommentedPortDecls(portDecs) + portDecs map (_ insert (0, " ")) + if (!c.clocks.isEmpty || !c.resets.isEmpty) res append ",\n" else res append "\n" + res append (portDecs addString (new StringBuilder, "\n")) + res append "\n );\n" + val driveRandPorts = c.wires filter (_._2.driveRand) + if (!driveRandPorts.isEmpty) res append if_not_synthesis + driveRandPorts map { case (n ,w) => + List(" assign ", c.name, ".", n, " = ", emitRand(w), ";\n").mkString } addString res + if (!driveRandPorts.isEmpty) res append endif_not_synthesis res } override def emitDef(node: Node): String = { - val res = - node match { + val res = node match { + case x: Bits if x.isIo && x.dir == INPUT => "" + case x: Bits if node.inputs.isEmpty => + if (Driver.saveConnectionWarnings) ChiselError.warning("UNCONNECTED " + node + " IN " + node.component) + List(" assign ", emitTmp(node), " = ", emitRand(node), ";\n").mkString case x: Bits => - if (x.isIo && x.dir == INPUT) { - "" - } else { - if (node.inputs.length == 0) { - ChiselError.warning("UNCONNECTED " + node + " IN " + node.component) - " assign " + emitTmp(node) + " = " + emitRand(node) + ";\n" - } else if (node.inputs(0) == null) { - ChiselError.warning("UNCONNECTED WIRE " + node + " IN " + node.component) - " assign " + emitTmp(node) + " = " + emitRand(node) + ";\n" - } else { - " assign " + emitTmp(node) + " = " + emitRef(node.inputs(0)) + ";\n" - } - } + List(" assign ", emitTmp(node), " = ", emitRef(node.inputs(0)), ";\n").mkString case x: Mux => - " assign " + emitTmp(x) + " = " + emitRef(x.inputs(0)) + " ? " + emitRef(x.inputs(1)) + " : " + emitRef(x.inputs(2)) + ";\n" - + List(" assign ", emitTmp(x), " = ", emitRef(x.inputs(0)), " ? ", emitRef(x.inputs(1)), " : ", emitRef(x.inputs(2)), ";\n").mkString + + case o: Op if o.op == "##" => + List(" assign ", emitTmp(o), " = ", "{", emitRef(node.inputs(0)), ", ", emitRef(node.inputs(1)), "}", ";\n").mkString + case o: Op if o.inputs.size == 1 => + List(" assign ", emitTmp(o), " = ", o.op, " ", emitRef(node.inputs(0)), ";\n").mkString + case o: Op if o.op == "s*s" || o.op == "s*u" || o.op == "s%s" || o.op == "s/s" => + List(" assign ", emitTmp(o), " = ", "$signed(", emitRef(node.inputs(0)), ") ", o.op(1), " $signed(", emitRef(node.inputs(1)), ")", ";\n").mkString + case o: Op if o.op == "s<" || o.op == "s<=" => + List(" assign ", emitTmp(o), " = ", "$signed(", emitRef(node.inputs(0)), ") ", o.op.tail, " $signed(", emitRef(node.inputs(1)), ")", ";\n").mkString + case o: Op if o.op == "s>>" => + List(" assign ", emitTmp(o), " = ", "$signed(", emitRef(node.inputs(0)), ") >>> ", emitRef(node.inputs(1)), ";\n").mkString case o: Op => - val c = o.component; - " assign " + emitTmp(o) + " = " + - (if (o.op == "##") { - "{" + emitRef(node.inputs(0)) + ", " + emitRef(node.inputs(1)) + "}" - } else if (node.inputs.length == 1) { - o.op + " " + emitRef(node.inputs(0)) - } else if (o.op == "s*s" || o.op == "s*u" || o.op == "s%s" || o.op == "s/s") { - "$signed(" + emitRef(node.inputs(0)) + ") " + o.op(1) + " $signed(" + emitRef(node.inputs(1)) + ")" - } else if (o.op == "s<" || o.op == "s<=") { - "$signed(" + emitRef(node.inputs(0)) + ") " + o.op.tail + " $signed(" + emitRef(node.inputs(1)) + ")" - } else if (o.op == "s>>") { - "$signed(" + emitRef(node.inputs(0)) + ") >>> " + emitRef(node.inputs(1)) - } else { - emitRef(node.inputs(0)) + " " + o.op + " " + emitRef(node.inputs(1)) - }) + ";\n" + List(" assign ", emitTmp(o), " = ", emitRef(node.inputs(0)), " ", o.op, " ", emitRef(node.inputs(1)), ";\n").mkString case x: Extract => node.inputs.tail.foreach(x.validateIndex) - val gotWidth = node.inputs(0).needWidth() - if (node.inputs.length < 3) { - if(gotWidth > 1) { - " assign " + emitTmp(node) + " = " + emitRef(node.inputs(0)) + "[" + emitRef(node.inputs(1)) + "];\n" + val source = emitRef(node.inputs(0)) + val hi = node.inputs(1) match { // if the high bit is a literal, we want it in base 10. ex io_something[7:3] + case x: Literal => emitLit(x.value, x.width, true) + case x => emitRef(x)} + List(" assign " + emitTmp(node) + " = ", + // Is this a no-op - extract all the source bits. + if (x.isNop) { + source + } else + // Is source a single bit? - no need to extract + if (node.inputs(0).needWidth == 1) { + source + } else + // Is this a single bit extraction? + if (x.isOneBit) { + List(source, "[", hi, "]").mkString } else { - " assign " + emitTmp(node) + " = " + emitRef(node.inputs(0)) + ";\n" - } - } else { - if(gotWidth > 1) { - " assign " + emitTmp(node) + " = " + emitRef(node.inputs(0)) + "[" + emitRef(node.inputs(1)) + ":" + emitRef(node.inputs(2)) + "];\n" - } else { - " assign " + emitTmp(node) + " = " + emitRef(node.inputs(0)) + ";\n" - } - } - - case m: Mem[_] => - if(!m.isInline) { - def gcd(a: Int, b: Int) : Int = { if(b == 0) a else gcd(b, a%b) } - def find_gran(x: Node) : Int = { - if (x.isInstanceOf[Literal]) - return x.needWidth() - else if (x.isInstanceOf[UInt]) - return if (x.inputs.length>0) find_gran(x.inputs(0)) else 1 - else if (x.isInstanceOf[Mux]) - return gcd(find_gran(x.inputs(1)), find_gran(x.inputs(2))) - else if (x.isInstanceOf[Op]) - return (x.inputs.map(find_gran(_))).reduceLeft(_ max _) - else - return 1 - } - val mask_writers = m.writeAccesses.filter(_.isMasked) - val mask_grans = mask_writers.map(x => find_gran(x.mask)) - val mask_gran = if (!mask_grans.isEmpty && mask_grans.forall(_ == mask_grans(0))) mask_grans(0) else 1 - val configStr = - (" depth " + m.n + - " width " + m.needWidth() + - " ports " + m.ports.map(_.getPortType).reduceLeft(_ + "," + _) + - (if (mask_gran != 1) " mask_gran " + mask_gran else "") + - "\n") - val name = getMemName(m, configStr) - ChiselError.info("MEM " + name) - - val clk = " .CLK(" + emitRef(m.clock) + ")" - val portdefs = for (i <- 0 until m.ports.size) - yield emitPortDef(m.ports(i), i) - " " + name + " " + emitRef(m) + " (\n" + - (clk +: portdefs).reduceLeft(_ + ",\n" + _) + "\n" + - " );\n" - } else { - "" - } - case m: MemRead => - if (m.mem.isInline) { - " assign " + emitTmp(node) + " = " + emitRef(m.mem) + "[" + emitRef(m.addr) + "];\n" - } else { - "" + // We have three inputs. + val lo = node.inputs(2) match { // if the low bit is a literal, we want it in base 10. ex io_something[7:3] + case x: Literal => emitLit(x.value, x.width, true) + case x => emitRef(x)} + // Are hi and lo constant expressions? + if (x.isStaticWidth) { + List(source, "[", hi , ":", lo, "]").mkString + } else { + // The extraction operands are different and at least one of them is not an integer. + // We need to generate the equivalent sequence of shifts and masks. + val resultWidth = node.needWidth + List( "(", source, " >> ", lo, ") & ((", resultWidth, "'h1 << (", hi, " - ", lo, " + 1)) - 1)").mkString + } + } + , ";\n").mkString + + case m: Mem[_] if !m.isInline => + def gcd(a: Int, b: Int) : Int = { if(b == 0) a else gcd(b, a%b) } + def find_gran(x: Node) : Int = x match { + case _: Literal => x.needWidth() + case _: UInt => if (x.inputs.isEmpty) 1 else find_gran(x.inputs(0)) + case _: Mux => gcd(find_gran(x.inputs(1)), find_gran(x.inputs(2))) + case _: Op => x.inputs map (find_gran(_)) reduceLeft (_ max _) + case _ => 1 } + val mask_writers = m.writeAccesses.filter(_.isMasked) + val mask_grans = mask_writers.map(x => find_gran(x.mask)) + val mask_gran = if (!mask_grans.isEmpty && mask_grans.forall(_ == mask_grans(0))) mask_grans(0) else 1 + val configStr = List( + " depth ", m.n, + " width ", m.needWidth(), + " ports ", m.ports map (_.getPortType) mkString ",", + (if (mask_gran != 1) " mask_gran " + mask_gran else ""), "\n").mkString + val name = getMemName(m, configStr) + ChiselError.info("MEM " + name) + + val clk = List(" .CLK(", emitRef(m.clock.get), ")").mkString + val portdefs = m.ports.zipWithIndex map { case (p, i) => emitPortDef(p, i) } + List(" ", name, " ", emitRef(m), " (\n", (clk +: portdefs) mkString ",\n", "\n", " );\n").mkString + + case m: MemRead if m.mem.isInline => + List(" assign ", emitTmp(node), " = ", emitRef(m.mem), "[", emitRef(m.addr), "];\n").mkString case r: ROMRead => - val inits = new StringBuilder - for ((i, v) <- r.rom.sparseLits) - inits append s" ${i}: ${emitRef(r)} = ${emitRef(v)};\n" - s" always @(*) case (${emitRef(r.inputs.head)})\n" + - inits + - s" default: begin\n" + - s" ${emitRef(r)} = ${r.needWidth()}'bx;\n" + - if_not_synthesis + - s" ${emitRef(r)} = ${emitRand(r)};\n" + - endif_not_synthesis + - s" end\n" + - " endcase\n" + val inits = r.rom.sparseLits map { case (i, v) => + s" ${i}: ${emitRef(r)} = ${emitRef(v)};\n" } addString (new StringBuilder) + (List(s" always @(*) case (${emitRef(r.inputs.head)})\n", + inits.result, + s" default: begin\n", + s" ${emitRef(r)} = ${r.needWidth()}'bx;\n", + if_not_synthesis, + s" ${emitRef(r)} = ${emitRand(r)};\n", + endif_not_synthesis, + s" end\n", + " endcase\n") addString (new StringBuilder)).result case s: Sprintf => - " always @(*) $sformat(" + emitTmp(s) + ", " + s.args.map(emitRef _).foldLeft(CString(s.format))(_ + ", " + _) + ");\n" + List(" always @(*) $sformat(", emitTmp(s), ", ", (CString(s.format) +: (s.args map (emitRef _))) mkString ", ", ");\n").mkString case _ => "" } - (if (node.prune && res != "") "//" else "") + res + List(if (node.prune && res != "") "//" else "", res).mkString } def emitDecBase(node: Node, wire: String = "wire"): String = @@ -383,15 +320,10 @@ class VerilogBackend extends Backend { val gotWidth = node.needWidth() val res = node match { - case x: Bits => - if(!x.isIo) { - emitDecBase(node) - } else { - "" - } + case x: Bits if x.isIo => "" case _: Assert => - " reg" + "[" + (gotWidth-1) + ":0] " + emitRef(node) + ";\n" + emitDecReg(node) case _: Reg => emitDecReg(node) @@ -402,12 +334,9 @@ class VerilogBackend extends Backend { case _: ROMRead => emitDecReg(node) + case m: Mem[_] if !m.isInline => "" case m: Mem[_] => - if (m.isInline) { - " reg [" + (m.needWidth()-1) + ":0] " + emitRef(m) + " [" + (m.n-1) + ":0];\n" - } else { - "" - } + s" reg ${emitWidth(m)} ${emitRef(m)} [${m.n-1}:0];\n" case x: MemAccess => x.referenced = true @@ -420,18 +349,15 @@ class VerilogBackend extends Backend { case _ => emitDecBase(node) } - (if (node.prune && res != "") "//" else "") + res + List(if (node.prune && res != "") "//" else "", res).mkString } def emitInit(node: Node): String = node match { case r: Reg => - " " + emitRef(r) + " = " + emitRand(r) + ";\n" - case m: Mem[_] => - if (m.isInline) - " for (initvar = 0; initvar < " + m.n + "; initvar = initvar+1)\n" + - " " + emitRef(m) + "[initvar] = " + emitRand(m) + ";\n" - else - "" + List(" ", emitRef(r), " = ", emitRand(r), ";\n").mkString + case m: Mem[_] if m.isInline => + " for (initvar = 0; initvar < " + m.n + "; initvar = initvar+1)\n" + + " " + emitRef(m) + "[initvar] = " + emitRand(m) + ";\n" case a: Assert => " " + emitRef(a) + " = 1'b0;\n" case _ => @@ -439,297 +365,105 @@ class VerilogBackend extends Backend { } def genHarness(c: Module, name: String) { - val harness = createOutputFile(name + "-harness.v"); - val printNodes = for ((n, io) <- c.wires ; if io.dir == OUTPUT) yield io - val scanNodes = for ((n, io) <- c.wires ; if io.dir == INPUT) yield io + val harness = createOutputFile(name + "-harness.v") + val ins = for ((n, io) <- c.wires if io.dir == INPUT) yield io + val outs = for ((n, io) <- c.wires if io.dir == OUTPUT) yield io val mainClk = Driver.implicitClock - val clocks = ListSet(mainClk) ++ c.clocks - val resets = c.resets.unzip._2.toList - - harness.write("module test;\n") - for (node <- scanNodes) { - val gotWidth = node.needWidth() - harness.write(" reg [" + (gotWidth-1) + ":0] " + emitRef(node) + ";\n") - } - for (node <- printNodes) { - val gotWidth = node.needWidth() - harness.write(" wire [" + (gotWidth-1) + ":0] " + emitRef(node) + ";\n") - } - for (rst <- resets) - harness.write(" reg %s;\n".format(rst.name)) - - // Diffent code generation for clocks - if (Driver.isCompiling) { - harness.write(" reg %s = 0;\n".format(mainClk.name)) - if (clocks.size > 1) { - for (clk <- clocks) { - val clkLength = - if (clk.srcClock == null) "0" else - clk.srcClock.name + "_length " + clk.initStr - harness.write(" integer %s_length = %s;\n".format(clk.name, clkLength)) - harness.write(" integer %s_cnt = 0;\n".format(clk.name)) - harness.write(" reg %s_fire = 0;\n".format(clk.name)) - } - } - harness.write(" always #`CLOCK_PERIOD %s = ~%s;\n\n".format(mainClk.name, mainClk.name)) - } else { - for (clk <- clocks) { - val clkLength = - if (clk.srcClock == null) "`CLOCK_PERIOD" else - clk.srcClock.name + "_length " + clk.initStr - harness.write(" reg %s = 1;\n".format(clk.name)) - harness.write(" parameter %s_length = %s;\n".format(clk.name, clkLength)) - } - for (clk <- clocks) { - harness.write(" always #%s_length %s = ~%s;\n".format(clk.name, clk.name, clk.name)) - } - } - - harness.write(" /*** DUT instantiation ***/\n") - harness.write(" " + c.moduleName + "\n") - harness.write(" " + c.name + "(\n") - if (Driver.isCompiling) { - if (c.clocks.size == 1) { - harness.write(" .%s(%s),\n".format(mainClk.name, mainClk.name)) - } else { - for (clk <- c.clocks) - harness.write(" .%s(%s && %s_fire),\n".format( - clk.name, mainClk.name, clk.name) - ) - } - } else { - for (clk <- c.clocks) - harness.write(" .%s(%s),\n".format(clk.name, clk.name)) - } - for (rst <- resets) - harness.write(" .%s(%s),\n".format(rst.name, rst.name)) - var first = true - for (node <- (scanNodes ++ printNodes)) - if(node.isIo && node.component == c) { - if (first) { - harness.write(" ." + emitRef(node) + "(" + emitRef(node) + ")") - first = false - } else { - harness.write(",\n ." + emitRef(node) + "(" + emitRef(node) + ")") - } - } - harness.write("\n") - harness.write(" );\n\n") - - // collect Chisel nodes for VCD dump - val dumpvars = new ArrayBuffer[Node] - for (m <- Driver.components ; node <- m.nodes ; if node.isInVCD) { - node match { - case io: Bits if m != c => { - var included = true - if (io.dir == INPUT) { - if (io.inputs.length == 0 || io.inputs.length > 1) - included = false - } - else if (io.dir == OUTPUT) { - if (io.consumers.size == 0 || m.parent.findBinding(io) == None || io.prune) - included = false - } - if (included) dumpvars += io - } - case _ => dumpvars += node - } - } - - harness.write(" /*** VCD / VPD dumps ***/\n") - harness.write(" initial begin\n") - if (Driver.isDebug) { - harness.write(" /*** Debuggin with VPD dump ***/\n") - harness.write(" $vcdplusfile(\"%s.vpd\");\n".format(ensureDir(Driver.targetDir)+c.name)) - harness.write(" $vcdpluson(0, %s);\n".format(c.name)) - if (Driver.isVCDMem) harness.write(" $vcdplusmemon;\n") - } - if (!Driver.isDebug && Driver.isVCD) { - harness.write(" /*** VCD dump ***/\n") - var first = true - for (dumpvar <- dumpvars) { - val pathName = dumpvar.component.getPathName(".") + "." + emitRef(dumpvar) - harness.write(" $dumpvars(1, %s);\n".format(pathName)) - } - harness.write(" $dumpfile(\"%s.vcd\");\n".format(ensureDir(Driver.targetDir)+c.name)) - harness.write(" $dumpon;\n") - } - harness.write(" end\n\n") - - if (Driver.isCompiling) { - harness write harnessAPIs(mainClk, clocks, resets) - } else { - harness write harnessBase(mainClk, resets, scanNodes, printNodes) - } - harness.write("endmodule\n") - - harness.close(); - } - - def harnessAPIs (mainClk: Clock, clocks: ListSet[Clock], resets: List[Bool]) = { - val apis = new StringBuilder - - apis.append("\n /*** API variables ***/\n") - apis.append(" reg[20*8:0] cmd; // API command\n") - apis.append(" reg[1000*8:0] node; // Chisel node name;\n") - apis.append(" reg[255:0] value; // 'poked' value\n") - apis.append(" integer offset; // mem's offset\n") - apis.append(" integer steps; // number of steps\n") - apis.append(" integer delta; // number of steps\n") - apis.append(" integer min = (1 << 31 -1);\n") - apis.append(" reg is_stale = 0;\n") - - apis.append("\n integer count;\n") - - def fscanf(form: String, args: String*) = - "count = $fscanf('h80000000, \"%s\", %s);\n".format(form, (args.tail foldLeft args.head) (_ + ", " + _)) - def display(form: String, args: String*) = - "$display(\"%s\", %s);\n".format(form, (args.tail foldLeft args.head) (_ + ", " + _)) - - apis.append(" initial begin\n") - apis.append(" /*** API interpreter ***/\n") - apis.append(" forever begin\n") - for (rst <- resets) - apis.append(" %s = 0;\n".format(rst.name)) - apis.append(" "+ fscanf("%s", "cmd")) - apis.append(" case (cmd)\n") - - apis.append(" // < reset >\n") - apis.append(" // inputs: # cycles the reset consumes\n") - apis.append(" // return: none\n") - apis.append(" \"reset\": begin\n") - apis.append(" " + fscanf("%d", "steps")) - for (rst <- resets) - apis.append(" %s = 1;\n".format(rst.name)) - apis.append(" repeat (steps) @(negedge %s) begin\n".format(mainClk.name)) - apis.append(" delta = delta + min;\n") + val clocks = Driver.clocks + val resets = c.resets.values.toList + + harness write "module test;\n" + ins foreach (node => harness write " reg[%d:0] %s = 0;\n".format(node.needWidth()-1, emitRef(node))) + outs foreach (node => harness write " wire[%d:0] %s;\n".format(node.needWidth()-1, emitRef(node))) + clocks foreach (clk => harness write " reg %s = 0;\n".format(clk.name)) + resets foreach (rst => harness write " reg %s = 1;\n".format(rst.name)) + clocks foreach (clk => harness write " integer %s_len;\n".format(clk.name)) + clocks foreach (clk => harness write " always #%s_len %s = ~%s;\n".format(clk.name, clk.name, clk.name)) if (clocks.size > 1) { - for (clk <- clocks) - apis.append(" %s_fire = 1;\n".format(clk.name, clk.name)) - } - apis.append(" end") - apis.append(" // return delta\n") - apis.append(" " + display("%1d", "delta")) - apis.append(" delta = 0;\n") - for (rst <- resets) - apis.append(" %s = 0;\n".format(rst.name)) - apis.append(" end\n") - - apis.append(" // < wire_peek >\n") - apis.append(" // inputs: wire's name\n") - apis.append(" // return: wire's value\n") - apis.append(" \"wire_peek\": begin\n") - apis.append(" if (is_stale) #0.1 is_stale = 0;\n") - apis.append(" " + fscanf("%s", "node")) - apis.append(" $wire_peek(node);\n") - apis.append(" end\n") - - apis.append(" // < mem_peek >\n") - apis.append(" // inputs: mem's name\n") - apis.append(" // return: mem's value\n") - apis.append(" \"mem_peek\": begin\n") - apis.append(" if (is_stale) #0.1 is_stale = 0;\n") - apis.append(" " + fscanf("%s %d", "node", "offset")) - apis.append(" $mem_peek(node, offset);\n") - apis.append(" end\n") - - apis.append(" // < wire_poke >\n") - apis.append(" // inputs: wire's name\n") - apis.append(" // return: \"ok\" or \"error\"\n") - apis.append(" \"wire_poke\": begin\n") - apis.append(" " + fscanf("%s 0x%x", "node", "value")) - apis.append(" $wire_poke(node, value);\n") - apis.append(" is_stale = 1;\n") - apis.append(" end\n") - - apis.append(" // < mem_poke >\n") - apis.append(" // inputs: wire's name\n") - apis.append(" // return: \"ok\" or \"error\"\n") - apis.append(" \"mem_poke\": begin\n") - apis.append(" " + fscanf("%s %d 0x%x", "node", "offset", "value")) - apis.append(" $mem_poke(node, offset, value);\n") - apis.append(" is_stale = 1;\n") - apis.append(" end\n") - - apis.append(" // < step > \n") - apis.append(" // inputs: # cycles\n") - apis.append(" // return: # cycles the target will proceed\n") - apis.append(" \"step\": begin\n") - apis.append(" " + fscanf("%d", "steps")) - apis.append(" if (is_stale) #0.1 is_stale = 0;\n") - apis.append(" repeat (steps) @(negedge %s) begin\n".format(mainClk.name)) - if (clocks.size > 1) { - for (clk <- clocks) - apis.append(" if (%s_length < min) min = %s_cnt;\n".format(clk.name, clk.name)) - for (clk <- clocks) - apis.append(" %s_cnt = %s_cnt - min;\n".format(clk.name, clk.name)) - for (clk <- clocks) { - apis.append(" if (%s_cnt == 0) %s_fire = 1;\n".format(clk.name, clk.name)) - apis.append(" else %s_fire = 0;\n".format(clk.name)) - } - for (clk <- clocks) - apis.append(" if (%s_cnt == 0) %s_cnt = %s_length;\n".format(clk.name, clk.name, clk.name)) - } - apis.append(" delta = delta + min;\n") - apis.append(" end\n") - apis.append(" // return delta\n") - apis.append(" " + display("%1d", "delta")) - apis.append(" delta = 0;\n") - apis.append(" end\n") + harness write " integer min = 1 << 31 - 1;\n\n" + clocks foreach (clk => harness write " integer %s_cnt;\n".format(clk.name)) + } + harness write " reg vcdon = 0;\n" + harness write " reg [1023:0] vcdfile = 0;\n" + harness write " reg [1023:0] vpdfile = 0;\n" + + harness write "\n /*** DUT instantiation ***/\n" + harness write " %s %s(\n".format(c.moduleName, c.name) + c.clocks foreach (clk => harness write " .%s(%s),\n".format(clk.name, clk.name)) + resets foreach (rst => harness write " .%s(%s),\n".format(rst.name, rst.name)) + + harness write ((ins ++ outs) map (node => " .%s(%s)".format(emitRef(node), emitRef(node))) mkString ",\n") + harness write ");\n\n" + + harness write " initial begin\n" + clocks foreach (clk => clk.srcClock match { + case None => harness write " %s_len = `CLOCK_PERIOD;\n".format(clk.name) + case Some(src) => + val initStr = "%s_len".format(src.name) + (if (src.period > clk.period) + " / " + (src.period / clk.period).round else + " * " + (clk.period / src.period).round) + harness write " %s_len = %s;\n".format(clk.name, initStr) + }) + if (clocks.size > 1) clocks foreach (clk => harness write " %s_cnt = %s_len;\n".format(clk.name, clk.name)) + harness write " $init_clks(" + (clocks map (_.name + "_len") mkString ", ") + ");\n" + harness write " $init_rsts(" + (resets map (_.name) mkString ", ") + ");\n" + harness write " $init_ins(" + (ins map (emitRef(_)) mkString ", ") + ");\n" + harness write " $init_outs(" + (outs map (emitRef(_)) mkString ", ") + ");\n" + harness write " $init_sigs(%s);\n".format(c.name) + + harness write " /*** VCD & VPD dump ***/\n" + harness write " if ($value$plusargs(\"vcdfile=%s\", vcdfile)) begin\n" + harness write " $dumpfile(vcdfile);\n" + harness write " $dumpvars(0, %s);\n".format(c.name) + harness write " $dumpoff;\n" + harness write " vcdon = 0;\n" + harness write " end\n" + harness write " if ($value$plusargs(\"vpdfile=%s\", vpdfile)) begin\n" + harness write " $vcdplusfile(vpdfile);\n" + harness write " $vcdpluson(0);\n" + harness write " $vcdplusautoflushon;\n" + harness write " end\n" + harness write " if ($test$plusargs(\"vpdmem\")) begin\n" + harness write " $vcdplusmemon;\n" + harness write " end\n" + harness write " end\n\n" if (clocks.size > 1) { - apis.append(" // \n") - apis.append(" // inputs: clocks' length\n") - apis.append(" // return: \"ok\" or \"error\"\n") - apis.append(" \"set_clocks\": begin\n") - val clkFormat = ((clocks filter (_.srcClock == null)).toList map (x => "%x")) - val clkFires = ((clocks filter (_.srcClock == null)) map (_.name + "_length")).toList - apis.append(" " + fscanf((clkFormat foldLeft "")(_ + " " + _), clkFires:_*) ) - apis.append(" " + display("%s", "\"ok\"")) - for (clk <- clocks) { - apis.append(" %s_cnt = %s_length;\n".format(clk.name, clk.name)) + harness write " initial forever begin\n" + clocks foreach (clk => harness write " if (%s_cnt < min) min = %s_cnt;\n".format(clk.name, clk.name)) + clocks foreach (clk => harness write " %s_cnt = %s_cnt - min;\n".format(clk.name, clk.name)) + clocks foreach (clk => harness write " if (%s_cnt == 0) %s_cnt = %s_len;\n".format(clk.name, clk.name, clk.name)) + harness write " #min $tick();\n" + if (!resets.isEmpty) { + harness write s""" if (vcdfile && (${resets map (_.name) mkString " || "})) begin\n""" + harness write " $dumpoff;\n" + harness write " vcdon = 0;\n" + harness write " end\n" + harness write " else if (vcdfile && !vcdon) begin\n" + harness write " $dumpon;\n" + harness write " vcdon = 1;\n" + harness write " end\n" } - apis.append(" end\n") - } - - apis.append(" // < quit>: finish simulation\n") - apis.append(" \"quit\": $finish;\n") - apis.append(" // default return: \"error\"\n") - apis.append(" default: " + display("%s", "\"error\"")) - apis.append(" endcase\n") - apis.append(" end\n\n") - - apis.append(" if (count == -1) $finish(1);\n\n") - apis.append(" end\n\n") - apis.result - } - - def harnessBase (mainClk: Clock, resets: List[Bool], scanNodes: Array[Bits], printNodes: Array[Bits]) = { - val base = new StringBuilder - val printFormat = printNodes.map(a => a.chiselName + ": 0x%x, ").fold("")((y,z) => z + " " + y) - val scanFormat = scanNodes.map(a => "%x").fold("")((y,z) => z + " " + y) - - if (!resets.isEmpty) { - base.append(" parameter reset_period = `CLOCK_PERIOD * 4;\n") - base.append(" initial begin\n") - for (rst <- resets) base.append(" %s = 1;\n".format(rst.name)) - base.append(" #reset_period;\n") - for (rst <- resets) base.append(" %s = 0;\n".format(rst.name)) - base.append(" end\n\n") - } - - base.append(" always @(posedge %s) begin\n".format(mainClk.name)) - if (!resets.isEmpty) - base.append(" if (%s)\n".format( - (resets.tail foldLeft ("!" + resets.head.name))(_ + " || !" + _.name))) - base.append(" $display(\"" + printFormat.slice(0,printFormat.length-1) + "\"") - for (node <- printNodes) { - base.append(", " + emitRef(node)) + harness write " #min ;\n" + harness write " end\n" + } else { + harness write " always @(negedge %s) begin\n".format(mainClk.name) + harness write " $tick();\n".format(mainClk.name) + if (!resets.isEmpty) { + harness write s""" if (vcdfile && (${resets map (_.name) mkString " || "})) begin\n""" + harness write " $dumpoff;\n" + harness write " vcdon = 0;\n" + harness write " end\n" + harness write " else if (vcdfile && !vcdon) begin\n" + harness write " $dumpon;\n" + harness write " vcdon = 1;\n" + harness write " end\n" + } + harness write " end\n\n" } - base.append(");\n") - base.append(" end\n\n") + harness write "endmodule\n" - base.result + harness.close } // Is the specified node synthesizeable? @@ -740,7 +474,7 @@ class VerilogBackend extends Backend { case x: Bits => if (x.isIo && x.dir == INPUT) { true - } else if (node.inputs.length > 0 && node.inputs(0) != null) { + } else if (node.inputs.length > 0) { true } else { false @@ -775,79 +509,77 @@ class VerilogBackend extends Backend { } def emitRegs(c: Module): StringBuilder = { - val res = new StringBuilder(); - val clkDomains = new HashMap[Clock, StringBuilder] - for (clock <- c.clocks) { - clkDomains += (clock -> new StringBuilder) - } + val res = new StringBuilder + val clkDomains = (c.clocks map (_ -> new StringBuilder)).toMap if (Driver.isAssert) { - for (p <- c.asserts) { - clkDomains(p.clock).append(emitAssert(p)) - } - } - for (m <- c.nodes) { - val clkDomain = clkDomains getOrElse (m.clock, null) - if (m.clock != null && clkDomain != null) - clkDomain.append(emitReg(m)) - } - for (p <- c.printfs) { - val clkDomain = clkDomains getOrElse (p.clock, null) - if (p.clock != null && clkDomain != null) - clkDomain.append(emitPrintf(p)) - } - for (clock <- c.clocks) { - val dom = clkDomains(clock) - if (!dom.isEmpty) { - if (res.isEmpty) - res.append("\n") - res.append(" always @(posedge " + emitRef(clock) + ") begin\n") - res.append(dom.result()) - res.append(" end\n") - } + c.asserts foreach (p => p.clock match { + case Some(clk) if clkDomains contains clk => + clkDomains(clk) append emitAssert(p) + case _ => + }) + } + c.nodes foreach (m => m.clock match { + case Some(clk) if clkDomains contains clk => + clkDomains(clk) append emitReg(m) + case _ => + }) + c.printfs foreach (p => p.clock match { + case Some(clk) if clkDomains contains clk => + clkDomains(clk) append emitPrintf(p) + case _ => + }) + for ((clock, dom) <- clkDomains ; if !dom.isEmpty) { + if (res.isEmpty) res.append("\n") + res.append(" always @(posedge " + emitRef(clock) + ") begin\n") + res.append(dom) + res.append(" end\n") } res } def emitPrintf(p: Printf): String = { - if_not_synthesis + - "`ifdef PRINTF_COND\n" + - " if (`PRINTF_COND)\n" + - "`endif\n" + - " if (" + emitRef(p.cond) + ")\n" + - " $fwrite(32'h80000002, " + p.args.map(emitRef _).foldLeft(CString(p.format))(_ + ", " + _) + ");\n" + - endif_not_synthesis + val file = "32'h80000002" + (List(if_not_synthesis, + "`ifdef PRINTF_COND\n", + " if (`PRINTF_COND)\n", + "`endif\n", + " if (", emitRef(p.cond), ")\n", + " $fwrite(", file, ", ", (CString(p.format) +: (p.args map (emitRef _))) mkString ", ", ");\n", + endif_not_synthesis) addString (new StringBuilder)).result } def emitAssert(a: Assert): String = { - if_not_synthesis + - " if(" + emitRef(a.reset) + ") " + emitRef(a) + " <= 1'b1;\n" + - " if(!" + emitRef(a.cond) + " && " + emitRef(a) + " && !" + emitRef(a.reset) + ") begin\n" + - " $fwrite(32'h80000002, " + CString("ASSERTION FAILED: %s\n") + ", " + CString(a.message) + ");\n" + - " $finish;\n" + - " end\n" + - endif_not_synthesis + val file = "32'h80000002" + (List(if_not_synthesis, + " if(", emitRef(a.reset), ") ", emitRef(a), " <= 1'b1;\n", + " if(!", emitRef(a.cond), " && ", emitRef(a), " && !", emitRef(a.reset), ") begin\n", + " $fwrite(", file, ", ", CString("ASSERTION FAILED: %s\n"), ", ", CString(a.message), ");\n", + " $finish;\n", + " end\n", + endif_not_synthesis) addString (new StringBuilder)).result } def emitReg(node: Node): String = { node match { case reg: Reg => - def cond(c: Node) = "if(" + emitRef(c) + ") begin" + def cond(c: Node) = List("if(", emitRef(c), ") begin").mkString def uncond = "begin" def sep = "\n " - def assign(r: Reg, x: Node) = emitRef(r) + " <= " + emitRef(x) + ";\n" + def assign(r: Reg, x: Node) = List(emitRef(r), " <= ", emitRef(x), ";\n").mkString def traverseMuxes(r: Reg, x: Node): List[String] = x match { case m: Mux => (cond(m.inputs(0)) + sep + assign(r, m.inputs(1))) :: traverseMuxes(r, m.inputs(2)) case _ => if (x eq r) Nil else List(uncond + sep + assign(r, x)) } - if (!reg.next.isInstanceOf[Mux]) " " + assign(reg, reg.next) - else " " + traverseMuxes(reg, reg.next).reduceLeft(_ + " end else " + _) + " end\n" - - case m: MemWrite => - if (m.mem.isInline) { - " if (" + emitRef(m.cond) + ")\n" + - " " + emitRef(m.mem) + "[" + emitRef(m.addr) + "] <= " + emitRef(m.data) + ";\n" - } else { - "" + reg.next match { + case _: Mux => + List(" ", traverseMuxes(reg, reg.next) mkString " end else ", " end\n").mkString + case _ => + List(" ", assign(reg, reg.next)).mkString } + + case m: MemWrite if m.mem.isInline => List( + " if (", emitRef(m.cond), ")\n", + " ", emitRef(m.mem), "[", emitRef(m.addr), "] <= ", emitRef(m.data), ";\n").mkString + case _ => "" } @@ -873,57 +605,49 @@ class VerilogBackend extends Backend { res } - def emitModuleText(c: Module): String = { - if (c.isInstanceOf[BlackBox]) - return "" + def emitModuleText(c: Module): StringBuilder = c match { + case _: BlackBox => new StringBuilder + case _ => val res = new StringBuilder() - var first = true; - var nl = ""; - if (c.clocks.length > 0 || c.resets.size > 0) - res.append((c.clocks ++ c.resets.values.toList).map(x => "input " + emitRef(x)).reduceLeft(_ + ", " + _)) - val ports = new ArrayBuffer[StringBuilder] - for ((n, w) <- c.wires) { - // if(first && !hasReg) {first = false; nl = "\n"} else nl = ",\n"; - w match { - case io: Bits => { - val prune = if (io.prune && c != Driver.topComponent) "//" else "" - if (io.dir == INPUT) { - ports += new StringBuilder(nl + " " + prune + "input " + - emitWidth(io) + " " + emitRef(io)); - } else if(io.dir == OUTPUT) { - ports += new StringBuilder(nl + " " + prune + "output" + - emitWidth(io) + " " + emitRef(io)); - } - } - }; + var first = true + (c.clocks ++ c.resets.values.toList) map ("input " + emitRef(_)) addString (res, ", ") + val ports = ArrayBuffer[StringBuilder]() + for ((n, io) <- c.wires) { + val prune = if (io.prune && c != topMod) "//" else "" + io.dir match { + case INPUT => + ports += List(" ", prune, "input ", emitWidth(io), " ", emitRef(io)) addString (new StringBuilder) + case OUTPUT => + ports += List(" ", prune, "output", emitWidth(io), " ", emitRef(io)) addString (new StringBuilder) + } } - val uncommentedPorts = ports.filter(!_.result.contains("//")) - uncommentedPorts.slice(0, uncommentedPorts.length-1).map(_.append(",")) - if (c.clocks.length > 0 || c.resets.size > 0) res.append(",\n") else res.append("\n") - res.append(ports.map(_.result).reduceLeft(_ + "\n" + _)) - res.append("\n);\n\n"); - res.append(emitDecs(c)); - res.append("\n"); - res.append(emitInits(c)); - res.append("\n"); - res.append(emitDefs(c)); + // Add trailing ',' to uncommented ports + delimitUncommentedPortDecls(ports) + if (!c.clocks.isEmpty || !c.resets.isEmpty) res.append(",\n") else res.append("\n") + res.append(ports addString (new StringBuilder, "\n")) + res.append("\n);\n\n") + res.append(emitDecs(c)) + res.append("\n") + res.append(emitInits(c)) + res.append("\n") + res.append(emitDefs(c)) res.append(emitRegs(c)) - res.append("endmodule\n\n"); - res.result(); + res.append("endmodule\n\n") + res } def flushModules( - defs: LinkedHashMap[String, LinkedHashMap[String,ArrayBuffer[Module]]], + defs: LinkedHashMap[String, LinkedHashMap[StringBuilder,ArrayBuffer[Module]]], level: Int ): Unit = { for( (className, modules) <- defs ) { var index = 0 for ( (text, comps) <- modules) { val moduleName = if( modules.size > 1 ) { - className + "_" + index.toString; + className + "_" + index.toString } else { - className; + className } index = index + 1 for( flushComp <- comps ) { @@ -940,28 +664,27 @@ class VerilogBackend extends Backend { def emitChildren(top: Module, - defs: LinkedHashMap[String, LinkedHashMap[String, ArrayBuffer[Module] ]], - out: java.io.FileWriter, depth: Int): Unit = - { - if (top.isInstanceOf[BlackBox]) - return + defs: LinkedHashMap[String, LinkedHashMap[StringBuilder, ArrayBuffer[Module] ]], + out: java.io.FileWriter, depth: Int): Unit = top match { + case _: BlackBox => + case _ => // First, emit my children for (child <- top.children) { - emitChildren(child, defs, out, depth + 1); + emitChildren(child, defs, out, depth + 1) } // Now, find and emit me // Note: emittedModules used to ensure modules only emitted once // regardless of how many times used (e.g. when folded) - val className = extractClassName(top); + val className = extractClassName(top) for{ (text, comps) <- defs(className) if comps contains top if !(emittedModules contains top.moduleName) } { out.append(s"module ${top.moduleName}(") - out.append(text); + out.append(text) emittedModules += top.moduleName return } @@ -972,12 +695,12 @@ class VerilogBackend extends Backend { /* *defs* maps Mod classes to Mod instances through the generated text of their module. We use a LinkedHashMap such that later iteration is predictable. */ - val defs = LinkedHashMap[String, LinkedHashMap[String, ArrayBuffer[Module]]]() - var level = 0; + val defs = LinkedHashMap[String, LinkedHashMap[StringBuilder, ArrayBuffer[Module]]]() + var level = 0 for (c <- Driver.sortedComps) { - ChiselError.info(depthString(depth) + "COMPILING " + c - + " " + c.children.length + " CHILDREN" - + " (" + c.level + "," + c.traversal + ")"); + ChiselError.info(genIndent(depth) + "COMPILING " + c + + " " + c.children.size + " CHILDREN" + + " (" + c.level + "," + c.traversal + ")") ChiselError.checkpoint() if( c.level > level ) { @@ -988,24 +711,24 @@ class VerilogBackend extends Backend { If that were not the case, we could flush modules as soon as the source text for all components at a certain level in the tree has been generated. */ - flushModules(defs, level); + flushModules(defs, level) level = c.level } - val res = emitModuleText(c); - val className = extractClassName(c); + val res = emitModuleText(c) + val className = extractClassName(c) if( !(defs contains className) ) { - defs += (className -> LinkedHashMap[String, ArrayBuffer[Module] ]()); + defs += (className -> LinkedHashMap[StringBuilder, ArrayBuffer[Module] ]()) } if( defs(className) contains res ) { /* We have already outputed the exact same source text */ - defs(className)(res) += c; - ChiselError.info("\t" + defs(className)(res).length + " components"); + defs(className)(res) += c + ChiselError.info("\t" + defs(className)(res).length + " components") } else { - defs(className) += (res -> ArrayBuffer[Module](c)); + defs(className) += (res -> ArrayBuffer[Module](c)) } } - flushModules(defs, level); - emitChildren(top, defs, out, depth); + flushModules(defs, level) + emitChildren(top, defs, out, depth) } override def elaborate(c: Module) { @@ -1023,44 +746,262 @@ class VerilogBackend extends Backend { if (!memConfs.isEmpty) { val out_conf = createOutputFile(n + ".conf") - out_conf.write(getMemConfString); - out_conf.close(); + out_conf.write(getMemConfString) + out_conf.close() } if (Driver.isGenHarness) { - genHarness(c, n); + genHarness(c, n) + copyToTarget("sim_api.h") + copyToTarget("vpi.h") + copyToTarget("vpi.cpp") + copyToTarget("vpi.tab") } } - override def compile(c: Module, flags: String) { - def copyToTarget(filename: String) = { - val resourceStream = getClass().getResourceAsStream("/" + filename) - if( resourceStream != null ) { - val classFile = createOutputFile(filename) - while(resourceStream.available > 0) { - classFile.write(resourceStream.read()) - } - classFile.close() - resourceStream.close() - } else { - println(s"WARNING: Unable to copy '$filename'" ) - } - } - copyToTarget("vpi_user.cc") + override def compile(c: Module, flags: Option[String]) { val n = Driver.appendString(Some(c.name),Driver.chiselConfigClassName) - def run(cmd: String) { - val bashCmd = Seq("bash", "-c", cmd) - val c = bashCmd.! - ChiselError.info(cmd + " RET " + c) - } val dir = Driver.targetDir + "/" - val src = n + "-harness.v " + n + ".v" - val cmd = "cd " + dir + " && vcs -full64 -quiet +v2k -Mdir=" + n + ".csrc " + - "-timescale=1ns/1ps +define+CLOCK_PERIOD=120 +vpi -use_vpiobj vpi_user.cc " + - "+vcs+initreg+random " + src + " -o " + n + " -debug_pp" - run(cmd) + val ccFlags = List("-I$VCS_HOME/include", "-I" + dir, "-fPIC", "-std=c++11") mkString " " + val vcsFlags = List("-full64", "-quiet", "-timescale=1ns/1ps", "-debug_pp", "-Mdir=" + n + ".csrc", + "+vcs+lic+wait", "+v2k", "+vpi", "+define+CLOCK_PERIOD=1", "+vcs+initreg+random") mkString " " + val vcsSrcs = List(n + ".v", n + "-harness.v") mkString " " + val cmd = List("cd", dir, "&&", "vcs", vcsFlags, "-P", "vpi.tab", "vpi.o", "-o", n, vcsSrcs) mkString " " + cc(dir, "vpi", ccFlags) + if (!run(cmd)) throw new RuntimeException("vcs command failed") } private def if_not_synthesis = "`ifndef SYNTHESIS\n// synthesis translate_off\n" private def endif_not_synthesis = "// synthesis translate_on\n`endif\n" } +object VerilogBackend { + val keywords = Set[String]( + "alias", + "always", + "always_comb", + "always_ff", + "always_latch", + "and", + "assert", + "assign", + "assume", + "attribute", + "automatic", + "before", + "begin", + "bind", + "bins", + "binsof", + "bit", + "break", + "buf", + "bufif0", + "bufif1", + "byte", + "case", + "casex", + "casez", + "cell", + "chandle", + "class", + "clocking", + "cmos", + "config", + "const", + "constraint", + "context", + "continue", + "cover", + "covergroup", + "coverpoint", + "cross", + "deassign", + "default", + "defparam", + "design", + "disable", + "dist", + "do", + "edge", + "else", + "end", + "endattribute", + "endcase", + "endclass", + "endclocking", + "endconfig", + "endfunction", + "endgenerate", + "endgroup", + "endinterface", + "endmodule", + "endpackage", + "endprimitive", + "endprogram", + "endproperty", + "endsequence", + "endspecify", + "endtable", + "endtask", + "enum", + "event", + "expect", + "export", + "extends", + "extern", + "final", + "first_match", + "for", + "force", + "foreach", + "forever", + "fork", + "forkjoin", + "function", + "generate", + "genvar", + "highz0", + "highz1", + "if", + "iff", + "ifnone", + "ignore_bins", + "illegal_bins", + "import", + "incdir", + "include", + "initial", + "initvar", + "inout", + "input", + "inside", + "instance", + "int", + "integer", + "interface", + "intersect", + "join", + "join_any", + "join_none", + "large", + "liblist", + "library", + "local", + "localparam", + "logic", + "longint", + "macromodule", + "matches", + "medium", + "modport", + "module", + "nand", + "negedge", + "new", + "nmos", + "nor", + "noshowcancelled", + "not", + "notif0", + "notif1", + "null", + "or", + "output", + "package", + "packed", + "parameter", + "pmos", + "posedge", + "primitive", + "priority", + "program", + "property", + "protected", + "pull0", + "pull1", + "pulldown", + "pullup", + "pulsestyle_ondetect", + "pulsestyle_onevent", + "pure", + "rand", + "randc", + "randcase", + "randsequence", + "rcmos", + "real", + "realtime", + "ref", + "reg", + "release", + "repeat", + "return", + "rnmos", + "rpmos", + "rtran", + "rtranif0", + "rtranif1", + "scalared", + "sequence", + "shortint", + "shortreal", + "showcancelled", + "signed", + "small", + "solve", + "specify", + "specparam", + "static", + "strength", + "string", + "strong0", + "strong1", + "struct", + "super", + "supply0", + "supply1", + "table", + "tagged", + "task", + "this", + "throughout", + "time", + "timeprecision", + "timeunit", + "tran", + "tranif0", + "tranif1", + "tri", + "tri0", + "tri1", + "triand", + "trior", + "trireg", + "type", + "typedef", + "union", + "unique", + "unsigned", + "use", + "uwire", + "var", + "vectored", + "virtual", + "void", + "wait", + "wait_order", + "wand", + "weak0", + "weak1", + "while", + "wildcard", + "wire", + "with", + "within ", + "wor", + "xnor", + "xor", + "SYNTHESIS", + "PRINTF_COND", + "VCS") +} diff --git a/src/main/scala/Version.scala b/src/main/scala/Version.scala new file mode 100644 index 00000000..e7d671dd --- /dev/null +++ b/src/main/scala/Version.scala @@ -0,0 +1,95 @@ +/* + Copyright (c) 2011 - 2016 The Regents of the University of + California (Regents). All Rights Reserved. Redistribution and use in + source and binary forms, with or without modification, are permitted + provided that the following conditions are met: + + * Redistributions of source code must retain the above + copyright notice, this list of conditions and the following + two paragraphs of disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + two paragraphs of disclaimer in the documentation and/or other materials + provided with the distribution. + * Neither the name of the Regents nor the names of its contributors + may be used to endorse or promote products derived from this + software without specific prior written permission. + + IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, + SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, + ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF + REGENTS HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF + ANY, PROVIDED HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION + TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR + MODIFICATIONS. +*/ + +package Chisel + +import scala.util.matching.Regex + +object Version { + val versionRE = """(^\d+){0,1}((\.(\d+)){0,2})$""".r + + def apply(s: String): Version = { + new Version(s) + } + + implicit def stringToVersion(s: String): Version = { + Version(s) + } +} + +/** Version - dotted string with up to three components. + * Comparisons are done component by component for the smallest number of components. + * So: + * "3" >= "2.99.99" + * "3" < "4" + * "3" >= "3.99.99" + * "3.9" >= "3" + * "3.9" >= "3.0" + * "3.9" >= "3.9.99" + * + * The empty string "" is the "maximum" version and compares > all other versions. + */ +class Version(val dottedString: String) extends scala.math.Ordered[Version] { + // Ensure we have a valid version string. + require(Version.versionRE.pattern.matcher(dottedString).matches) + val maxVersion: Boolean = dottedString == "" + + def compare(that: Version):Int = { + // If both versions are maximum, they're equal. + if (this.maxVersion && that.maxVersion) { + 0 + } else if (this.maxVersion) { + 1 + } else if (that.maxVersion) { + -1 + } else { + // Neither version is maximum. Compare components. + val vtuples: Array[(String, String)] = this.dottedString.split('.') zip that.dottedString.split('.') + vtuples.find(vtuple => vtuple._1 != vtuple._2) match { + case Some((vsthis, vsthat)) => vsthis.toInt - vsthat.toInt + case None => 0 + } + } + } + + override def toString = dottedString + + /** Determine Version equality. */ + override def equals(other: Any): Boolean = other match { + case that: Version => + (that canEqual this) && (this.dottedString == that.dottedString) + case _ => + false + } + + /** Determine if two Versions are comparable. */ + def canEqual(other: Any): Boolean = other.isInstanceOf[Version] +} + diff --git a/src/main/scala/Width.scala b/src/main/scala/Width.scala index 190c4482..87f8ba8c 100644 --- a/src/main/scala/Width.scala +++ b/src/main/scala/Width.scala @@ -1,5 +1,5 @@ /* - Copyright (c) 2011, 2012, 2013, 2014 The Regents of the University of + Copyright (c) 2011 - 2016 The Regents of the University of California (Regents). All Rights Reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: @@ -30,15 +30,16 @@ package Chisel -import Node._ -import Width._ -import ChiselError._ +import java.util.NoSuchElementException +/** Get the number of bits required */ object Width { type WidthType = Option[Int] // The internal representation of width // Class variables. - val unSet: WidthType = None // The internal "unset" value - val unSetVal: Int = -1 // The external "unset" value + /** The internal "unset" value */ + val unSet: WidthType = None + /** The external "unset" value */ + val unSetVal: Int = -1 val throwIfUnsetRef: Boolean = false val debug: Boolean = false @@ -46,7 +47,7 @@ object Width { if (w < -1) { ChiselError.warning("Width:apply < -1") if (throwIfUnsetRef) { - throw new Exception("Width:apply < -1"); + throwException("Width:apply < -1"); } } val neww = new Width(w) @@ -54,7 +55,10 @@ object Width { } } +/** Create a new width */ class Width(_width: Int) extends Ordered[Width] { + import Width._ + // Construction: initialize internal state private var widthVal: WidthType = if (_width > -1) Some(_width) else unSet @@ -66,12 +70,12 @@ class Width(_width: Int) extends Ordered[Width] { @deprecated("Clients should not expect a Width is directly convertable to an Int", "2.3") def width: Int = if (isKnown) widthVal.get else unSetVal - // Set the width of a Node. + /** Set the width of a Node, w must be >= 0*/ def setWidth(w: Int): Unit = { assert(w >= 0, ChiselError.error("Width.setWidth: setting width to " + w)) if (w < 0) { if (throwIfUnsetRef) { - throw new Exception("Width:setWidth < -1"); + throwException("Width:setWidth < -1"); } widthVal = unSet } else { @@ -89,28 +93,24 @@ class Width(_width: Int) extends Ordered[Width] { setWidth(w) } - // Indicate whether width is actually known(set) or not. + /** Indicate whether width is actually known(set) or not */ def isKnown: Boolean = widthVal != unSet - // Return an "known" integer value or raise an exception - // if called when the width is unknown. + /** @return an "known" integer value + * @throws NoSuchElementException if called when the width is unknown */ def needWidth(): Int = { if (! isKnown ) { ChiselError.warning("needWidth but width not set") - if (throwIfUnsetRef) { - ChiselError.report() - throw new Exception("uninitialized width"); - } } widthVal.get } - // Return either the width or the specificed value if the width isn't set. + /** @return the width or the specificed value if the width isn't set */ def widthOrValue(v: Int): Int = { if (widthVal != unSet) widthVal.get else v } - // Compare two widths. We assume an unknown width is less than any known width + /** Compare two widths where an unknown width is less than any known width */ def compare(that: Width): Int = { if (this.isKnown && that.isKnown) { this.widthVal.get - that.widthVal.get @@ -121,17 +121,20 @@ class Width(_width: Int) extends Ordered[Width] { } } - // Print a string representation of width + /** Print a string representation of width */ override def toString: String = (widthVal match { case Some(w) => w case x => x }).toString + /** create a copy of this width + * @param w optionally set the width for the new copy */ def copy(w: Int = this.widthVal.get): Width = { val neww = new Width(w) neww } + /** clone this width */ override def clone(): Width = { if (this.isKnown) { Width(this.widthVal.get) @@ -141,6 +144,7 @@ class Width(_width: Int) extends Ordered[Width] { } // Define the arithmetic operations so we can deal with unspecified widths + // TODO: make private? def binaryOp(op: String, operand: Width): Width = { if (!this.isKnown) { this @@ -188,17 +192,23 @@ class Width(_width: Int) extends Ordered[Width] { // (undefined widths should NOT compare equal) // Since hashCode (and equals) depends on a var, it can change if the value changes. // This will be problematic for collections of widths. + /** Define the hashcode based on the width + * the same widths should have the same hash code + * unknown widths should be unique + */ override def hashCode: Int = widthVal match { case Some(w) => w * 41 case _ => super.hashCode } + /** Define equality for width */ override def equals(other: Any): Boolean = other match { case that: Width => (that canEqual this) && (this.widthVal != unSet) (this.widthVal == that.widthVal) case _ => false -} - def canEqual(other: Any): Boolean = other.isInstanceOf[Width] + } + /** check if 'other' is a Width to check if its possible to equal a Width */ + def canEqual(other: Any): Boolean = other.isInstanceOf[Width] } diff --git a/src/main/scala/fixpt.scala b/src/main/scala/fixpt.scala index b82ed1e0..5a68ca55 100644 --- a/src/main/scala/fixpt.scala +++ b/src/main/scala/fixpt.scala @@ -1,5 +1,5 @@ /* - Copyright (c) 2011, 2012, 2013, 2014 The Regents of the University of + Copyright (c) 2011 - 2016 The Regents of the University of California (Regents). All Rights Reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: @@ -54,8 +54,8 @@ abstract class Fix[B<:Bits with Num[B],T<:Fix[B,T]](val exp: Int, val raw: B) ex def do_addsub(b: T, isSub: Boolean = false): T = { val (t_adj_rd, b_adj_rd, int_exp) = aligned_with(b) - val new_width = math.max(exp-int_exp, b.exp-int_exp)+1 - // note: exp - int_exp = width + eff_exp-int_exp where eff_exp = exp-width + val new_width = math.max(exp - int_exp, b.exp - int_exp) + 1 + // note: exp - int_exp = width + eff_exp - int_exp where eff_exp = exp - width val new_exp = int_exp + new_width val result = Factory(new_exp, new_width) @@ -73,14 +73,14 @@ abstract class Fix[B<:Bits with Num[B],T<:Fix[B,T]](val exp: Int, val raw: B) ex } def do_mult(b: T): T = { - val result = Factory(exp+b.exp,raw.needWidth()+b.raw.needWidth()) + val result = Factory(exp + b.exp,raw.needWidth() + b.raw.needWidth()) result.raw := raw * b.raw - return result + result } def do_divide(b: T): T = { val result = Factory(exp-b.exp,raw.needWidth()) result.raw := raw / b.raw - return result + result } def do_truncate(source: T): Unit = { if(exp > source.exp) { @@ -97,23 +97,27 @@ abstract class Fix[B<:Bits with Num[B],T<:Fix[B,T]](val exp: Int, val raw: B) ex } else { val msb_extract = source.raw.needWidth()-(source.exp-exp)-1 - val remaining_source = if(msb_extract>=0) msb_extract+1 else 0 + val remaining_source = if(msb_extract>=0) msb_extract + 1 else 0 val taken_source = math.min(remaining_source, raw.needWidth()) val append_zs = raw.needWidth()-taken_source raw := toRaw( if(append_zs>0) ( - if(taken_source>0) Cat(source.raw(msb_extract, msb_extract-taken_source+1), UInt(0, width=append_zs)) + if(taken_source>0) Cat(source.raw(msb_extract, msb_extract - taken_source + 1), UInt(0, width=append_zs)) else UInt(0, append_zs) - ) else source.raw(msb_extract, msb_extract-taken_source+1) + ) else source.raw(msb_extract, msb_extract - taken_source + 1) ) } } } +/** An unsigned Fixed point representation + * Consider using [[Chisel.Fixed Fixed]] instead */ object UFix { def apply(exp: Int, width: Int): UFix = new UFix(exp, UInt(width=width)) } +/** An unsigned Fixed point representation + * Consider using [[Chisel.Fixed Fixed]] instead */ class UFix(exp: Int, raw: UInt) extends Fix[UInt,UFix](exp, raw) with Num[UFix] { def Factory(exp: Int, width: Int) = UFix(exp, width) def toRaw(a: Bits) = a.toUInt @@ -130,21 +134,23 @@ class UFix(exp: Int, raw: UInt) extends Fix[UInt,UFix](exp, raw) with Num[UFix] case _ => illegalAssignment(that) } - def <<(b: Int): UFix = new UFix(exp+b, raw) - def >>(b: Int): UFix = new UFix(exp-b, raw) + def <<(b: Int): UFix = new UFix(exp + b, raw) + def >>(b: Int): UFix = new UFix(exp - b, raw) def < (b: UFix): Bool = do_lessthan(b) def <= (b: UFix): Bool = do_lesseq(b) def > (b: UFix): Bool = b.do_lessthan(this) def >= (b: UFix): Bool = b.do_lesseq(this) - def % (b: UFix): UFix = throw new Exception("% unavailable for UFix") + def % (b: UFix): UFix = throwException("% unavailable for UFix") } +@deprecated("Use [[Chisel.Fixed Fixed]] instead", "3") object SFix { def apply(exp: Int, width: Int): SFix = new SFix(exp, SInt(width=width)) } +@deprecated("Use [[Chisel.Fixed Fixed]] instead", "3") class SFix(exp: Int, raw: SInt) extends Fix[SInt,SFix](exp, raw) with Num[SFix] { def Factory(exp: Int, width: Int) = SFix(exp, width) def toRaw(a: Bits) = a.toSInt @@ -161,55 +167,13 @@ class SFix(exp: Int, raw: SInt) extends Fix[SInt,SFix](exp, raw) with Num[SFix] case _ => illegalAssignment(that) } - def <<(b: Int): SFix = new SFix(exp+b, raw) - def >>(b: Int): SFix = new SFix(exp-b, raw) + def <<(b: Int): SFix = new SFix(exp + b, raw) + def >>(b: Int): SFix = new SFix(exp - b, raw) def < (b: SFix): Bool = do_lessthan(b) def <= (b: SFix): Bool = do_lesseq(b) def > (b: SFix): Bool = b.do_lessthan(this) def >= (b: SFix): Bool = b.do_lesseq(this) - def % (b: SFix): SFix = throw new Exception("% unavailable for UFix") + def % (b: SFix): SFix = throwException("% unavailable for SFix") } - -object QR { - def genSFix(int: Int, frac: Int) = SFix(int, int+frac) - def genUFix(int: Int, frac: Int) = UFix(int, int+frac) -} - - -class Toy extends Module { - val io = new Bundle { - val in0 = SFix(2, 4).asInput - val in1 = SFix(2, 4).asInput - - val out = SFix(4,16).asOutput - val oraw = Bits(OUTPUT, width=128) - } - - val int_result = -io.in0 * (io.in0 + io.in1) - - io.out := int_result - io.oraw := int_result.raw -} - -class ToyTester(dut: Toy) extends AdvTester.AdvTester(dut) { - poke(dut.io.in0.raw, BigInt(16-2)) - poke(dut.io.in1.raw, BigInt(5)) - takestep() - def signed_peek(target: Bits): Double = { - val raw = peek(target) - val gotWidth = target.getWidth() - val max_pos = (BigInt(1) << (gotWidth-1))-1 - (if(raw > max_pos) raw - (BigInt(1) << gotWidth) else raw).toDouble - } - def convert[T<:Fix[_,_]](target: T): Double = { - target match { - case s: SFix => (signed_peek(s.raw).toDouble * math.pow(2, s.exp-s.raw.needWidth())) - case u: UFix => (peek(u.raw).toDouble * math.pow(2, u.exp-u.raw.needWidth())) - } - } - println("In = %g, %g : Out = %g".format(convert(dut.io.in0), convert(dut.io.in1), convert(dut.io.out))) - println("Raw output is: %s".format(peek(dut.io.oraw).toByteArray.map("%02X".format(_)).reduce(_+" "+_))) -} - diff --git a/src/main/scala/hcl.scala b/src/main/scala/hcl.scala index 3a4dc31a..8de40254 100644 --- a/src/main/scala/hcl.scala +++ b/src/main/scala/hcl.scala @@ -1,5 +1,5 @@ /* - Copyright (c) 2011, 2012, 2013, 2014 The Regents of the University of + Copyright (c) 2011 - 2016 The Regents of the University of California (Regents). All Rights Reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: @@ -29,17 +29,14 @@ */ package Chisel -import ChiselError._ - -class TestIO(val format: String, val args: Seq[Data] = null) +import scala.util.Properties +class TestIO(val format: String, val args: Seq[Data] = Seq()) object Scanner { - def apply (format: String, args: Data*): TestIO = - new TestIO(format, args.toList); + def apply (format: String, args: Data*): TestIO = new TestIO(format, args.toList) } object Printer { - def apply (format: String, args: Data*): TestIO = - new TestIO(format, args.toList); + def apply (format: String, args: Data*): TestIO = new TestIO(format, args.toList) } /** @@ -83,11 +80,22 @@ class ChiselException(message: String, cause: Throwable) extends Exception(messa object throwException { def apply(s: String, t: Throwable = null) = { val xcpt = new ChiselException(s, t) - findFirstUserLine(xcpt.getStackTrace) foreach { u => xcpt.setStackTrace(Array(u)) } + ChiselError.findFirstUserLine(xcpt.getStackTrace) foreach { u => xcpt.setStackTrace(Array(u)) } + // Record this as an error (for tests and error reporting). + ChiselError.error(s) throw xcpt } } +// Throw a "quiet" exception. This is essentially the same as throwException, +// except that it leaves the recording of the error up to the caller. +object throwQuietException { + def apply(s: String, t: Throwable = null) = { + val xcpt = new ChiselException(s, t) + ChiselError.findFirstUserLine(xcpt.getStackTrace) foreach { u => xcpt.setStackTrace(Array(u)) } + throw xcpt + } +} trait proc extends Node { protected var procAssigned = false @@ -121,10 +129,8 @@ trait proc extends Node { traverse(inputs(0)) } - protected[Chisel] def next: Node = { - val node = getNode - if (node.inputs.isEmpty) null else node.inputs(0) - } + protected[Chisel] def nextOpt = if (getNode.inputs.isEmpty) None else Some(getNode.inputs(0).getNode) + protected[Chisel] def next = nextOpt getOrElse throwException("Input is empty") protected def default = if (defaultRequired) null else this protected def defaultRequired: Boolean = false protected def defaultMissing: Boolean = @@ -132,29 +138,49 @@ trait proc extends Node { protected def setDefault(src: Node): Unit = muxes.last.inputs(2) = src } -trait nameable { +/** This trait allows an instantiation of something to be given a particular name */ +trait Nameable { + /** Name of the instance. */ var name: String = "" - /** _named_ is used to indicates name was set explicitely - and should not be overriden by a _nameIt_ generator. */ + /** named is used to indicate that name was set explicitly and should not be overriden */ var named = false + /** Set the name of this module to the string 'n' + * @example {{{ my.io.node.setName("MY_IO_NODE") }}} + */ + def setName(n: String) { name = n ; named = true } } -abstract class BlackBox extends Module { - Driver.blackboxes += this - - def setVerilogParameters(string: String) { - this.asInstanceOf[Module].verilog_parameters = string; - } - - def setName(name: String) { - moduleName = name; - } -} - - -class Delay extends Node { - override def isReg: Boolean = true +trait Delay extends Node { + override lazy val isInObject: Boolean = true def assignReset(rst: => Bool): Boolean = false - def assignClock(clk: Clock): Unit = { clock = clk } + def assignClock(clk: Clock) { clock = Some(clk) } } + /** If there is an environment variable `chiselArguments`, construct an `Array[String]` + * of its value split on ' ', otherwise, return a 0 length `Array[String]` + * + * This makes it easy to merge with command line arguments and have the latter take precedence. + * {{{ + * def main(args: Array[String]) { + * val readArgs(chiselEnvironmentArguments() ++ args) + * ... + * } + * }}} + */ +object chiselEnvironmentArguments { + /** The ''name'' of the environment variable containing the arguments. */ + val chiselArgumentNameDefault = "chiselArguments" + + /** + * @return value of environment variable `chiselArguments` split on ' ' or a 0 length Array[String] + * + */ + def apply(envName: String = chiselArgumentNameDefault): Array[String] = { + val chiselArgumentString = Properties.envOrElse(envName, "") + if (chiselArgumentString != "") { + chiselArgumentString.split(' ') + } else { + new Array[String](0) + } + } +} diff --git a/src/main/scala/iotesters/ChiselSpec.scala b/src/main/scala/iotesters/ChiselSpec.scala new file mode 100644 index 00000000..b78fcf6c --- /dev/null +++ b/src/main/scala/iotesters/ChiselSpec.scala @@ -0,0 +1,83 @@ +// See LICENSE for license details. + +package Chisel.iotesters + +//import Chisel._ +import Chisel.testers.{BasicTester, TesterDriver} +//import java.io.File + +import org.scalatest._ +import org.scalatest.prop._ +import org.scalacheck._ + +/** Common utility functions for Chisel unit tests. */ +trait ChiselRunners extends Assertions { + val backends = TesterDriver.backends + implicit val testArgs = Driver.testArgs + def runTester(t: => BasicTester): Boolean = { + TesterDriver.execute(() => t) + } + def assertTesterPasses(t: => BasicTester): Unit = { + assert(runTester(t)) + } + def assertTesterFails(t: => BasicTester): Unit = { + assert(!runTester(t)) + } +// def elaborate(t: => Module): Unit = Driver.elaborate(() => t) + +} + +/** Spec base class for BDD-style testers. */ +class ChiselFlatSpec extends FlatSpec with ChiselRunners with Matchers + +/** Spec base class for property-based testers. */ +class ChiselPropSpec extends PropSpec with ChiselRunners with PropertyChecks { + + // Constrain the default number of instances generated for every use of forAll. + implicit override val generatorDrivenConfig = + PropertyCheckConfig(minSuccessful = 8, minSize = 1, maxSize = 4) + + // Generator for small positive integers. + val smallPosInts = Gen.choose(1, 4) + + // Generator for widths considered "safe". + val safeUIntWidth = Gen.choose(1, 30) + + // Generators for integers that fit within "safe" widths. + val safeUInts = Gen.choose(0, (1 << 30)) + + // Generators for vector sizes. + val vecSizes = Gen.choose(0, 4) + + // Generator for string representing an arbitrary integer. + val binaryString = for (i <- Arbitrary.arbitrary[Int]) yield "b" + i.toBinaryString + + // Generator for a sequence of Booleans of size n. + def enSequence(n: Int): Gen[List[Boolean]] = Gen.containerOfN[List, Boolean](n, Gen.oneOf(true, false)) + + // Generator which gives a width w and a list (of size n) of numbers up to w bits. + def safeUIntN(n: Int): Gen[(Int, List[Int])] = for { + w <- smallPosInts + i <- Gen.containerOfN[List, Int](n, Gen.choose(0, (1 << w) - 1)) + } yield (w, i) + + // Generator which gives a width w and a numbers up to w bits. + val safeUInt = for { + w <- smallPosInts + i <- Gen.choose(0, (1 << w) - 1) + } yield (w, i) + + // Generator which gives a width w and a list (of size n) of a pair of numbers up to w bits. + def safeUIntPairN(n: Int): Gen[(Int, List[(Int, Int)])] = for { + w <- smallPosInts + i <- Gen.containerOfN[List, Int](n, Gen.choose(0, (1 << w) - 1)) + j <- Gen.containerOfN[List, Int](n, Gen.choose(0, (1 << w) - 1)) + } yield (w, i zip j) + + // Generator which gives a width w and a pair of numbers up to w bits. + val safeUIntPair = for { + w <- smallPosInts + i <- Gen.choose(0, (1 << w) - 1) + j <- Gen.choose(0, (1 << w) - 1) + } yield (w, i, j) +} diff --git a/src/main/scala/iotesters/Driver.scala b/src/main/scala/iotesters/Driver.scala new file mode 100644 index 00000000..8b1d2459 --- /dev/null +++ b/src/main/scala/iotesters/Driver.scala @@ -0,0 +1,62 @@ +/* + Copyright (c) 2011 - 2016 The Regents of the University of + California (Regents). All Rights Reserved. Redistribution and use in + source and binary forms, with or without modification, are permitted + provided that the following conditions are met: + + * Redistributions of source code must retain the above + copyright notice, this list of conditions and the following + two paragraphs of disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + two paragraphs of disclaimer in the documentation and/or other materials + provided with the distribution. + * Neither the name of the Regents nor the names of its contributors + may be used to endorse or promote products derived from this + software without specific prior written permission. + + IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, + SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, + ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF + REGENTS HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF + ANY, PROVIDED HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION + TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR + MODIFICATIONS. +*/ + +package Chisel.iotesters + +import Chisel.{Backend => ChiselBackend} +import Chisel._ + +object Driver { + val basicTestArgs = Array[String]("--compile", "--genHarness", "--test") ++ chiselEnvironmentArguments() + var backendName: Option[String] = None + def testArgs: Array[String] = basicTestArgs ++ (if (backendName != None) { + Array("--backend", backendName.get) + } else { + Array[String]() + }) + + def apply[T <: Module](dutGen: () => T, backendType: String = "")(testerGen: T => PeekPokeTester[T]): Boolean = { + // Save the current backend name. + if (backendType != "") { + backendName = Some(backendType) + } + val res: Boolean = { + try { +// val oldTesterGen = testerGen(_: T, None) + chiselMain.run(testArgs, dutGen, testerGen) + true + } + catch { + case e: Throwable => false + } + } + res + } +} diff --git a/src/main/scala/iotesters/HWIOTester.scala b/src/main/scala/iotesters/HWIOTester.scala new file mode 100644 index 00000000..7ce63e08 --- /dev/null +++ b/src/main/scala/iotesters/HWIOTester.scala @@ -0,0 +1,71 @@ +/* + Copyright (c) 2011 - 2016 The Regents of the University of + California (Regents). All Rights Reserved. Redistribution and use in + source and binary forms, with or without modification, are permitted + provided that the following conditions are met: + + * Redistributions of source code must retain the above + copyright notice, this list of conditions and the following + two paragraphs of disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + two paragraphs of disclaimer in the documentation and/or other materials + provided with the distribution. + * Neither the name of the Regents nor the names of its contributors + may be used to endorse or promote products derived from this + software without specific prior written permission. + + IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, + SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, + ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF + REGENTS HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF + ANY, PROVIDED HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION + TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR + MODIFICATIONS. +*/ + +package Chisel.iotesters + +import Chisel._ +import Chisel.testers.BasicTester + +// scalastyle:off regex +// scalastyle:off method.name +/** + * provide common facilities for step based testing and decoupled interface testing + */ +abstract class HWIOTester extends BasicTester { + val device_under_test: Module + var io_info: IOAccessor = null + def finish(): Unit + + def int(x: Bits): BigInt = x.litValue() + + override val io = new Bundle { + val running = Bool(INPUT) + val error = Bool(OUTPUT) + val pc = UInt(OUTPUT, 32) + val done = Bool(OUTPUT) + } + io.done := setDone + io.error := setError + + val rnd = new scala.util.Random(Chisel.Driver.testerSeed) + + var enable_scala_debug = false + var enable_printf_debug = false + var enable_all_debug = false + + def logScalaDebug(msg: => String): Unit = { + //noinspection ScalaStyle + if(enable_all_debug || enable_scala_debug) println(msg) + } + + def logPrintfDebug(fmt: String, args: Bits*): Unit = { + if(enable_all_debug || enable_scala_debug) printf(fmt, args :_*) + } +} diff --git a/src/main/scala/iotesters/IOAccessor.scala b/src/main/scala/iotesters/IOAccessor.scala new file mode 100644 index 00000000..add65efe --- /dev/null +++ b/src/main/scala/iotesters/IOAccessor.scala @@ -0,0 +1,174 @@ +/* + Copyright (c) 2011 - 2016 The Regents of the University of + California (Regents). All Rights Reserved. Redistribution and use in + source and binary forms, with or without modification, are permitted + provided that the following conditions are met: + + * Redistributions of source code must retain the above + copyright notice, this list of conditions and the following + two paragraphs of disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + two paragraphs of disclaimer in the documentation and/or other materials + provided with the distribution. + * Neither the name of the Regents nor the names of its contributors + may be used to endorse or promote products derived from this + software without specific prior written permission. + + IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, + SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, + ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF + REGENTS HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF + ANY, PROVIDED HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION + TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR + MODIFICATIONS. +*/ + +package Chisel.iotesters + +import Chisel._ + +import scala.collection.mutable +import scala.util.matching.Regex + +// scalastyle:off regex +// scalastyle:off method.name + +/** + * named access and type information about the IO bundle of a module + * used for building testing harnesses + */ +class IOAccessor(val device_io_data: Data, verbose: Boolean = true) { + val device_io: Bundle = device_io_data match { + case b: Bundle => b + case _ => { + ChiselError.error("DUT io isn't a Bundle") + new Bundle() + } + } + val dut_inputs = device_io.flatten.map( { case (name, port) => port } ).filter( _.dir == INPUT) + val dut_outputs = device_io.flatten.map( { case (name, port) => port } ).filter( _.dir == OUTPUT) + val ports_referenced = new mutable.HashSet[Data] + + val referenced_inputs = new mutable.HashSet[Data]() + val referenced_outputs = new mutable.HashSet[Data]() + + val name_to_decoupled_port = new mutable.HashMap[String, DecoupledIO[Data]]() + val name_to_valid_port = new mutable.HashMap[String, ValidIO[Data]]() + + val port_to_name = { + val port_to_name_accumulator = new mutable.HashMap[Data, String]() + + def checkDecoupledOrValid(port: Data, name: String): Unit = { + port match { + case decoupled_port : DecoupledIO[Data] => + name_to_decoupled_port(name) = decoupled_port + case valid_port : ValidIO[Data] => + name_to_valid_port(name) = valid_port + case _ => + } + } + + def parseBundle(b: Bundle, name: String = ""): Unit = { + for ((n, e) <- b.elements) { + val new_name = name + (if(name.length > 0 ) "." else "" ) + n + port_to_name_accumulator(e) = new_name + + e match { + case bb: Bundle => parseBundle(bb, new_name) + case vv: Vec[_] => parseVecs(vv, new_name) + case ee: Bits => + case _ => + throw new Exception(s"bad bundle member $new_name $e") + } + checkDecoupledOrValid(e, new_name) + } + } + def parseVecs[T<:Data](b: Vec[T], name: String = ""): Unit = { + for ((e, i) <- b.zipWithIndex) { + val new_name = name + s"($i)" + port_to_name_accumulator(e) = new_name + + e match { + case bb: Bundle => parseBundle(bb, new_name) + case vv: Vec[_] => parseVecs(vv, new_name) + case ee: Bits => + case _ => + throw new Exception(s"bad bundle member $new_name $e") + } + checkDecoupledOrValid(e, new_name) + } + } + + parseBundle(device_io) + port_to_name_accumulator + } + val name_to_port = port_to_name.map(_.swap) + + //noinspection ScalaStyle + def showPorts(pattern : Regex): Unit = { + def orderPorts(a: Data, b: Data) : Boolean = { + port_to_name(a) < port_to_name(b) + } + def showDecoupledCode(port_name:String): String = { + if(name_to_decoupled_port.contains(port_name)) "D" + else if(name_to_valid_port.contains(port_name)) "V" + else if(findParentDecoupledPortName(port_name).nonEmpty) "D." + else if(findParentValidPortName(port_name).nonEmpty) "V." + else "" + + } + def showDecoupledParent(port_name:String): String = { + findParentDecoupledPortName(port_name) match { + case Some(decoupled_name) => s"$decoupled_name" + case _ => findParentValidPortName(port_name).getOrElse("") + } + } + def show_dir(dir: IODirection) = dir match { + case INPUT => "I" + case OUTPUT => "O" + case _ => "-" + } + + println("=" * 80) + println("Device under test: io bundle") + println("%3s %3s %-4s %4s %-25s %s".format( + "#", "Dir", "D/V", "Used", "Name", "Parent" + )) + println("-" * 80) + + for((port,index) <- port_to_name.keys.toList.sortWith(orderPorts).zipWithIndex) { + val port_name = port_to_name(port) + println("%3d %3s %-4s%4s %-25s %s".format( + index, + show_dir(port.toBits.dir), + showDecoupledCode(port_name), + if(ports_referenced.contains(port)) "y" else "", + port_name, + showDecoupledParent(port_name) + )) + } + if(verbose) { + println("=" * 80) + } + } + + def findParentDecoupledPortName(name: String): Option[String] = { + val possible_parents = name_to_decoupled_port.keys.toList.filter(s => name.startsWith(s)) + if(possible_parents.isEmpty) return None + possible_parents.sorted.lastOption + } + def findParentValidPortName(name: String): Option[String] = { + val possible_parents = name_to_valid_port.keys.toList.filter(s => name.startsWith(s)) + if(possible_parents.isEmpty) return None + possible_parents.sorted.lastOption + } + + def contains(port: Data) : Boolean = { + ports_referenced.contains(port) + } +} diff --git a/src/main/scala/iotesters/OrderedDecoupledHWIOTester.scala b/src/main/scala/iotesters/OrderedDecoupledHWIOTester.scala new file mode 100644 index 00000000..8673e88a --- /dev/null +++ b/src/main/scala/iotesters/OrderedDecoupledHWIOTester.scala @@ -0,0 +1,471 @@ +/* + Copyright (c) 2011 - 2016 The Regents of the University of + California (Regents). All Rights Reserved. Redistribution and use in + source and binary forms, with or without modification, are permitted + provided that the following conditions are met: + + * Redistributions of source code must retain the above + copyright notice, this list of conditions and the following + two paragraphs of disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + two paragraphs of disclaimer in the documentation and/or other materials + provided with the distribution. + * Neither the name of the Regents nor the names of its contributors + may be used to endorse or promote products derived from this + software without specific prior written permission. + + IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, + SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, + ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF + REGENTS HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF + ANY, PROVIDED HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION + TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR + MODIFICATIONS. +*/ + +package Chisel.iotesters + +import Chisel._ + +import scala.collection.mutable +import scala.collection.mutable.ArrayBuffer + +/** + * Base class supports implementation of test circuits of modules + * that use Decoupled inputs and either Decoupled or Valid outputs + * Multiple decoupled inputs are supported. + * Testers that subclass this will be strictly ordered. + * Input will flow into their devices asynchronously but in order they were generated + * be compared in the order they are generated + * + * @example + * {{{ + * class XTimesXTester extends [[OrderedDecoupledHWIOTester]] { + * val device_under_test = new XTimesY + * test_block { + * for { + * i <- 0 to 10 + * j <- 0 to 10 + * } { + * input_event(device_under_test.io.in.x -> i, device_under_test.in.y -> j) + * output_event(device_under_test.io.out.z -> i*j) + * } + * } + * } + * }}} + * an input event is a series of values that will be gated into the decoupled input interface at the same time + * an output event is a series of values that will be tested at the same time + * + * independent small state machines are set up for input and output interface + * all inputs regardless of interfaces are submitted to the device under test in the order in which they were created + * likewise, + * all outputs regardless of which interface are tested in the same order that they were created + */ + +// scalastyle:off regex +// scalastyle:off method.name + +abstract class OrderedDecoupledHWIOTester extends HWIOTester { + val input_event_list = new ArrayBuffer[Seq[(Data, BigInt)]]() + val output_event_list = new ArrayBuffer[Seq[(Data, BigInt)]]() + + val port_to_decoupled = new mutable.HashMap[Data, DecoupledIO[Data]] + val port_to_valid = new mutable.HashMap[Data, ValidIO[Data]] + + case class TestingEvent(port_values: Map[Data, BigInt], event_number: Int) + + val control_port_to_input_values = new mutable.HashMap[DecoupledIO[Data], ArrayBuffer[TestingEvent]] { + override def default(key: DecoupledIO[Data]) = { + this(key) = new ArrayBuffer[TestingEvent]() + this(key) + } + } + val decoupled_control_port_to_output_values = new mutable.HashMap[DecoupledIO[Data], ArrayBuffer[TestingEvent]] { + override def default(key: DecoupledIO[Data]) = { + this(key) = new ArrayBuffer[TestingEvent]() + this(key) + } + } + val valid_control_port_to_output_values = new mutable.HashMap[ValidIO[Data], ArrayBuffer[TestingEvent]] { + override def default(key: ValidIO[Data]) = { + this(key) = new ArrayBuffer[TestingEvent]() + this(key) + } + } + + /** + * Validate that all pokes ports are members of the same DecoupledIO + * makes a list of all decoupled parents based on the ports referenced in pokes + */ + def checkAndGetCommonDecoupledOrValidParentPort( + pokes: Seq[(Data, BigInt)], + must_be_decoupled: Boolean = true, + event_number: Int + ) : Either[DecoupledIO[Data],ValidIO[Data]] = { + val decoupled_parent_names = pokes.flatMap { case (port, value) => + Predef.assert( + !io_info.port_to_name(port).endsWith(".valid"), + s"Error: port ${io_info.port_to_name(port)}. input_event and output_event cannot directly reference valid" + ) + Predef.assert( + !io_info.port_to_name(port).endsWith(".ready"), + s"Error: port ${io_info.port_to_name(port)}, input_event and output_event cannot directly reference ready" + ) + + io_info.findParentDecoupledPortName(io_info.port_to_name(port)) match { + case None => + if (must_be_decoupled) { + throw new Exception( + s"Error: event $event_number port ${io_info.port_to_name(port)} not member of DecoupledIO" + ) + None + } + else { + return getCommonValidParentPort(pokes, event_number) + } + case Some(parent) => + val decoupled_port = io_info.name_to_decoupled_port(parent) + port_to_decoupled(port) = decoupled_port + Some(parent) + } + } + if( decoupled_parent_names.toSet.size != 1 ) { + throw new Exception( + s"Error: event $event_number multiple DecoupledIO's referenced " + + decoupled_parent_names.toSet.mkString(",") + ) + } + + Left(io_info.name_to_decoupled_port(decoupled_parent_names.head)) + } + /** + * Validate that all pokes ports are members of the same DecoupledIO or ValidIO + * makes a list of all decoupled parents based on the ports referenced in pokes + */ + def getCommonValidParentPort( + expects: Seq[(Data, BigInt)], + event_number: Int + ): Either[DecoupledIO[Data], ValidIO[Data]] = { + val valid_parent_names = expects.flatMap { case (port, value) => + io_info.findParentValidPortName(io_info.port_to_name(port)) match { + case None => + throw new Exception(s"Error: event $event_number " + + s"port ${io_info.port_to_name(port)} not member of ValidIO") + None + case Some(parent) => + val valid_port = io_info.name_to_valid_port(parent) + port_to_valid(port) = valid_port + Some(parent) + } + } + if (valid_parent_names.toSet.size != 1) { + throw new Exception( + s"Error: event $event_number multiple ValidIO's referenced ${valid_parent_names.toSet.mkString(",")}" + ) + } + Right(io_info.name_to_valid_port(valid_parent_names.head)) + } + + def inputEvent(pokes: (Data, BigInt)*): Unit = { + input_event_list += pokes + } + + def outputEvent(expects: (Data, BigInt)*): Unit = { + output_event_list += expects + } + + /** + * iterate over recorded events, checking constraints on ports referenced, etc. + * use poke and expect to record + */ + def processInputEvents(): Unit = { + input_event_list.zipWithIndex.foreach { case (pokes, event_number) => + val Left(parent_port) = checkAndGetCommonDecoupledOrValidParentPort( + pokes, must_be_decoupled = true, event_number + ) + + control_port_to_input_values(parent_port) += new TestingEvent(pokes.toMap, event_number) + io_info.referenced_inputs ++= pokes.map(_._1) + io_info.ports_referenced ++= pokes.map(_._1) + } + logScalaDebug( + s"Processing input events done, referenced controlling ports " + + control_port_to_input_values.keys.map { p => io_info.port_to_name(p) }.mkString(",") + ) + } + + def processOutputEvents(): Unit = { + output_event_list.zipWithIndex.foreach { case (expects, event_number) => + checkAndGetCommonDecoupledOrValidParentPort( + expects, + must_be_decoupled = false, + event_number = event_number + ) match { + case Left(parent_port) => + decoupled_control_port_to_output_values(parent_port) += new TestingEvent(expects.toMap, event_number) + io_info.referenced_outputs ++= expects.map(_._1) + io_info.ports_referenced ++= expects.map(_._1) + + case Right(parent_port) => + valid_control_port_to_output_values(parent_port) += new TestingEvent(expects.toMap, event_number) + io_info.referenced_outputs ++= expects.map(_._1) + io_info.ports_referenced ++= expects.map(_._1) + + } + } + logScalaDebug( + s"Processing output events done, referenced controlling ports" + + ( + if (decoupled_control_port_to_output_values.nonEmpty) { + decoupled_control_port_to_output_values.keys.map { + p => io_info.port_to_name(p) + }.mkString(", decoupled : ", ",", "") + } + else { + "" + } + ) + + ( + if (valid_control_port_to_output_values.nonEmpty) { + valid_control_port_to_output_values.keys.map { + p => io_info.port_to_name(p) + }.mkString(", valid : ", ",", "") + } + else { + "" + } + ) + ) + } + + private def name(port: Data): String = io_info.port_to_name(port) + + /** + * creates a Vec of Booleans that indicate if the io interface in question + * is operational at particular io event_number + * + * @param events is a list of events and their associated event numbers + * @return + */ + private def createIsMyTurnTable(events: ArrayBuffer[TestingEvent]): Vec[Bool] = { + val associated_event_numbers = events.map { event => event.event_number }.toSet + logScalaDebug(s" associated event numbers ${associated_event_numbers.toArray.sorted.mkString(",")}") + + Vec( + input_event_list.indices.map { event_number => Bool(associated_event_numbers.contains(event_number)) } ++ + List(Bool(false)) // We append a false at the end so no-one tries to go when counter done + ) + } + + /** + * build a set of all ports referenced by all events associated with a particular + * io interface + * + * @param events a set of events + * @return + */ + private def portsReferencedByEvents(events: ArrayBuffer[TestingEvent]): mutable.HashSet[Data] = { + val ports_referenced = new mutable.HashSet[Data]() + events.foreach { event => + event.port_values.foreach { case (port, value) => ports_referenced += port } + } + ports_referenced + } + + private def buildValuesVectorForEachPort( + io_interface : Data, + referenced_ports : mutable.HashSet[Data], + events : ArrayBuffer[TestingEvent] + ): Map[Data, Vec[UInt]] = { + val port_vector_events = referenced_ports.map { port => + port -> Vec(events.map { event => UInt(event.port_values.getOrElse(port, BigInt(0))) } ++ List(UInt(0))) //0 added to end + }.toMap + + logScalaDebug(s"Input controller ${io_info.port_to_name(io_interface)} : ports " + + s" ${referenced_ports.map { port => name(port) }.mkString(",")}") + port_vector_events + } + /** + * for each input event only one controller is active (determined by it's private is_my_turn vector) + * each controller has a private counter indicating which event specific to that controller + * is on deck. those values are wired to the inputs of the decoupled input and the valid is asserted + * IMPORTANT NOTE: the lists generated here has an extra 0 element added to the end because the counter + * used will stop at a value one higher than the number of test elements + */ + private def buildInputEventHandlers(event_counter: GlobalEventCounter) { + control_port_to_input_values.foreach { case (controlling_port, events) => + val ports_referenced_for_this_controlling_port = portsReferencedByEvents(events) + val is_this_my_turn = createIsMyTurnTable(events) + + val counter_for_this_decoupled = Counter(events.length) + + val port_vector_events = buildValuesVectorForEachPort( + controlling_port, + ports_referenced_for_this_controlling_port, + events + ) + + logScalaDebug(s"Input controller ${io_info.port_to_name(controlling_port)} : ports " + + s" ${ports_referenced_for_this_controlling_port.map { port => name(port) }.mkString(",")}") + + ports_referenced_for_this_controlling_port.foreach { port => + port := port_vector_events(port)(counter_for_this_decoupled.value) + } + controlling_port.valid := is_this_my_turn(event_counter.value) + + when(controlling_port.valid && controlling_port.ready) { + counter_for_this_decoupled.inc() + event_counter.inc() + } + } + } + + /** + * Test values on ports moderated with a decoupled interface + * IMPORTANT NOTE: the lists generated here has an extra 0 element added to the end because the counter + * used will stop at a value one higher than the number of test elements + */ + private def buildDecoupledOutputEventHandlers(event_counter: GlobalEventCounter) { + decoupled_control_port_to_output_values.foreach { case (controlling_port, events) => + val ports_referenced_for_this_controlling_port = portsReferencedByEvents(events) + val is_this_my_turn = createIsMyTurnTable(events) + + val counter_for_this_decoupled = Counter(output_event_list.length) + logScalaDebug(s"Output decoupled controller ${name(controlling_port)} : ports " + + s" ${ports_referenced_for_this_controlling_port.map { port => name(port) }.mkString(",")}") + + val port_vector_events = buildValuesVectorForEachPort( + controlling_port, + ports_referenced_for_this_controlling_port, + events + ) + + controlling_port.ready := is_this_my_turn(event_counter.value) + + when(controlling_port.ready && controlling_port.valid) { + ports_referenced_for_this_controlling_port.foreach { port => + printf(s"output test event %d testing ${name(port)} = %d, should be %d\n", + event_counter.value, port.asInstanceOf[UInt], port_vector_events(port)(counter_for_this_decoupled.value) + ) + when(port.asInstanceOf[UInt] =/= port_vector_events(port)(counter_for_this_decoupled.value)) { + printf(s"Error: event %d ${name(port)} was %d should be %d\n", + event_counter.value, port.toBits(), port_vector_events(port)(counter_for_this_decoupled.value)) +// assert(Bool(false)) + stop() + } + } + counter_for_this_decoupled.inc() + event_counter.inc() + } + } + } + + /** + * Test events on output ports moderated with a valid interface + * IMPORTANT NOTE: the lists generated here has an extra 0 element added to the end because the counter + * used will stop at a value one higher than the number of test elements + */ + private def buildValidIoPortEventHandlers(event_counter: GlobalEventCounter) { + valid_control_port_to_output_values.foreach { case (controlling_port, events) => + val ports_referenced_for_this_controlling_port = portsReferencedByEvents(events) + val is_this_my_turn = createIsMyTurnTable(events) + + val counter_for_this_valid = Counter(output_event_list.length) + logScalaDebug(s"Output decoupled controller ${name(controlling_port)} : ports " + + s" ${ports_referenced_for_this_controlling_port.map { port => name(port) }.mkString(",")}") + + val port_vector_events = buildValuesVectorForEachPort( + controlling_port, + ports_referenced_for_this_controlling_port, + events + ) + + when(is_this_my_turn(event_counter.value)) { + when(controlling_port.valid) { + ports_referenced_for_this_controlling_port.foreach { port => + printf(s"output test event %d testing ${name(port)} = %d, should be %d", + event_counter.value, port.asInstanceOf[UInt], port_vector_events(port)(counter_for_this_valid.value) + ) + when(port.asInstanceOf[UInt] =/= port_vector_events(port)(counter_for_this_valid.value)) { + printf(s"Error: event %d ${name(port)} was %x should be %x", + event_counter.value, port.toBits(), port_vector_events(port)(counter_for_this_valid.value)) +// assert(Bool(false)) + } + } + counter_for_this_valid.inc() + event_counter.inc() + } + } + } + } + + class GlobalEventCounter(val max_count: Int) { + val counter = Reg(init = UInt(0, width = log2Up(max_count) + 2)) + val reached_end = Reg(init = Bool(false)) + + def value: UInt = counter + + def inc(): Unit = { + when(! reached_end ) { + when(counter === UInt(max_count-1)) { + reached_end := Bool(true) + } + counter := counter + UInt(1) + } + } + } + + /** + * this builds a circuit to load inputs and circuits to test outputs that are controlled + * by either a decoupled or valid + */ + override def finish(): Unit = { + io_info = new IOAccessor(device_under_test.io) + + processInputEvents() + processOutputEvents() + + val input_event_counter = new GlobalEventCounter(input_event_list.length) + val output_event_counter = new GlobalEventCounter(output_event_list.length) + + when(input_event_counter.reached_end && output_event_counter.reached_end) { + printf("All input and output events completed\n") + stop() + } + + + val ti = Reg(init= UInt(0, width = log2Up(OrderedDecoupledHWIOTester.max_tick_count))) + ti := ti + UInt(1) + when(ti > UInt(OrderedDecoupledHWIOTester.max_tick_count)) { + printf( + "Exceeded maximum allowed %d ticks in OrderedDecoupledHWIOTester, If you think code is correct use:\n" + + "DecoupleTester.max_tick_count = \n" + + "in the OrderedDecoupledHWIOTester subclass\n", + UInt(OrderedDecoupledHWIOTester.max_tick_count) + ) + stop() + } + + buildInputEventHandlers(input_event_counter) + buildDecoupledOutputEventHandlers(output_event_counter) + buildValidIoPortEventHandlers(output_event_counter) + + logPrintfDebug(s"in_event_counter %d, out_event_counter %d\n", + input_event_counter.value, output_event_counter.value) + if(enable_scala_debug || enable_all_debug) { + io_info.showPorts("".r) + } + } +} + +object OrderedDecoupledHWIOTester { + val default_max_tick_count = 1000 + var max_tick_count = default_max_tick_count +} + + diff --git a/src/main/scala/iotesters/PeekPokeTester.scala b/src/main/scala/iotesters/PeekPokeTester.scala new file mode 100644 index 00000000..5aebc0b2 --- /dev/null +++ b/src/main/scala/iotesters/PeekPokeTester.scala @@ -0,0 +1,63 @@ +/* + Copyright (c) 2011 - 2016 The Regents of the University of + California (Regents). All Rights Reserved. Redistribution and use in + source and binary forms, with or without modification, are permitted + provided that the following conditions are met: + + * Redistributions of source code must retain the above + copyright notice, this list of conditions and the following + two paragraphs of disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + two paragraphs of disclaimer in the documentation and/or other materials + provided with the distribution. + * Neither the name of the Regents nor the names of its contributors + may be used to endorse or promote products derived from this + software without specific prior written permission. + + IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, + SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, + ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF + REGENTS HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF + ANY, PROVIDED HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION + TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR + MODIFICATIONS. +*/ + +package Chisel.iotesters + +import Chisel.{ Backend => ChiselBackend } +import Chisel._ + +class Backend + +class PeekPokeTester[+T <: Module]( + val dut: T, + verbose: Boolean = true, + _base: Int = 16, + logFile: Option[String] = None, + waveform: Option[String] = None, + _backend: Option[Backend] = None, + _seed: Long = System.currentTimeMillis + ) extends Tester[T](dut, verbose, _base) + +object runPeekPokeTester { + def apply[T <: Module](dutGen: () => T, backendType: String = "")(testerGen: (T, Option[Backend]) => PeekPokeTester[T]): Boolean = { + val testArgs = Array[String]("--backend", "c", "--compile", "--genHarness", "--test") ++ chiselEnvironmentArguments() + val res: Boolean = { + try { + val oldTesterGen = testerGen(_: T, None) + chiselMainTest(testArgs, dutGen)(oldTesterGen) + true + } + catch { + case e: Throwable => false + } + } + res + } +} diff --git a/src/main/scala/iotesters/SteppedHWIOTester.scala b/src/main/scala/iotesters/SteppedHWIOTester.scala new file mode 100644 index 00000000..230d0212 --- /dev/null +++ b/src/main/scala/iotesters/SteppedHWIOTester.scala @@ -0,0 +1,213 @@ +/* + Copyright (c) 2011 - 2016 The Regents of the University of + California (Regents). All Rights Reserved. Redistribution and use in + source and binary forms, with or without modification, are permitted + provided that the following conditions are met: + + * Redistributions of source code must retain the above + copyright notice, this list of conditions and the following + two paragraphs of disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + two paragraphs of disclaimer in the documentation and/or other materials + provided with the distribution. + * Neither the name of the Regents nor the names of its contributors + may be used to endorse or promote products derived from this + software without specific prior written permission. + + IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, + SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, + ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF + REGENTS HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF + ANY, PROVIDED HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION + TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR + MODIFICATIONS. +*/ + +package Chisel.iotesters + +import Chisel._ + +import scala.collection.mutable +import scala.collection.mutable.ArrayBuffer + +// scalastyle:off regex +// scalastyle:off method.name + +/** + * Use a UnitTester to construct a test harness for a chisel module + * this module will be canonically referred to as the device_under_test, often simply as c in + * a unit test, and also dut + * The UnitTester is used to put series of values (as chisel.Vec's) into the ports of the dut io which are INPUT + * At specified times it check the dut io OUTPUT ports to see that they match a specific value + * The vec's are assembled through the following API + * poke, expect and step, pokes + * + * @example + * {{{ + * + * class Adder(width:Int) extends Module { + * val io = new Bundle { + * val in0 : UInt(INPUT, width=width) + * val in1 : UInt(INPUT, width=width) + * val out : UInt(OUTPUT, width=width) + * } + * } + * class AdderTester extends UnitTester { + * val device_under_test = Module( new Adder(32) ) + * + * testBlock { + * poke(c.io.in0, 5) + * poke(c.io.in1, 7) + * expect(c.io.out, 12) + * } + * } + * }}} + */ +abstract class SteppedHWIOTester extends HWIOTester { + case class Step(input_map: mutable.HashMap[Data,BigInt], output_map: mutable.HashMap[Data,BigInt]) + + // Scala stuff + val test_actions = new ArrayBuffer[Step]() + step(1) // gives us a slot to put in our input and outputs from beginning + + def poke(io_port: Data, value: BigInt): Unit = { + require(io_port.toBits.dir == INPUT, s"poke error: $io_port not an input") + require(!test_actions.last.input_map.contains(io_port), + s"second poke to $io_port without step\nkeys ${test_actions.last.input_map.keys.mkString(",")}") + + test_actions.last.input_map(io_port) = value + } +// def poke(io_port: Data, bool_value: Boolean) = poke(io_port, if(bool_value) 1 else 0) + + def expect(io_port: Data, value: BigInt): Unit = { + require(io_port.toBits.dir == OUTPUT, s"expect error: $io_port not an output") + require(!test_actions.last.output_map.contains(io_port), s"second expect to $io_port without step") + + test_actions.last.output_map(io_port) = value + } + def expect(io_port: Data, bool_value: Boolean): Unit = expect(io_port, BigInt(if(bool_value) 1 else 0)) + + def step(number_of_cycles: Int): Unit = { + test_actions ++= Array.fill(number_of_cycles) { + new Step(new mutable.HashMap[Data, BigInt](), new mutable.HashMap[Data, BigInt]()) + } + } + + private def name(port: Data): String = io_info.port_to_name(port) + + //noinspection ScalaStyle + private def printStateTable(): Unit = { + val default_table_width = 80 + + if(io_info.ports_referenced.nonEmpty) { + val max_col_width = io_info.ports_referenced.map { port => + Array(name(port).length, port.getWidth / 4).max // width/4 is how wide value might be in hex + }.max + 2 + val string_col_template = s"%${max_col_width}s" +// val number_col_template = s"%${max_col_width}x" + + println("=" * default_table_width) + println("UnitTester state table") + println( + "%6s".format("step") + + io_info.dut_inputs.map { dut_input => string_col_template.format(name(dut_input)) }.mkString + + io_info.dut_outputs.map { dut_output => string_col_template.format(name(dut_output)) }.mkString + ) + println("-" * default_table_width) + /** + * prints out a table form of input and expected outputs + */ + def val_str(hash: mutable.HashMap[Data, BigInt], key: Data): String = { + if (hash.contains(key)) "%d".format(hash(key)) else "-" + } + test_actions.zipWithIndex.foreach { case (step, step_number) => + print("%6d".format(step_number)) + for (port <- io_info.dut_inputs) { + print(string_col_template.format(val_str(step.input_map, port))) + } + for (port <- io_info.dut_outputs) { + print(string_col_template.format(val_str(step.output_map, port))) + } + println() + } + println("=" * default_table_width) + } + } + + def createVectorsForInput(input_port: Data, counter: Counter): Unit = { + var default_value = BigInt(0) + val input_values = Vec( + test_actions.map { step => + default_value = step.input_map.getOrElse(input_port, default_value) + UInt(default_value, input_port.width) + } + ) + input_port := input_values(counter.value) + } + + def createVectorsAndTestsForOutput(output_port: Data, counter: Counter): Unit = { + val output_values = Vec( + test_actions.map { step => + output_port.fromBits(UInt(step.output_map.getOrElse(output_port, BigInt(0)))) + } + ) + val ok_to_test_output_values = Vec( + test_actions.map { step => + Bool(step.output_map.contains(output_port)) + } + ) + + when(ok_to_test_output_values(counter.value)) { + when(output_port.toBits() === output_values(counter.value).toBits()) { + logPrintfDebug(" passed step %d -- " + name(output_port) + ": %d\n", + counter.value, + output_port.toBits() + ) + }.otherwise { + printf(" failed on step %d -- port " + name(output_port) + ": %d expected %d\n", + counter.value, + output_port.toBits(), + output_values(counter.value).toBits() + ) + assert(Bool(false), "Failed test") + stop() + } + } + } + + private def processEvents(): Unit = { + test_actions.foreach { case step => + io_info.ports_referenced ++= step.input_map.keys + io_info.ports_referenced ++= step.output_map.keys + } + } + + override def finish(): Unit = { + io_info = new IOAccessor(device_under_test.io) + + processEvents() + + val pc = Counter(test_actions.length) + val done = Reg(init = Bool(false)) + + io_info.dut_inputs.foreach { port => port := UInt(0) } + + when(!done) { + io_info.dut_inputs.foreach { port => createVectorsForInput(port, pc) } + io_info.dut_outputs.foreach { port => createVectorsAndTestsForOutput(port, pc) } + + when(pc.inc()) { + printf(s"Stopping, end of tests, ${test_actions.length} steps\n") + done := Bool(true) + stop() + } + } + io_info.showPorts("".r) + printStateTable() + } +} diff --git a/src/main/scala/package.scala b/src/main/scala/package.scala new file mode 100644 index 00000000..18cc94e1 --- /dev/null +++ b/src/main/scala/package.scala @@ -0,0 +1,57 @@ +/* + Copyright (c) 2011 - 2016 The Regents of the University of + California (Regents). All Rights Reserved. Redistribution and use in + source and binary forms, with or without modification, are permitted + provided that the following conditions are met: + + * Redistributions of source code must retain the above + copyright notice, this list of conditions and the following + two paragraphs of disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + two paragraphs of disclaimer in the documentation and/or other materials + provided with the distribution. + * Neither the name of the Regents nor the names of its contributors + may be used to endorse or promote products derived from this + software without specific prior written permission. + + IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, + SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, + ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF + REGENTS HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF + ANY, PROVIDED HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION + TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR + MODIFICATIONS. +*/ + +package object Chisel { + import Chisel.Width + implicit class fromBigIntToLiteral(val x: BigInt) extends AnyVal { + def U: UInt = UInt(x) + def S: SInt = SInt(x) + } + implicit class fromIntToLiteral(val x: Int) extends AnyVal { + def U: UInt = UInt(BigInt(x)) + def S: SInt = SInt(BigInt(x)) + } + implicit class fromStringToLiteral(val x: String) extends AnyVal { + def U: UInt = UInt(x) + } + implicit class fromBooleanToLiteral(val x: Boolean) extends AnyVal { + def B: Bool = Bool(x) + } + // Chisel3 compatibility. + object Input { + def apply[T<:Data](source: T): T = source.asInput() + } + object Output { + def apply[T<:Data](source: T): T = source.asOutput() + } + object Flipped { + def apply[T<:Data](source: T): T = source.flip() + } +} diff --git a/src/main/scala/testers/BasicTester.scala b/src/main/scala/testers/BasicTester.scala new file mode 100644 index 00000000..d4990b12 --- /dev/null +++ b/src/main/scala/testers/BasicTester.scala @@ -0,0 +1,69 @@ +/* + Copyright (c) 2011 - 2016 The Regents of the University of + California (Regents). All Rights Reserved. Redistribution and use in + source and binary forms, with or without modification, are permitted + provided that the following conditions are met: + + * Redistributions of source code must retain the above + copyright notice, this list of conditions and the following + two paragraphs of disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + two paragraphs of disclaimer in the documentation and/or other materials + provided with the distribution. + * Neither the name of the Regents nor the names of its contributors + may be used to endorse or promote products derived from this + software without specific prior written permission. + + IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, + SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, + ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF + REGENTS HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF + ANY, PROVIDED HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION + TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR + MODIFICATIONS. +*/ + +package Chisel.testers +import Chisel._ + +// In Chisel2, the BasicTester has an IO interface which it uses to communicate with the Chisel2 Tester Scala code. +class BasicTester extends Module { + + val io = new Bundle { + val running = Bool(INPUT) + val error = Bool(OUTPUT) + val pc = UInt(OUTPUT, 32) + val done = Bool(OUTPUT) + } + + val setDone = Reg(init = Bool(false)) + val setError = Reg(init = Bool(false)) + + def popCount(n: Long): Int = n.toBinaryString.count(_=='1') + + /** Ends the test reporting success. + * + * Does not fire when in reset (defined as the encapsulating Module's + * reset). If your definition of reset is not the encapsulating Module's + * reset, you will need to gate this externally. + */ + def stop() { + when (!reset) { + setDone := Bool(true) + printf("STOP %d\n", io.done) + } + } + + def error(message: String = "") { + setError := Bool(true) + printf("ERROR: %s\n".format(message)) + stop() + } + + def finish(): Unit = {} +} diff --git a/src/main/scala/testers/TesterDriver.scala b/src/main/scala/testers/TesterDriver.scala new file mode 100644 index 00000000..d6c1a664 --- /dev/null +++ b/src/main/scala/testers/TesterDriver.scala @@ -0,0 +1,86 @@ +/* + Copyright (c) 2011 - 2016 The Regents of the University of + California (Regents). All Rights Reserved. Redistribution and use in + source and binary forms, with or without modification, are permitted + provided that the following conditions are met: + + * Redistributions of source code must retain the above + copyright notice, this list of conditions and the following + two paragraphs of disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + two paragraphs of disclaimer in the documentation and/or other materials + provided with the distribution. + * Neither the name of the Regents nor the names of its contributors + may be used to endorse or promote products derived from this + software without specific prior written permission. + + IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, + SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, + ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF + REGENTS HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF + ANY, PROVIDED HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION + TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR + MODIFICATIONS. +*/ + +package Chisel.testers + +import Chisel._ +import scala.io.Source +import scala.sys.process._ +import java.io._ + +// Wrapper to run Chisel3-style testers in Chisel2. + +object TesterDriver { + def execute(t: () => BasicTester)(implicit testArgs: Array[String]): Boolean = { + try { + // Construct the combined circuit, containing all the required + // poke()'s and expect()'s as arrays of data. + val mod = Driver(testArgs, finishWrapper(t), false) + if (Driver.isTesting) { + // Initialize a tester with tracing turned on. + val c = new Tester(mod, true) + // Run the testing circuit until we see io.done. + while(c.peek(mod.io.done) == 0) { + c.step(1) + } + val error = c.peek(mod.io.error) + val pc = c.peek(mod.io.pc) + if (error != 0) { + c.fail + } + + // Do an additional step to get any printf output. + c.step(1) + c.finish + } + Driver.done + true + } catch { + case e: Throwable => + println(e) + false + } + } + + def elaborate(t: () => BasicTester)(implicit testArgs: Array[String]): Module = { + val mod = Driver(testArgs, finishWrapper(t), false) + mod + } + + def finishWrapper(test: () => BasicTester): () => BasicTester = { + () => { + val tester = test() + tester.finish() + tester + } + } + + val backends = List("c") ++ {if (Driver.isVCSAvailable) "v" :: Nil else Nil} +} diff --git a/src/main/scala/when.scala b/src/main/scala/when.scala index 4a347853..dc44ed0b 100644 --- a/src/main/scala/when.scala +++ b/src/main/scala/when.scala @@ -1,5 +1,5 @@ /* - Copyright (c) 2011, 2012, 2013, 2014 The Regents of the University of + Copyright (c) 2011 - 2016 The Regents of the University of California (Regents). All Rights Reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: @@ -30,23 +30,44 @@ package Chisel +/** An object to create conditional logic + * See [[Chisel.when when]] for functions elsewhen and otherwise + * @example + * {{{ + * when ( myData === UInt(3) ) { + * ... // Some logic + * } .elsewhen ( myData === UInt(1) ) { + * ... // Some logic + * } .otherwise { + * ... // Some logic + * } }}} + */ object when { + // TODO: make private[Chisel]? + /** Execute a when block - internal do not use */ def execWhen(cond: Bool)(block: => Unit) { Module.current.whenConds.push(Module.current.whenCond && cond) block Module.current.whenConds.pop() } + /** @param cond condition to execute upon + * @param block a section of logic to enable if cond is true */ def apply(cond: Bool)(block: => Unit): when = { execWhen(cond){ block } new when(cond) } } +/** A class representing the when block + * Use [[Chisel.when$ when]] rather than this class directly + */ class when (prevCond: Bool) { + /** execute block when alternative cond is true */ def elsewhen (cond: Bool)(block: => Unit): when = { when.execWhen(!prevCond && cond){ block } new when(prevCond || cond); } + /** execute block by default */ def otherwise (block: => Unit) { val cond = !prevCond cond.canBeUsedAsDefault = !Module.current.hasWhenCond @@ -54,12 +75,24 @@ class when (prevCond: Bool) { } } +/** This is identical to [[Chisel.when when]] with the condition inverted */ object unless { def apply(c: Bool)(block: => Unit) { when (!c) { block } } } +/** Conditional logic to form a switch block + * @example + * {{{ ... // default values here + * switch ( myState ) { + * is( state1 ) { + * ... // some logic here + * } + * is( state2 ) { + * ... // some logic here + * } + * } }}}*/ object switch { def apply(c: Bits)(block: => Unit) { Module.current.switchKeys.push(c) @@ -68,14 +101,23 @@ object switch { } } +/** An object for separate cases in [[Chisel.switch switch]] + * It is equivalent to a [[Chisel.when$ when]] block comparing to the condition + * Use outside of a switch statement is illegal */ object is { + def apply(v: BitPat)(block: => Unit): Unit = + when (v === switchCond) { block } def apply(v: Bits)(block: => Unit): Unit = apply(Seq(v))(block) def apply(v: Bits, vr: Bits*)(block: => Unit): Unit = apply(v :: vr.toList)(block) - def apply(v: Iterable[Bits])(block: => Unit): Unit = { - val keys = Module.current.switchKeys - if (keys.isEmpty) ChiselError.error("The 'is' keyword may not be used outside of a switch.") - else if (!v.isEmpty) when (v.map(_ === keys.top).reduce(_||_)) { block } + def apply(v: Iterable[Bits])(block: => Unit): Unit = + when (v.map(_ === switchCond).fold(Bool(false))(_||_)) { block } + + private def switchCond = { + if (Module.current.switchKeys.isEmpty) { + ChiselError.error("The 'is' keyword may not be used outside of a switch.") + Bits(0) + } else Module.current.switchKeys.top } } diff --git a/src/test/resources/ConnectSuite_BindingTest_1.v b/src/test/resources/ConnectSuite_BindingTest_1.v new file mode 100644 index 00000000..c3e37860 --- /dev/null +++ b/src/test/resources/ConnectSuite_BindingTest_1.v @@ -0,0 +1,143 @@ +module ConnectSuite_CrossingBlock_1( + input [7:0] io_i1, + input [7:0] io_i2, + output[7:0] io_o1, + output[7:0] io_o2 +); + + wire[7:0] T0; + + + assign io_o2 = T0; + assign T0 = io_o1 + io_i2; + assign io_o1 = io_i1; +endmodule + +module ConnectSuite_BindingTestInternal_1( + input [7:0] io_in1, + input [7:0] io_in2, + input [7:0] io_in3, + input [7:0] io_in4, + output[7:0] io_out1, + output[7:0] io_out2, + output[7:0] io_out3, + output[7:0] io_out4, + output[7:0] io_out5, + output[7:0] io_out6, + output[7:0] io_out7, + output[7:0] io_out8, + output[7:0] io_out9 +); + + wire[7:0] T0; + wire[7:0] T1; + wire[7:0] T2; + wire[7:0] cb5_io_o1; + wire[7:0] cb5_io_o2; + wire[7:0] cb4_io_o1; + wire[7:0] cb4_io_o2; + wire[7:0] cb3_io_o1; + wire[7:0] cb3_io_o2; + wire[7:0] cb2_io_o1; + wire[7:0] cb2_io_o2; + wire[7:0] cb1_io_o1; + wire[7:0] cb1_io_o2; + + + assign T0 = io_in1 + 8'h1; + assign io_out9 = io_out7; + assign io_out8 = cb5_io_o2; + assign io_out7 = cb4_io_o2; + assign io_out6 = cb4_io_o1; + assign io_out5 = T1; + assign T1 = T2 + io_out4; + assign T2 = cb3_io_o1 + cb3_io_o2; + assign io_out4 = cb2_io_o2; + assign io_out3 = cb2_io_o1; + assign io_out2 = io_in2; + assign io_out1 = cb1_io_o1; + ConnectSuite_CrossingBlock_1 cb5( + .io_i1( io_in4 ), + .io_i2( cb5_io_o1 ), + .io_o1( cb5_io_o1 ), + .io_o2( cb5_io_o2 ) + ); + ConnectSuite_CrossingBlock_1 cb4( + .io_i1( io_in3 ), + .io_i2( io_in3 ), + .io_o1( cb4_io_o1 ), + .io_o2( cb4_io_o2 ) + ); + ConnectSuite_CrossingBlock_1 cb3( + .io_i1( T0 ), + .io_i2( cb1_io_o2 ), + .io_o1( cb3_io_o1 ), + .io_o2( cb3_io_o2 ) + ); + ConnectSuite_CrossingBlock_1 cb2( + .io_i1( cb1_io_o2 ), + .io_i2( io_out1 ), + .io_o1( cb2_io_o1 ), + .io_o2( cb2_io_o2 ) + ); + ConnectSuite_CrossingBlock_1 cb1( + .io_i1( io_in1 ), + .io_i2( io_in2 ), + .io_o1( cb1_io_o1 ), + .io_o2( cb1_io_o2 ) + ); +endmodule + +module ConnectSuite_BindingTest_1( + input [7:0] io_in1, + input [7:0] io_in2, + input [7:0] io_in3, + input [7:0] io_in4, + output[7:0] io_out1, + output[7:0] io_out2, + output[7:0] io_out3, + output[7:0] io_out4, + output[7:0] io_out5, + output[7:0] io_out6, + output[7:0] io_out7, + output[7:0] io_out8, + output[7:0] io_out9 +); + + wire[7:0] myTest_io_out1; + wire[7:0] myTest_io_out2; + wire[7:0] myTest_io_out3; + wire[7:0] myTest_io_out4; + wire[7:0] myTest_io_out5; + wire[7:0] myTest_io_out6; + wire[7:0] myTest_io_out7; + wire[7:0] myTest_io_out8; + wire[7:0] myTest_io_out9; + + + assign io_out9 = myTest_io_out9; + assign io_out8 = myTest_io_out8; + assign io_out7 = myTest_io_out7; + assign io_out6 = myTest_io_out6; + assign io_out5 = myTest_io_out5; + assign io_out4 = myTest_io_out4; + assign io_out3 = myTest_io_out3; + assign io_out2 = myTest_io_out2; + assign io_out1 = myTest_io_out1; + ConnectSuite_BindingTestInternal_1 myTest( + .io_in1( io_in1 ), + .io_in2( io_in2 ), + .io_in3( io_in3 ), + .io_in4( io_in4 ), + .io_out1( myTest_io_out1 ), + .io_out2( myTest_io_out2 ), + .io_out3( myTest_io_out3 ), + .io_out4( myTest_io_out4 ), + .io_out5( myTest_io_out5 ), + .io_out6( myTest_io_out6 ), + .io_out7( myTest_io_out7 ), + .io_out8( myTest_io_out8 ), + .io_out9( myTest_io_out9 ) + ); +endmodule + diff --git a/src/test/resources/ConnectSuite_SubmoduleInputUse_1.v b/src/test/resources/ConnectSuite_SubmoduleInputUse_1.v new file mode 100644 index 00000000..33451473 --- /dev/null +++ b/src/test/resources/ConnectSuite_SubmoduleInputUse_1.v @@ -0,0 +1,46 @@ +module ConnectSuite_PassThrough_1( + input [7:0] io_ptin, + output[7:0] io_ptout +); + + + + assign io_ptout = io_ptin; +endmodule + +module ConnectSuite_SubmoduleInputUse_1( + input [7:0] io_in, + output[7:0] io_out1, + output[7:0] io_out2a, + output[7:0] io_out2b, + output[7:0] io_out3 +); + + wire[7:0] pt3_io_ptout; + wire[7:0] pt2b_io_ptout; + wire[7:0] pt2a_io_ptout; + wire[7:0] pt1_io_ptout; + + + assign io_out3 = pt3_io_ptout; + assign io_out2b = pt2b_io_ptout; + assign io_out2a = pt2a_io_ptout; + assign io_out1 = pt1_io_ptout; + ConnectSuite_PassThrough_1 pt3( + .io_ptin( io_out2b ), + .io_ptout( pt3_io_ptout ) + ); + ConnectSuite_PassThrough_1 pt2b( + .io_ptin( pt1_io_ptout ), + .io_ptout( pt2b_io_ptout ) + ); + ConnectSuite_PassThrough_1 pt2a( + .io_ptin( pt1_io_ptout ), + .io_ptout( pt2a_io_ptout ) + ); + ConnectSuite_PassThrough_1 pt1( + .io_ptin( io_in ), + .io_ptout( pt1_io_ptout ) + ); +endmodule + diff --git a/src/test/resources/ConnectSuite_UnconnectedIOs_1.h b/src/test/resources/ConnectSuite_UnconnectedIOs_1.h new file mode 100644 index 00000000..30f14a7e --- /dev/null +++ b/src/test/resources/ConnectSuite_UnconnectedIOs_1.h @@ -0,0 +1,41 @@ +#ifndef __ConnectSuite_UnconnectedIOs_1__ +#define __ConnectSuite_UnconnectedIOs_1__ + +#include "emulator.h" + +class ConnectSuite_UnconnectedIOs_1_t : public mod_t { + private: + val_t __rand_seed; + void __srand(val_t seed) { __rand_seed = seed; } + val_t __rand_val() { return ::__rand_val(&__rand_seed); } + public: + dat_t<1> ConnectSuite_UnconnectedIOs_1__io_in; + dat_t<1> ConnectSuite_UnconnectedIOs_1_sub__io_in; + dat_t<1> ConnectSuite_UnconnectedIOs_1_sub__reset; + dat_t<1> T0; + dat_t<1> ConnectSuite_UnconnectedIOs_1_sub__r; + dat_t<1> ConnectSuite_UnconnectedIOs_1_sub__io_ncOut; + dat_t<1> ConnectSuite_UnconnectedIOs_1_sub__io_out; + dat_t<1> ConnectSuite_UnconnectedIOs_1__io_out; + dat_t<1> ConnectSuite_UnconnectedIOs_1__io_ncOut; + dat_t<1> reset; + dat_t<1> ConnectSuite_UnconnectedIOs_1__regs_0; + dat_t<1> ConnectSuite_UnconnectedIOs_1__regs_1; + dat_t<1> ConnectSuite_UnconnectedIOs_1__regs_2; + dat_t<1> ConnectSuite_UnconnectedIOs_1__io_ncIn; + clk_t clk; + + void init ( val_t rand_init = 0 ); + void clock_lo ( dat_t<1> reset, bool assert_fire=true ); + void clock_hi ( dat_t<1> reset ); + int clock ( dat_t<1> reset ); + void print ( FILE* f ); + void print ( std::ostream& s ); + void dump ( FILE* f, val_t t, dat_t<1> reset=LIT<1>(0) ); + void dump_init ( FILE* f ); + +}; + + + +#endif diff --git a/src/test/resources/ConnectWireSuite_BindingTest_1.v b/src/test/resources/ConnectWireSuite_BindingTest_1.v new file mode 100644 index 00000000..6961c2a3 --- /dev/null +++ b/src/test/resources/ConnectWireSuite_BindingTest_1.v @@ -0,0 +1,143 @@ +module ConnectWireSuite_CrossingBlock_1( + input [7:0] io_i1, + input [7:0] io_i2, + output[7:0] io_o1, + output[7:0] io_o2 +); + + wire[7:0] T0; + + + assign io_o2 = T0; + assign T0 = io_o1 + io_i2; + assign io_o1 = io_i1; +endmodule + +module ConnectWireSuite_BindingTestInternal_1( + input [7:0] io_in1, + input [7:0] io_in2, + input [7:0] io_in3, + input [7:0] io_in4, + output[7:0] io_out1, + output[7:0] io_out2, + output[7:0] io_out3, + output[7:0] io_out4, + output[7:0] io_out5, + output[7:0] io_out6, + output[7:0] io_out7, + output[7:0] io_out8, + output[7:0] io_out9 +); + + wire[7:0] T0; + wire[7:0] T1; + wire[7:0] T2; + wire[7:0] cb5_io_o1; + wire[7:0] cb5_io_o2; + wire[7:0] cb4_io_o1; + wire[7:0] cb4_io_o2; + wire[7:0] cb3_io_o1; + wire[7:0] cb3_io_o2; + wire[7:0] cb2_io_o1; + wire[7:0] cb2_io_o2; + wire[7:0] cb1_io_o1; + wire[7:0] cb1_io_o2; + + + assign T0 = io_in1 + 8'h1; + assign io_out9 = io_out7; + assign io_out8 = cb5_io_o2; + assign io_out7 = cb4_io_o2; + assign io_out6 = cb4_io_o1; + assign io_out5 = T1; + assign T1 = T2 + io_out4; + assign T2 = cb3_io_o1 + cb3_io_o2; + assign io_out4 = cb2_io_o2; + assign io_out3 = cb2_io_o1; + assign io_out2 = io_in2; + assign io_out1 = cb1_io_o1; + ConnectWireSuite_CrossingBlock_1 cb5( + .io_i1( io_in4 ), + .io_i2( cb5_io_o1 ), + .io_o1( cb5_io_o1 ), + .io_o2( cb5_io_o2 ) + ); + ConnectWireSuite_CrossingBlock_1 cb4( + .io_i1( io_in3 ), + .io_i2( io_in3 ), + .io_o1( cb4_io_o1 ), + .io_o2( cb4_io_o2 ) + ); + ConnectWireSuite_CrossingBlock_1 cb3( + .io_i1( T0 ), + .io_i2( cb1_io_o2 ), + .io_o1( cb3_io_o1 ), + .io_o2( cb3_io_o2 ) + ); + ConnectWireSuite_CrossingBlock_1 cb2( + .io_i1( cb1_io_o2 ), + .io_i2( io_out1 ), + .io_o1( cb2_io_o1 ), + .io_o2( cb2_io_o2 ) + ); + ConnectWireSuite_CrossingBlock_1 cb1( + .io_i1( io_in1 ), + .io_i2( io_in2 ), + .io_o1( cb1_io_o1 ), + .io_o2( cb1_io_o2 ) + ); +endmodule + +module ConnectWireSuite_BindingTest_1( + input [7:0] io_in1, + input [7:0] io_in2, + input [7:0] io_in3, + input [7:0] io_in4, + output[7:0] io_out1, + output[7:0] io_out2, + output[7:0] io_out3, + output[7:0] io_out4, + output[7:0] io_out5, + output[7:0] io_out6, + output[7:0] io_out7, + output[7:0] io_out8, + output[7:0] io_out9 +); + + wire[7:0] myTest_io_out1; + wire[7:0] myTest_io_out2; + wire[7:0] myTest_io_out3; + wire[7:0] myTest_io_out4; + wire[7:0] myTest_io_out5; + wire[7:0] myTest_io_out6; + wire[7:0] myTest_io_out7; + wire[7:0] myTest_io_out8; + wire[7:0] myTest_io_out9; + + + assign io_out9 = myTest_io_out9; + assign io_out8 = myTest_io_out8; + assign io_out7 = myTest_io_out7; + assign io_out6 = myTest_io_out6; + assign io_out5 = myTest_io_out5; + assign io_out4 = myTest_io_out4; + assign io_out3 = myTest_io_out3; + assign io_out2 = myTest_io_out2; + assign io_out1 = myTest_io_out1; + ConnectWireSuite_BindingTestInternal_1 myTest( + .io_in1( io_in1 ), + .io_in2( io_in2 ), + .io_in3( io_in3 ), + .io_in4( io_in4 ), + .io_out1( myTest_io_out1 ), + .io_out2( myTest_io_out2 ), + .io_out3( myTest_io_out3 ), + .io_out4( myTest_io_out4 ), + .io_out5( myTest_io_out5 ), + .io_out6( myTest_io_out6 ), + .io_out7( myTest_io_out7 ), + .io_out8( myTest_io_out8 ), + .io_out9( myTest_io_out9 ) + ); +endmodule + diff --git a/src/test/resources/DelaySuite_MemReadModule_1.v b/src/test/resources/DelaySuite_MemReadModule_1.v index 57fe98a8..ec9e9789 100644 --- a/src/test/resources/DelaySuite_MemReadModule_1.v +++ b/src/test/resources/DelaySuite_MemReadModule_1.v @@ -20,6 +20,6 @@ module DelaySuite_MemReadModule_1(input clk, assign io_out = T0; assign T0 = mem[T1]; - assign T1 = io_addr[2'h2:1'h0]; + assign T1 = io_addr[2:0]; endmodule diff --git a/src/test/resources/DelaySuite_ROMModule_1.cpp b/src/test/resources/DelaySuite_ROMModule_1.cpp index a4ab27b7..23577111 100644 --- a/src/test/resources/DelaySuite_ROMModule_1.cpp +++ b/src/test/resources/DelaySuite_ROMModule_1.cpp @@ -2,54 +2,36 @@ void DelaySuite_ROMModule_1_t::init ( val_t rand_init ) { this->__srand(rand_init); - T0.randomize(&__rand_seed); - { T0.put(0, 0, 0x1L);} - { T0.put(1, 0, 0x2L);} - { T0.put(2, 0, 0x3L);} + T1.randomize(&__rand_seed); + { T1.put(0, 0, 0x1L);} + { T1.put(1, 0, 0x2L);} + { T1.put(2, 0, 0x3L);} + clk.len = 1; + clk.cnt = 0; + clk.values[0] = 0; } int DelaySuite_ROMModule_1_t::clock ( dat_t<1> reset ) { uint32_t min = ((uint32_t)1<<31)-1; - if (clk_cnt < min) min = clk_cnt; - clk_cnt-=min; - if (clk_cnt == 0) clock_hi( reset ); - if (clk_cnt == 0) clock_lo( reset ); - if (clk_cnt == 0) clk_cnt = clk; + if (clk.cnt < min) min = clk.cnt; + clk.cnt-=min; + if (clk.cnt == 0) clock_lo( reset ); + if (!reset.to_bool()) print( std::cerr ); + if (clk.cnt == 0) clock_hi( reset ); + if (clk.cnt == 0) clk.cnt = clk.len; return min; } -mod_t* DelaySuite_ROMModule_1_t::clone() { - mod_t* cloned = new DelaySuite_ROMModule_1_t(*this); - return cloned; -} -bool DelaySuite_ROMModule_1_t::set_circuit_from ( mod_t* src ) { - DelaySuite_ROMModule_1_t* mod_typed = dynamic_cast(src); - assert(mod_typed); - T0 = mod_typed->T0; - DelaySuite_ROMModule_1__io_addr = mod_typed->DelaySuite_ROMModule_1__io_addr; - DelaySuite_ROMModule_1__io_out = mod_typed->DelaySuite_ROMModule_1__io_out; - clk = mod_typed->clk; - clk_cnt = mod_typed->clk_cnt; - return true; -} void DelaySuite_ROMModule_1_t::print ( FILE* f ) { } void DelaySuite_ROMModule_1_t::print ( std::ostream& s ) { } void DelaySuite_ROMModule_1_t::dump_init ( FILE* f ) { } -void DelaySuite_ROMModule_1_t::dump ( FILE* f, int t ) { +void DelaySuite_ROMModule_1_t::dump ( FILE* f, val_t t, dat_t<1> reset ) { } -void DelaySuite_ROMModule_1_t::clock_lo ( dat_t<1> reset ) { - val_t T1; - { T1 = T0.get(DelaySuite_ROMModule_1__io_addr.values[0], 0);} - { DelaySuite_ROMModule_1__io_out.values[0] = T1;} +void DelaySuite_ROMModule_1_t::clock_lo ( dat_t<1> reset, bool assert_fire ) { + val_t T0; + { T0 = T1.get(DelaySuite_ROMModule_1__io_addr.values[0], 0);} + { DelaySuite_ROMModule_1__io_out.values[0] = T0;} } void DelaySuite_ROMModule_1_t::clock_hi ( dat_t<1> reset ) { } -void DelaySuite_ROMModule_1_api_t::init_mapping_table ( ) { - dat_table.clear(); - mem_table.clear(); - DelaySuite_ROMModule_1_t* mod_typed = dynamic_cast(module); - assert(mod_typed); - dat_table["DelaySuite_ROMModule_1.io_addr"] = new dat_api<2>(&mod_typed->DelaySuite_ROMModule_1__io_addr, "DelaySuite_ROMModule_1.io_addr", ""); - dat_table["DelaySuite_ROMModule_1.io_out"] = new dat_api<4>(&mod_typed->DelaySuite_ROMModule_1__io_out, "DelaySuite_ROMModule_1.io_out", ""); -} diff --git a/src/test/resources/DelaySuite_ROMModule_1.h b/src/test/resources/DelaySuite_ROMModule_1.h index e8d399ec..d1896526 100644 --- a/src/test/resources/DelaySuite_ROMModule_1.h +++ b/src/test/resources/DelaySuite_ROMModule_1.h @@ -11,27 +11,20 @@ class DelaySuite_ROMModule_1_t : public mod_t { public: dat_t<2> DelaySuite_ROMModule_1__io_addr; dat_t<4> DelaySuite_ROMModule_1__io_out; - mem_t<4,3> T0; - int clk; - int clk_cnt; + mem_t<4,3> T1; + clk_t clk; void init ( val_t rand_init = 0 ); - void clock_lo ( dat_t<1> reset ); + void clock_lo ( dat_t<1> reset, bool assert_fire=true ); void clock_hi ( dat_t<1> reset ); int clock ( dat_t<1> reset ); - mod_t* clone(); - bool set_circuit_from(mod_t* src); void print ( FILE* f ); void print ( std::ostream& s ); - void dump ( FILE* f, int t ); + void dump ( FILE* f, val_t t, dat_t<1> reset=LIT<1>(0) ); void dump_init ( FILE* f ); }; -class DelaySuite_ROMModule_1_api_t : public mod_api_t { - void init_mapping_table(); -}; - #endif diff --git a/src/test/resources/DelaySuite_ReadCondMaskedWrite_1.v b/src/test/resources/DelaySuite_ReadCondMaskedWrite_1.v index 33a1922a..00dd4aae 100644 --- a/src/test/resources/DelaySuite_ReadCondMaskedWrite_1.v +++ b/src/test/resources/DelaySuite_ReadCondMaskedWrite_1.v @@ -29,8 +29,8 @@ module DelaySuite_ReadCondMaskedWrite_1(input clk, assign T2 = T4 | T3; assign T3 = T0 & 32'hff; assign T4 = T0 & 32'hff00; - assign T5 = io_addr[2'h2:1'h0]; - assign T6 = io_addr[2'h2:1'h0]; + assign T5 = io_addr[2:0]; + assign T6 = io_addr[2:0]; always @(posedge clk) begin if (io_enable) diff --git a/src/test/resources/DelaySuite_ReadCondWriteModule_1.v b/src/test/resources/DelaySuite_ReadCondWriteModule_1.v index ab815592..30ccda91 100644 --- a/src/test/resources/DelaySuite_ReadCondWriteModule_1.v +++ b/src/test/resources/DelaySuite_ReadCondWriteModule_1.v @@ -31,13 +31,13 @@ module DelaySuite_ReadCondWriteModule_1(input clk, assign io_out = T0; assign T0 = mem[T10]; assign T2 = mem[T7]; - assign T7 = T3[2'h2:1'h0]; + assign T7 = T3[2:0]; assign T3 = io_addr + 32'h4; assign T4 = io_enable ^ 1'h1; - assign T8 = io_addr[2'h2:1'h0]; + assign T8 = io_addr[2:0]; assign T6 = T0 + 32'h1; - assign T9 = io_addr[2'h2:1'h0]; - assign T10 = io_addr[2'h2:1'h0]; + assign T9 = io_addr[2:0]; + assign T10 = io_addr[2:0]; always @(posedge clk) begin if (T4) diff --git a/src/test/resources/DelaySuite_ReadWriteModule_1.v b/src/test/resources/DelaySuite_ReadWriteModule_1.v index 2aac57e5..94f354f0 100644 --- a/src/test/resources/DelaySuite_ReadWriteModule_1.v +++ b/src/test/resources/DelaySuite_ReadWriteModule_1.v @@ -24,8 +24,8 @@ module DelaySuite_ReadWriteModule_1(input clk, assign io_out = T0; assign T0 = mem[T4]; assign T2 = T0 + 32'h1; - assign T3 = io_addr[2'h2:1'h0]; - assign T4 = io_addr[2'h2:1'h0]; + assign T3 = io_addr[2:0]; + assign T4 = io_addr[2:0]; always @(posedge clk) begin if (1'h1) diff --git a/src/test/resources/DelaySuite_SeqReadBundle_1.cpp b/src/test/resources/DelaySuite_SeqReadBundle_1.cpp index 97e82cf1..f64468c2 100644 --- a/src/test/resources/DelaySuite_SeqReadBundle_1.cpp +++ b/src/test/resources/DelaySuite_SeqReadBundle_1.cpp @@ -4,56 +4,29 @@ void DelaySuite_SeqReadBundle_1_t::init ( val_t rand_init ) { this->__srand(rand_init); DelaySuite_SeqReadBundle_1__R9.randomize(&__rand_seed); DelaySuite_SeqReadBundle_1__mem.randomize(&__rand_seed); + clk.len = 1; + clk.cnt = 0; + clk.values[0] = 0; } int DelaySuite_SeqReadBundle_1_t::clock ( dat_t<1> reset ) { uint32_t min = ((uint32_t)1<<31)-1; - if (clk_cnt < min) min = clk_cnt; - clk_cnt-=min; - if (clk_cnt == 0) clock_hi( reset ); - if (clk_cnt == 0) clock_lo( reset ); - if (clk_cnt == 0) clk_cnt = clk; + if (clk.cnt < min) min = clk.cnt; + clk.cnt-=min; + if (clk.cnt == 0) clock_lo( reset ); + if (!reset.to_bool()) print( std::cerr ); + if (clk.cnt == 0) clock_hi( reset ); + if (clk.cnt == 0) clk.cnt = clk.len; return min; } -mod_t* DelaySuite_SeqReadBundle_1_t::clone() { - mod_t* cloned = new DelaySuite_SeqReadBundle_1_t(*this); - return cloned; -} -bool DelaySuite_SeqReadBundle_1_t::set_circuit_from ( mod_t* src ) { - DelaySuite_SeqReadBundle_1_t* mod_typed = dynamic_cast(src); - assert(mod_typed); - DelaySuite_SeqReadBundle_1__io_out_1_a_a = mod_typed->DelaySuite_SeqReadBundle_1__io_out_1_a_a; - DelaySuite_SeqReadBundle_1__io_out_1_a_b = mod_typed->DelaySuite_SeqReadBundle_1__io_out_1_a_b; - DelaySuite_SeqReadBundle_1__io_out_1_a_b_ = mod_typed->DelaySuite_SeqReadBundle_1__io_out_1_a_b_; - DelaySuite_SeqReadBundle_1__io_out_0_a_a = mod_typed->DelaySuite_SeqReadBundle_1__io_out_0_a_a; - DelaySuite_SeqReadBundle_1__io_out_0_a_b = mod_typed->DelaySuite_SeqReadBundle_1__io_out_0_a_b; - DelaySuite_SeqReadBundle_1__io_raddr = mod_typed->DelaySuite_SeqReadBundle_1__io_raddr; - DelaySuite_SeqReadBundle_1__io_ren = mod_typed->DelaySuite_SeqReadBundle_1__io_ren; - T6 = mod_typed->T6; - DelaySuite_SeqReadBundle_1__R9 = mod_typed->DelaySuite_SeqReadBundle_1__R9; - DelaySuite_SeqReadBundle_1__io_in_0_a_b_ = mod_typed->DelaySuite_SeqReadBundle_1__io_in_0_a_b_; - DelaySuite_SeqReadBundle_1__io_in_0_a_b = mod_typed->DelaySuite_SeqReadBundle_1__io_in_0_a_b; - DelaySuite_SeqReadBundle_1__io_in_0_a_a = mod_typed->DelaySuite_SeqReadBundle_1__io_in_0_a_a; - DelaySuite_SeqReadBundle_1__io_in_1_a_b_ = mod_typed->DelaySuite_SeqReadBundle_1__io_in_1_a_b_; - DelaySuite_SeqReadBundle_1__io_in_1_a_b = mod_typed->DelaySuite_SeqReadBundle_1__io_in_1_a_b; - DelaySuite_SeqReadBundle_1__io_in_1_a_a = mod_typed->DelaySuite_SeqReadBundle_1__io_in_1_a_a; - T12 = mod_typed->T12; - DelaySuite_SeqReadBundle_1__io_wen = mod_typed->DelaySuite_SeqReadBundle_1__io_wen; - DelaySuite_SeqReadBundle_1__io_waddr = mod_typed->DelaySuite_SeqReadBundle_1__io_waddr; - DelaySuite_SeqReadBundle_1__mem = mod_typed->DelaySuite_SeqReadBundle_1__mem; - DelaySuite_SeqReadBundle_1__io_out_0_a_b_ = mod_typed->DelaySuite_SeqReadBundle_1__io_out_0_a_b_; - clk = mod_typed->clk; - clk_cnt = mod_typed->clk_cnt; - return true; -} void DelaySuite_SeqReadBundle_1_t::print ( FILE* f ) { } void DelaySuite_SeqReadBundle_1_t::print ( std::ostream& s ) { } void DelaySuite_SeqReadBundle_1_t::dump_init ( FILE* f ) { } -void DelaySuite_SeqReadBundle_1_t::dump ( FILE* f, int t ) { +void DelaySuite_SeqReadBundle_1_t::dump ( FILE* f, val_t t, dat_t<1> reset ) { } -void DelaySuite_SeqReadBundle_1_t::clock_lo ( dat_t<1> reset ) { +void DelaySuite_SeqReadBundle_1_t::clock_lo ( dat_t<1> reset, bool assert_fire ) { val_t T0[2]; { T0[0] = DelaySuite_SeqReadBundle_1__mem.get(DelaySuite_SeqReadBundle_1__R9.values[0], 0); T0[1] = DelaySuite_SeqReadBundle_1__mem.get(DelaySuite_SeqReadBundle_1__R9.values[0], 1);} val_t T1; @@ -98,27 +71,3 @@ void DelaySuite_SeqReadBundle_1_t::clock_hi ( dat_t<1> reset ) { { if (DelaySuite_SeqReadBundle_1__io_wen.values[0]) DelaySuite_SeqReadBundle_1__mem.put(DelaySuite_SeqReadBundle_1__io_waddr.values[0], 0, T12.values[0]); if (DelaySuite_SeqReadBundle_1__io_wen.values[0]) DelaySuite_SeqReadBundle_1__mem.put(DelaySuite_SeqReadBundle_1__io_waddr.values[0], 1, T12.values[1]);} DelaySuite_SeqReadBundle_1__R9 = T6; } -void DelaySuite_SeqReadBundle_1_api_t::init_mapping_table ( ) { - dat_table.clear(); - mem_table.clear(); - DelaySuite_SeqReadBundle_1_t* mod_typed = dynamic_cast(module); - assert(mod_typed); - dat_table["DelaySuite_SeqReadBundle_1.io_out_1_a_a"] = new dat_api<8>(&mod_typed->DelaySuite_SeqReadBundle_1__io_out_1_a_a, "DelaySuite_SeqReadBundle_1.io_out_1_a_a", ""); - dat_table["DelaySuite_SeqReadBundle_1.io_out_1_a_b"] = new dat_api<16>(&mod_typed->DelaySuite_SeqReadBundle_1__io_out_1_a_b, "DelaySuite_SeqReadBundle_1.io_out_1_a_b", ""); - dat_table["DelaySuite_SeqReadBundle_1.io_out_1_a_b_"] = new dat_api<32>(&mod_typed->DelaySuite_SeqReadBundle_1__io_out_1_a_b_, "DelaySuite_SeqReadBundle_1.io_out_1_a_b_", ""); - dat_table["DelaySuite_SeqReadBundle_1.io_out_0_a_a"] = new dat_api<8>(&mod_typed->DelaySuite_SeqReadBundle_1__io_out_0_a_a, "DelaySuite_SeqReadBundle_1.io_out_0_a_a", ""); - dat_table["DelaySuite_SeqReadBundle_1.io_out_0_a_b"] = new dat_api<16>(&mod_typed->DelaySuite_SeqReadBundle_1__io_out_0_a_b, "DelaySuite_SeqReadBundle_1.io_out_0_a_b", ""); - dat_table["DelaySuite_SeqReadBundle_1.io_raddr"] = new dat_api<4>(&mod_typed->DelaySuite_SeqReadBundle_1__io_raddr, "DelaySuite_SeqReadBundle_1.io_raddr", ""); - dat_table["DelaySuite_SeqReadBundle_1.io_ren"] = new dat_api<1>(&mod_typed->DelaySuite_SeqReadBundle_1__io_ren, "DelaySuite_SeqReadBundle_1.io_ren", ""); - dat_table["DelaySuite_SeqReadBundle_1.R9"] = new dat_api<4>(&mod_typed->DelaySuite_SeqReadBundle_1__R9, "DelaySuite_SeqReadBundle_1.R9", ""); - dat_table["DelaySuite_SeqReadBundle_1.io_in_0_a_b_"] = new dat_api<32>(&mod_typed->DelaySuite_SeqReadBundle_1__io_in_0_a_b_, "DelaySuite_SeqReadBundle_1.io_in_0_a_b_", ""); - dat_table["DelaySuite_SeqReadBundle_1.io_in_0_a_b"] = new dat_api<16>(&mod_typed->DelaySuite_SeqReadBundle_1__io_in_0_a_b, "DelaySuite_SeqReadBundle_1.io_in_0_a_b", ""); - dat_table["DelaySuite_SeqReadBundle_1.io_in_0_a_a"] = new dat_api<8>(&mod_typed->DelaySuite_SeqReadBundle_1__io_in_0_a_a, "DelaySuite_SeqReadBundle_1.io_in_0_a_a", ""); - dat_table["DelaySuite_SeqReadBundle_1.io_in_1_a_b_"] = new dat_api<32>(&mod_typed->DelaySuite_SeqReadBundle_1__io_in_1_a_b_, "DelaySuite_SeqReadBundle_1.io_in_1_a_b_", ""); - dat_table["DelaySuite_SeqReadBundle_1.io_in_1_a_b"] = new dat_api<16>(&mod_typed->DelaySuite_SeqReadBundle_1__io_in_1_a_b, "DelaySuite_SeqReadBundle_1.io_in_1_a_b", ""); - dat_table["DelaySuite_SeqReadBundle_1.io_in_1_a_a"] = new dat_api<8>(&mod_typed->DelaySuite_SeqReadBundle_1__io_in_1_a_a, "DelaySuite_SeqReadBundle_1.io_in_1_a_a", ""); - dat_table["DelaySuite_SeqReadBundle_1.io_wen"] = new dat_api<1>(&mod_typed->DelaySuite_SeqReadBundle_1__io_wen, "DelaySuite_SeqReadBundle_1.io_wen", ""); - dat_table["DelaySuite_SeqReadBundle_1.io_waddr"] = new dat_api<4>(&mod_typed->DelaySuite_SeqReadBundle_1__io_waddr, "DelaySuite_SeqReadBundle_1.io_waddr", ""); - mem_table["DelaySuite_SeqReadBundle_1.mem"] = new mem_api<112, 16>(&mod_typed->DelaySuite_SeqReadBundle_1__mem, "DelaySuite_SeqReadBundle_1.mem", ""); - dat_table["DelaySuite_SeqReadBundle_1.io_out_0_a_b_"] = new dat_api<32>(&mod_typed->DelaySuite_SeqReadBundle_1__io_out_0_a_b_, "DelaySuite_SeqReadBundle_1.io_out_0_a_b_", ""); -} diff --git a/src/test/resources/DelaySuite_SeqReadBundle_1.h b/src/test/resources/DelaySuite_SeqReadBundle_1.h index 36497780..82bb9383 100644 --- a/src/test/resources/DelaySuite_SeqReadBundle_1.h +++ b/src/test/resources/DelaySuite_SeqReadBundle_1.h @@ -12,8 +12,8 @@ class DelaySuite_SeqReadBundle_1_t : public mod_t { dat_t<1> DelaySuite_SeqReadBundle_1__io_ren; dat_t<1> DelaySuite_SeqReadBundle_1__io_wen; dat_t<4> DelaySuite_SeqReadBundle_1__io_raddr; - dat_t<4> T0; - dat_t<4> R1; + dat_t<4> T6; + dat_t<4> DelaySuite_SeqReadBundle_1__R9; dat_t<4> DelaySuite_SeqReadBundle_1__io_waddr; dat_t<8> DelaySuite_SeqReadBundle_1__io_out_1_a_a; dat_t<8> DelaySuite_SeqReadBundle_1__io_out_0_a_a; @@ -27,28 +27,21 @@ class DelaySuite_SeqReadBundle_1_t : public mod_t { dat_t<32> DelaySuite_SeqReadBundle_1__io_in_0_a_b_; dat_t<32> DelaySuite_SeqReadBundle_1__io_in_1_a_b_; dat_t<32> DelaySuite_SeqReadBundle_1__io_out_0_a_b_; - dat_t<112> T2; + dat_t<112> T12; mem_t<112,16> DelaySuite_SeqReadBundle_1__mem; - int clk; - int clk_cnt; + clk_t clk; void init ( val_t rand_init = 0 ); - void clock_lo ( dat_t<1> reset ); + void clock_lo ( dat_t<1> reset, bool assert_fire=true ); void clock_hi ( dat_t<1> reset ); int clock ( dat_t<1> reset ); - mod_t* clone(); - bool set_circuit_from(mod_t* src); void print ( FILE* f ); void print ( std::ostream& s ); - void dump ( FILE* f, int t ); + void dump ( FILE* f, val_t t, dat_t<1> reset=LIT<1>(0) ); void dump_init ( FILE* f ); }; -class DelaySuite_SeqReadBundle_1_api_t : public mod_api_t { - void init_mapping_table(); -}; - #endif diff --git a/src/test/resources/FullAdderSysCdriver.cpp b/src/test/resources/FullAdderSysCdriver.cpp new file mode 100644 index 00000000..4de7eecb --- /dev/null +++ b/src/test/resources/FullAdderSysCdriver.cpp @@ -0,0 +1,74 @@ +#include +using namespace std; +using namespace sc_core; +using namespace sc_dt; +#include "SCWrappedFullAdder.cpp" +#include + +SC_MODULE(Generator){ + sc_fifo out; + sc_fifo src; + + SC_HAS_PROCESS(Generator); + Generator(sc_module_name a_name) : sc_module(a_name), out(1){ + SC_THREAD(generator_thread); + } + + void generator_thread(void){ + cs_io_in_bits_i dat; + + for(int i=1; i<100; i++){ + dat.FullAdder__io_in_bits_a = rand() & 0x01; + dat.FullAdder__io_in_bits_b = rand() & 0x01; + dat.FullAdder__io_in_bits_cin = rand() & 0x01; + out.write(dat); + src.write(dat); + wait(20.0, SC_SEC); + } + } +}; + +SC_MODULE(Eater){ + sc_fifo *src; + sc_fifo* in; + + SC_HAS_PROCESS(Eater); + Eater(sc_module_name a_name) : sc_module(a_name){ + SC_THREAD(eater_thread); + } + + void eater_thread(void){ + while(true){ + cs_io_in_bits_i test = src->read(); + printf("Input a = %llu\n", test.FullAdder__io_in_bits_a.values[0]); + printf("Input b = %llu\n", test.FullAdder__io_in_bits_b.values[0]); + printf("Input cin = %llu\n", test.FullAdder__io_in_bits_cin.values[0]); + cs_io_out_bits_o data = in->read(); + printf("Output sum = %llu\n", data.FullAdder__io_out_bits_sum.values[0]); + printf("Output cout = %llu\n", data.FullAdder__io_out_bits_cout.values[0]); + } + } +}; + +int sc_main(int sc_argc, char* sc_argv[1]) +{ + // See if we've been provided with a SEED. + for (int i = 0; i < sc_argc; i += 1) { + if (strcmp(sc_argv[i], "--SEED") == 0) { + srand(atoi(sc_argv[i + 1])); + } + } + //Create components + Generator generator("mygenerator"); + Eater eater("muncher"); + SCWrappedFullAdder filter("myfilter"); + + //Connect components + filter.in = &generator.out; + eater.in = filter.out; + eater.src = &generator.src; + + //Simulate + sc_start(1000.0, SC_SEC); + return 0; +} diff --git a/src/test/resources/MultiClockSuite_ClockDec_1.v b/src/test/resources/MultiClockSuite_ClockDec_1.v new file mode 100644 index 00000000..d568b44e --- /dev/null +++ b/src/test/resources/MultiClockSuite_ClockDec_1.v @@ -0,0 +1,30 @@ +module MultiClockSuite_ClockDec_1(input myClock, input myNewReset, + input io_in, + output io_out +); + + reg reg_; + wire T1; + +`ifndef SYNTHESIS +// synthesis translate_off + integer initvar; + initial begin + #0.002; + reg_ = {1{$random}}; + end +// synthesis translate_on +`endif + + assign io_out = reg_; + assign T1 = myNewReset ? 1'h0 : io_in; + + always @(posedge myClock) begin + if(myNewReset) begin + reg_ <= 1'h0; + end else begin + reg_ <= io_in; + end + end +endmodule + diff --git a/src/test/resources/NameSuite_BindFifthComp_1.v b/src/test/resources/NameSuite_BindFifthComp_1.v index fdc571dc..62eeffe3 100644 --- a/src/test/resources/NameSuite_BindFifthComp_1.v +++ b/src/test/resources/NameSuite_BindFifthComp_1.v @@ -45,15 +45,15 @@ module NameSuite_Block_2(input clk, assign T1 = T7 ? tag_ram_1 : 32'h0; assign T2 = T3 ? io_in_resp_bits_ppn : tag_ram_1; assign T3 = io_in_resp_valid & T4; - assign T4 = T5[1'h1:1'h1]; + assign T4 = T5[1]; assign T5 = 1'h1 << T6; assign T6 = 1'h0; - assign T7 = tag_ram_0[1'h1:1'h1]; + assign T7 = tag_ram_0[1]; assign T8 = T9 ? io_in_resp_bits_ppn : tag_ram_0; assign T9 = io_in_resp_valid & T10; - assign T10 = T5[1'h0:1'h0]; + assign T10 = T5[0]; assign T11 = T12 ? tag_ram_0 : 32'h0; - assign T12 = tag_ram_0[1'h0:1'h0]; + assign T12 = tag_ram_0[0]; always @(posedge clk) begin if(T3) begin diff --git a/src/test/resources/NameSuite_DebugComp_1.cpp b/src/test/resources/NameSuite_DebugComp_1.cpp index 548504fc..7bf35d26 100644 --- a/src/test/resources/NameSuite_DebugComp_1.cpp +++ b/src/test/resources/NameSuite_DebugComp_1.cpp @@ -3,35 +3,21 @@ void NameSuite_DebugComp_1_t::init ( val_t rand_init ) { this->__srand(rand_init); NameSuite_DebugComp_1_dpath__wb_reg_ll_wb.randomize(&__rand_seed); + clk.len = 1; + clk.cnt = 0; + clk.values[0] = 0; } int NameSuite_DebugComp_1_t::clock ( dat_t<1> reset ) { uint32_t min = ((uint32_t)1<<31)-1; - if (clk_cnt < min) min = clk_cnt; - clk_cnt-=min; - if (clk_cnt == 0) clock_hi( reset ); - if (clk_cnt == 0) clock_lo( reset ); - if (clk_cnt == 0) clk_cnt = clk; + if (clk.cnt < min) min = clk.cnt; + clk.cnt-=min; + if (clk.cnt == 0) clock_lo( reset ); + if (!reset.to_bool()) print( std::cerr ); + mod_t::dump( reset ); + if (clk.cnt == 0) clock_hi( reset ); + if (clk.cnt == 0) clk.cnt = clk.len; return min; } -mod_t* NameSuite_DebugComp_1_t::clone() { - mod_t* cloned = new NameSuite_DebugComp_1_t(*this); - return cloned; -} -bool NameSuite_DebugComp_1_t::set_circuit_from ( mod_t* src ) { - NameSuite_DebugComp_1_t* mod_typed = dynamic_cast(src); - assert(mod_typed); - NameSuite_DebugComp_1__io_ctrl_wb_wen = mod_typed->NameSuite_DebugComp_1__io_ctrl_wb_wen; - NameSuite_DebugComp_1_dpath__io_ctrl_wb_wen = mod_typed->NameSuite_DebugComp_1_dpath__io_ctrl_wb_wen; - NameSuite_DebugComp_1_dpath__wb_wen = mod_typed->NameSuite_DebugComp_1_dpath__wb_wen; - NameSuite_DebugComp_1_dpath__reset = mod_typed->NameSuite_DebugComp_1_dpath__reset; - T0 = mod_typed->T0; - NameSuite_DebugComp_1_dpath__wb_reg_ll_wb = mod_typed->NameSuite_DebugComp_1_dpath__wb_reg_ll_wb; - NameSuite_DebugComp_1_dpath__io_ctrl_out = mod_typed->NameSuite_DebugComp_1_dpath__io_ctrl_out; - NameSuite_DebugComp_1__io_ctrl_out = mod_typed->NameSuite_DebugComp_1__io_ctrl_out; - clk = mod_typed->clk; - clk_cnt = mod_typed->clk_cnt; - return true; -} void NameSuite_DebugComp_1_t::print ( FILE* f ) { } void NameSuite_DebugComp_1_t::print ( std::ostream& s ) { @@ -39,102 +25,107 @@ void NameSuite_DebugComp_1_t::print ( std::ostream& s ) { void NameSuite_DebugComp_1_t::dump_init ( FILE* f ) { fputs("$timescale 1ps $end\n", f); fputs("$scope module NameSuite_DebugComp_1 $end\n", f); - fputs("$var wire 1 \x21 io_ctrl_wb_wen $end\n", f); - fputs("$var wire 1 \x26 io_ctrl_out $end\n", f); + fputs("$var wire 1 \x21 clk $end\n", f); + fputs("$var wire 1 \x22 reset $end\n", f); + fputs("$var wire 1 \x23 io_ctrl_wb_wen $end\n", f); + fputs("$var wire 1 \x28 io_ctrl_out $end\n", f); fputs("$scope module dpath $end\n", f); - fputs("$var wire 1 \x22 io_ctrl_wb_wen $end\n", f); - fputs("$var wire 1 \x23 reset $end\n", f); - fputs("$var wire 1 \x24 wb_reg_ll_wb $end\n", f); - fputs("$var wire 1 \x25 io_ctrl_out $end\n", f); + fputs("$var wire 1 \x24 io_ctrl_wb_wen $end\n", f); + fputs("$var wire 1 \x25 reset $end\n", f); + fputs("$var wire 1 \x26 wb_reg_ll_wb $end\n", f); + fputs("$var wire 1 \x27 io_ctrl_out $end\n", f); fputs("$upscope $end\n", f); fputs("$upscope $end\n", f); fputs("$enddefinitions $end\n", f); fputs("$dumpvars\n", f); fputs("$end\n", f); fputs("#0\n", f); - dat_dump<1>(f, NameSuite_DebugComp_1__io_ctrl_wb_wen, 0x21); + if (clk.cnt == 0) { + clk.values[0] = 1; + dat_dump<1>(f, clk, 0x21); + } + dat_t<1> reset = LIT<1>(1); + dat_dump<1>(f, reset, 0x22); + dat_dump<1>(f, NameSuite_DebugComp_1__io_ctrl_wb_wen, 0x23); NameSuite_DebugComp_1__io_ctrl_wb_wen__prev = NameSuite_DebugComp_1__io_ctrl_wb_wen; - dat_dump<1>(f, NameSuite_DebugComp_1_dpath__io_ctrl_wb_wen, 0x22); + dat_dump<1>(f, NameSuite_DebugComp_1_dpath__io_ctrl_wb_wen, 0x24); NameSuite_DebugComp_1_dpath__io_ctrl_wb_wen__prev = NameSuite_DebugComp_1_dpath__io_ctrl_wb_wen; - dat_dump<1>(f, NameSuite_DebugComp_1_dpath__reset, 0x23); + dat_dump<1>(f, NameSuite_DebugComp_1_dpath__reset, 0x25); NameSuite_DebugComp_1_dpath__reset__prev = NameSuite_DebugComp_1_dpath__reset; - dat_dump<1>(f, NameSuite_DebugComp_1_dpath__wb_reg_ll_wb, 0x24); + dat_dump<1>(f, NameSuite_DebugComp_1_dpath__wb_reg_ll_wb, 0x26); NameSuite_DebugComp_1_dpath__wb_reg_ll_wb__prev = NameSuite_DebugComp_1_dpath__wb_reg_ll_wb; - dat_dump<1>(f, NameSuite_DebugComp_1_dpath__io_ctrl_out, 0x25); + dat_dump<1>(f, NameSuite_DebugComp_1_dpath__io_ctrl_out, 0x27); NameSuite_DebugComp_1_dpath__io_ctrl_out__prev = NameSuite_DebugComp_1_dpath__io_ctrl_out; - dat_dump<1>(f, NameSuite_DebugComp_1__io_ctrl_out, 0x26); + dat_dump<1>(f, NameSuite_DebugComp_1__io_ctrl_out, 0x28); NameSuite_DebugComp_1__io_ctrl_out__prev = NameSuite_DebugComp_1__io_ctrl_out; + fputs("#1\n", f); + if (clk.cnt == 0) { + clk.values[0] = 0; + dat_dump<1>(f, clk, 0x21); + } } -void NameSuite_DebugComp_1_t::dump ( FILE* f, int t ) { - if (t == 0) return dump_init(f); - fprintf(f, "#%d\n", t); - if (NameSuite_DebugComp_1__io_ctrl_wb_wen != NameSuite_DebugComp_1__io_ctrl_wb_wen__prev) - goto L0; -K0: - if (NameSuite_DebugComp_1_dpath__io_ctrl_wb_wen != NameSuite_DebugComp_1_dpath__io_ctrl_wb_wen__prev) - goto L1; -K1: - if (NameSuite_DebugComp_1_dpath__reset != NameSuite_DebugComp_1_dpath__reset__prev) - goto L2; -K2: - if (NameSuite_DebugComp_1_dpath__wb_reg_ll_wb != NameSuite_DebugComp_1_dpath__wb_reg_ll_wb__prev) - goto L3; -K3: - if (NameSuite_DebugComp_1_dpath__io_ctrl_out != NameSuite_DebugComp_1_dpath__io_ctrl_out__prev) - goto L4; -K4: - if (NameSuite_DebugComp_1__io_ctrl_out != NameSuite_DebugComp_1__io_ctrl_out__prev) - goto L5; -K5: - return; +void NameSuite_DebugComp_1_t::dump ( FILE* f, val_t t, dat_t<1> reset ) { + if (t == 0L) return dump_init(f); + fprintf(f, "#%lu\n", t << 1); + if (clk.cnt == 0) goto L0; +K0: if (reset != reset__prev) goto L1; +K1: if (NameSuite_DebugComp_1__io_ctrl_wb_wen != NameSuite_DebugComp_1__io_ctrl_wb_wen__prev) goto L2; +K2: if (NameSuite_DebugComp_1_dpath__io_ctrl_wb_wen != NameSuite_DebugComp_1_dpath__io_ctrl_wb_wen__prev) goto L3; +K3: if (NameSuite_DebugComp_1_dpath__reset != NameSuite_DebugComp_1_dpath__reset__prev) goto L4; +K4: if (NameSuite_DebugComp_1_dpath__wb_reg_ll_wb != NameSuite_DebugComp_1_dpath__wb_reg_ll_wb__prev) goto L5; +K5: if (NameSuite_DebugComp_1_dpath__io_ctrl_out != NameSuite_DebugComp_1_dpath__io_ctrl_out__prev) goto L6; +K6: if (NameSuite_DebugComp_1__io_ctrl_out != NameSuite_DebugComp_1__io_ctrl_out__prev) goto L7; +K7: fprintf(f, "#%lu\n", (t << 1) + 1); + if (clk.cnt == 0) goto Z0; +C0: return; L0: - NameSuite_DebugComp_1__io_ctrl_wb_wen__prev = NameSuite_DebugComp_1__io_ctrl_wb_wen; - dat_dump<1>(f, NameSuite_DebugComp_1__io_ctrl_wb_wen, 0x21); + clk.values[0] = 1; + dat_dump<1>(f, clk, 0x21); goto K0; L1: - NameSuite_DebugComp_1_dpath__io_ctrl_wb_wen__prev = NameSuite_DebugComp_1_dpath__io_ctrl_wb_wen; - dat_dump<1>(f, NameSuite_DebugComp_1_dpath__io_ctrl_wb_wen, 0x22); + reset__prev = reset; + dat_dump<1>(f, reset, 0x22); goto K1; L2: - NameSuite_DebugComp_1_dpath__reset__prev = NameSuite_DebugComp_1_dpath__reset; - dat_dump<1>(f, NameSuite_DebugComp_1_dpath__reset, 0x23); + NameSuite_DebugComp_1__io_ctrl_wb_wen__prev = NameSuite_DebugComp_1__io_ctrl_wb_wen; + dat_dump<1>(f, NameSuite_DebugComp_1__io_ctrl_wb_wen, 0x23); goto K2; L3: - NameSuite_DebugComp_1_dpath__wb_reg_ll_wb__prev = NameSuite_DebugComp_1_dpath__wb_reg_ll_wb; - dat_dump<1>(f, NameSuite_DebugComp_1_dpath__wb_reg_ll_wb, 0x24); + NameSuite_DebugComp_1_dpath__io_ctrl_wb_wen__prev = NameSuite_DebugComp_1_dpath__io_ctrl_wb_wen; + dat_dump<1>(f, NameSuite_DebugComp_1_dpath__io_ctrl_wb_wen, 0x24); goto K3; L4: - NameSuite_DebugComp_1_dpath__io_ctrl_out__prev = NameSuite_DebugComp_1_dpath__io_ctrl_out; - dat_dump<1>(f, NameSuite_DebugComp_1_dpath__io_ctrl_out, 0x25); + NameSuite_DebugComp_1_dpath__reset__prev = NameSuite_DebugComp_1_dpath__reset; + dat_dump<1>(f, NameSuite_DebugComp_1_dpath__reset, 0x25); goto K4; L5: - NameSuite_DebugComp_1__io_ctrl_out__prev = NameSuite_DebugComp_1__io_ctrl_out; - dat_dump<1>(f, NameSuite_DebugComp_1__io_ctrl_out, 0x26); + NameSuite_DebugComp_1_dpath__wb_reg_ll_wb__prev = NameSuite_DebugComp_1_dpath__wb_reg_ll_wb; + dat_dump<1>(f, NameSuite_DebugComp_1_dpath__wb_reg_ll_wb, 0x26); goto K5; +L6: + NameSuite_DebugComp_1_dpath__io_ctrl_out__prev = NameSuite_DebugComp_1_dpath__io_ctrl_out; + dat_dump<1>(f, NameSuite_DebugComp_1_dpath__io_ctrl_out, 0x27); + goto K6; +L7: + NameSuite_DebugComp_1__io_ctrl_out__prev = NameSuite_DebugComp_1__io_ctrl_out; + dat_dump<1>(f, NameSuite_DebugComp_1__io_ctrl_out, 0x28); + goto K7; +Z0: + clk.values[0] = 0; + dat_dump<1>(f, clk, 0x21); + goto C0; } -void NameSuite_DebugComp_1_t::clock_lo ( dat_t<1> reset ) { +void NameSuite_DebugComp_1_t::clock_lo ( dat_t<1> reset, bool assert_fire ) { { NameSuite_DebugComp_1_dpath__io_ctrl_wb_wen.values[0] = NameSuite_DebugComp_1__io_ctrl_wb_wen.values[0];} { NameSuite_DebugComp_1_dpath__wb_wen.values[0] = NameSuite_DebugComp_1_dpath__io_ctrl_wb_wen.values[0] | NameSuite_DebugComp_1_dpath__wb_reg_ll_wb.values[0];} - val_t T1; - { T1 = TERNARY_1(NameSuite_DebugComp_1_dpath__wb_wen.values[0], NameSuite_DebugComp_1_dpath__io_ctrl_wb_wen.values[0], NameSuite_DebugComp_1_dpath__wb_reg_ll_wb.values[0]);} + val_t T0; + { T0 = TERNARY_1(NameSuite_DebugComp_1_dpath__wb_wen.values[0], NameSuite_DebugComp_1_dpath__io_ctrl_wb_wen.values[0], NameSuite_DebugComp_1_dpath__wb_reg_ll_wb.values[0]);} { NameSuite_DebugComp_1_dpath__reset.values[0] = reset.values[0];} - { T0.values[0] = TERNARY(NameSuite_DebugComp_1_dpath__reset.values[0], 0x0L, T1);} + { T1.values[0] = TERNARY(NameSuite_DebugComp_1_dpath__reset.values[0], 0x0L, T0);} { NameSuite_DebugComp_1_dpath__io_ctrl_out.values[0] = NameSuite_DebugComp_1_dpath__wb_reg_ll_wb.values[0];} { NameSuite_DebugComp_1__io_ctrl_out.values[0] = NameSuite_DebugComp_1_dpath__io_ctrl_out.values[0];} } void NameSuite_DebugComp_1_t::clock_hi ( dat_t<1> reset ) { - dat_t<1> NameSuite_DebugComp_1_dpath__wb_reg_ll_wb__shadow = T0; - NameSuite_DebugComp_1_dpath__wb_reg_ll_wb = T0; -} -void NameSuite_DebugComp_1_api_t::init_mapping_table ( ) { - dat_table.clear(); - mem_table.clear(); - NameSuite_DebugComp_1_t* mod_typed = dynamic_cast(module); - assert(mod_typed); - dat_table["NameSuite_DebugComp_1.io_ctrl_wb_wen"] = new dat_api<1>(&mod_typed->NameSuite_DebugComp_1__io_ctrl_wb_wen, "NameSuite_DebugComp_1.io_ctrl_wb_wen", ""); - dat_table["NameSuite_DebugComp_1.dpath.io_ctrl_wb_wen"] = new dat_api<1>(&mod_typed->NameSuite_DebugComp_1_dpath__io_ctrl_wb_wen, "NameSuite_DebugComp_1.dpath.io_ctrl_wb_wen", ""); - dat_table["NameSuite_DebugComp_1.dpath.wb_wen"] = new dat_api<1>(&mod_typed->NameSuite_DebugComp_1_dpath__wb_wen, "NameSuite_DebugComp_1.dpath.wb_wen", ""); - dat_table["NameSuite_DebugComp_1.dpath.wb_reg_ll_wb"] = new dat_api<1>(&mod_typed->NameSuite_DebugComp_1_dpath__wb_reg_ll_wb, "NameSuite_DebugComp_1.dpath.wb_reg_ll_wb", ""); - dat_table["NameSuite_DebugComp_1.dpath.io_ctrl_out"] = new dat_api<1>(&mod_typed->NameSuite_DebugComp_1_dpath__io_ctrl_out, "NameSuite_DebugComp_1.dpath.io_ctrl_out", ""); - dat_table["NameSuite_DebugComp_1.io_ctrl_out"] = new dat_api<1>(&mod_typed->NameSuite_DebugComp_1__io_ctrl_out, "NameSuite_DebugComp_1.io_ctrl_out", ""); + dat_t<1> NameSuite_DebugComp_1_dpath__wb_reg_ll_wb__shadow = T1; + NameSuite_DebugComp_1_dpath__wb_reg_ll_wb = T1; } diff --git a/src/test/resources/NameSuite_DebugComp_1.h b/src/test/resources/NameSuite_DebugComp_1.h index c32509e7..e750454f 100644 --- a/src/test/resources/NameSuite_DebugComp_1.h +++ b/src/test/resources/NameSuite_DebugComp_1.h @@ -14,7 +14,7 @@ class NameSuite_DebugComp_1_t : public mod_t { dat_t<1> NameSuite_DebugComp_1_dpath__wb_wen; dat_t<1> reset; dat_t<1> NameSuite_DebugComp_1_dpath__reset; - dat_t<1> T0; + dat_t<1> T1; dat_t<1> NameSuite_DebugComp_1_dpath__wb_reg_ll_wb; dat_t<1> NameSuite_DebugComp_1_dpath__io_ctrl_out; dat_t<1> NameSuite_DebugComp_1__io_ctrl_out; @@ -24,26 +24,20 @@ class NameSuite_DebugComp_1_t : public mod_t { dat_t<1> NameSuite_DebugComp_1_dpath__wb_reg_ll_wb__prev; dat_t<1> NameSuite_DebugComp_1_dpath__io_ctrl_out__prev; dat_t<1> NameSuite_DebugComp_1__io_ctrl_out__prev; - int clk; - int clk_cnt; + clk_t clk; + dat_t<1> reset__prev; void init ( val_t rand_init = 0 ); - void clock_lo ( dat_t<1> reset ); + void clock_lo ( dat_t<1> reset, bool assert_fire=true ); void clock_hi ( dat_t<1> reset ); int clock ( dat_t<1> reset ); - mod_t* clone(); - bool set_circuit_from(mod_t* src); void print ( FILE* f ); void print ( std::ostream& s ); - void dump ( FILE* f, int t ); + void dump ( FILE* f, val_t t, dat_t<1> reset=LIT<1>(0) ); void dump_init ( FILE* f ); }; -class NameSuite_DebugComp_1_api_t : public mod_api_t { - void init_mapping_table(); -}; - #endif diff --git a/src/test/resources/NameSuite_ListLookupsComp_1.v b/src/test/resources/NameSuite_ListLookupsComp_1.v index d65a6905..4a6fc6e1 100644 --- a/src/test/resources/NameSuite_ListLookupsComp_1.v +++ b/src/test/resources/NameSuite_ListLookupsComp_1.v @@ -17,7 +17,7 @@ module NameSuite_ListLookupsComp_1( assign io_sigs_valid = T0; assign T0 = T1; assign T1 = T7 ^ T2; - assign T2 = T3[2'h2:2'h2]; + assign T2 = T3[2]; assign T3 = T6 ? 3'h4 : T4; assign T4 = T5 ? 3'h1 : 3'h0; assign T5 = io_inst == 32'h257b; diff --git a/src/test/resources/NameSuite_VecComp_1.v b/src/test/resources/NameSuite_VecComp_1.v index 14e56191..6235838f 100644 --- a/src/test/resources/NameSuite_VecComp_1.v +++ b/src/test/resources/NameSuite_VecComp_1.v @@ -27,7 +27,7 @@ module NameSuite_VecComp_1(input clk, `endif assign io_status_im = reg_status_im; - assign T0 = wdata[3'h7:1'h0]; + assign T0 = wdata[7:0]; assign wdata = io_r_en ? io_w_data : host_pcr_bits_data; assign T1 = io_r_en ? T2 : host_pcr_bits_data; assign T2 = {56'h0, rdata}; diff --git a/src/test/resources/RegVcdSuite_RegVcdTest_1.vcd b/src/test/resources/RegVcdSuite_RegVcdTest_1.vcd new file mode 100644 index 00000000..73a5fbc0 --- /dev/null +++ b/src/test/resources/RegVcdSuite_RegVcdTest_1.vcd @@ -0,0 +1,102 @@ +$timescale 1ps $end +$scope module RegVcdSuite_RegVcdTest_1 $end +$var wire 1 ! clk $end +$var wire 1 " reset $end +$var wire 1 # io_ready $end +$var wire 1 $ io_full $end +$var wire 1 % io_write $end +$var wire 1 & io_read $end +$var wire 1 ' stateReg $end +$var wire 1 ( io_stateReg $end +$var wire 8 ) io_din $end +$var wire 8 * dataReg $end +$var wire 8 + io_dout $end +$upscope $end +$enddefinitions $end +$dumpvars +$end +#0 +b1 ! +b1 " +b1 # +b0 $ +b0 % +b0 & +b0 ' +b0 ( +b00000001 ) +b00000000 * +b00000000 + +#1 +b0 ! +#2 +b1 ! +b1 " +#3 +b0 ! +#4 +b1 ! +#5 +b0 ! +#6 +b1 ! +#7 +b0 ! +#8 +b1 ! +#9 +b0 ! +#10 +b1 ! +b0 " +b10101011 ) +#11 +b0 ! +#12 +b1 ! +b1 % +b00010010 ) +#13 +b0 ! +#14 +b1 ! +b0 # +b1 $ +b0 % +b1 ' +b1 ( +b00110100 ) +b00010010 * +b00010010 + +#15 +b0 ! +#16 +b1 ! +b1 & +#17 +b0 ! +#18 +b1 ! +b1 # +b0 $ +b0 & +b0 ' +b0 ( +#19 +b0 ! +#20 +b1 ! +b1 % +b01010110 ) +#21 +b0 ! +#22 +b1 ! +b0 # +b1 $ +b1 ' +b1 ( +b01010110 * +b01010110 + +#23 +b0 ! diff --git a/src/test/resources/StdlibSuite_ArbiterTest_1.v b/src/test/resources/StdlibSuite_ArbiterTest_1.v index 068c2a77..2b3391bf 100644 --- a/src/test/resources/StdlibSuite_ArbiterTest_1.v +++ b/src/test/resources/StdlibSuite_ArbiterTest_1.v @@ -53,18 +53,18 @@ module Arbiter( assign io_out_bits = T2; assign T2 = T8 ? T6 : T3; assign T3 = T4 ? io_in_1_bits : io_in_0_bits; - assign T4 = T5[1'h0:1'h0]; + assign T4 = T5[0]; assign T5 = chosen; assign T6 = T7 ? io_in_3_bits : io_in_2_bits; - assign T7 = T5[1'h0:1'h0]; - assign T8 = T5[1'h1:1'h1]; + assign T7 = T5[0]; + assign T8 = T5[1]; assign io_out_valid = T9; assign T9 = T14 ? T12 : T10; assign T10 = T11 ? io_in_1_valid : io_in_0_valid; - assign T11 = T5[1'h0:1'h0]; + assign T11 = T5[0]; assign T12 = T13 ? io_in_3_valid : io_in_2_valid; - assign T13 = T5[1'h0:1'h0]; - assign T14 = T5[1'h1:1'h1]; + assign T13 = T5[0]; + assign T14 = T5[1]; assign io_in_0_ready = io_out_ready; assign io_in_1_ready = T15; assign T15 = T16 & io_out_ready; diff --git a/src/test/resources/StdlibSuite_OHToUIntComp_1.v b/src/test/resources/StdlibSuite_OHToUIntComp_1.v index 43c98579..567cf182 100644 --- a/src/test/resources/StdlibSuite_OHToUIntComp_1.v +++ b/src/test/resources/StdlibSuite_OHToUIntComp_1.v @@ -17,14 +17,14 @@ module StdlibSuite_OHToUIntComp_1( assign io_out = T5; assign T5 = {T10, T6}; - assign T6 = T7[1'h1:1'h1]; + assign T6 = T7[1]; assign T7 = T9 | T8; - assign T8 = T1[1'h1:1'h0]; + assign T8 = T1[1:0]; assign T1 = T2; assign T2 = {T4, T3}; assign T3 = {io_in, 1'h1}; assign T4 = {io_in, 1'h0}; - assign T9 = T1[2'h3:2'h2]; + assign T9 = T1[3:2]; assign T10 = T9 != 2'h0; endmodule diff --git a/src/test/resources/StdlibSuite_RRArbiterTest_1.v b/src/test/resources/StdlibSuite_RRArbiterTest_1.v index f3718629..330606fc 100644 --- a/src/test/resources/StdlibSuite_RRArbiterTest_1.v +++ b/src/test/resources/StdlibSuite_RRArbiterTest_1.v @@ -129,18 +129,18 @@ module StdlibSuite_RRArbiterTest_1(input clk, input reset, assign io_out_bits = T13; assign T13 = T19 ? T17 : T14; assign T14 = T15 ? io_in_1_bits : io_in_0_bits; - assign T15 = T16[1'h0:1'h0]; + assign T15 = T16[0]; assign T16 = chosen; assign T17 = T18 ? io_in_3_bits : io_in_2_bits; - assign T18 = T16[1'h0:1'h0]; - assign T19 = T16[1'h1:1'h1]; + assign T18 = T16[0]; + assign T19 = T16[1]; assign io_out_valid = T20; assign T20 = T25 ? T23 : T21; assign T21 = T22 ? io_in_1_valid : io_in_0_valid; - assign T22 = T16[1'h0:1'h0]; + assign T22 = T16[0]; assign T23 = T24 ? io_in_3_valid : io_in_2_valid; - assign T24 = T16[1'h0:1'h0]; - assign T25 = T16[1'h1:1'h1]; + assign T24 = T16[0]; + assign T25 = T16[1]; assign io_in_0_ready = T26; assign T26 = T27 & io_out_ready; assign T27 = T40 | T28; diff --git a/src/test/resources/VCDVerifySuite_Top_1.vcd b/src/test/resources/VCDVerifySuite_Top_1.vcd new file mode 100644 index 00000000..7681fb02 --- /dev/null +++ b/src/test/resources/VCDVerifySuite_Top_1.vcd @@ -0,0 +1,81 @@ +$timescale 1ps $end +$scope module VCDVerifySuite_Top_1 $end +$var wire 1 ! clk $end +$var wire 1 " reset $end +$var wire 1 # io_input $end +$var wire 1 ( io_output $end +$scope module hz $end +$var wire 1 $ io_input $end +$var wire 1 % reset $end +$var wire 1 & reg_ $end +$var wire 1 ' io_output $end +$upscope $end +$upscope $end +$enddefinitions $end +$dumpvars +$end +#0 +b1 ! +b1 " +b0 # +b0 $ +b1 % +b0 & +b0 ' +b0 ( +#1 +b0 ! +#2 +b1 ! +b1 " +#3 +b0 ! +#4 +b1 ! +#5 +b0 ! +#6 +b1 ! +#7 +b0 ! +#8 +b1 ! +#9 +b0 ! +#10 +b1 ! +b0 " +b0 # +b0 $ +b0 % +#11 +b0 ! +#12 +b1 ! +b1 # +b1 $ +#13 +b0 ! +#14 +b1 ! +b1 & +b1 ' +b1 ( +#15 +b0 ! +#16 +b1 ! +#17 +b0 ! +#18 +b1 ! +#19 +b0 ! +#20 +b1 ! +#21 +b0 ! +#22 +b1 ! +#23 +b0 ! diff --git a/src/test/resources/VerifSuite_CppAssertComp_1.cpp b/src/test/resources/VerifSuite_CppAssertComp_1.cpp index 18c11cd4..e53026ef 100644 --- a/src/test/resources/VerifSuite_CppAssertComp_1.cpp +++ b/src/test/resources/VerifSuite_CppAssertComp_1.cpp @@ -2,53 +2,33 @@ void VerifSuite_CppAssertComp_1_t::init ( val_t rand_init ) { this->__srand(rand_init); + clk.len = 1; + clk.cnt = 0; + clk.values[0] = 0; } int VerifSuite_CppAssertComp_1_t::clock ( dat_t<1> reset ) { uint32_t min = ((uint32_t)1<<31)-1; - if (clk_cnt < min) min = clk_cnt; - clk_cnt-=min; - if (clk_cnt == 0) clock_hi( reset ); - if (clk_cnt == 0) clock_lo( reset ); - if (clk_cnt == 0) clk_cnt = clk; + if (clk.cnt < min) min = clk.cnt; + clk.cnt-=min; + if (clk.cnt == 0) clock_lo( reset ); + if (!reset.to_bool()) print( std::cerr ); + if (clk.cnt == 0) clock_hi( reset ); + if (clk.cnt == 0) clk.cnt = clk.len; return min; } -mod_t* VerifSuite_CppAssertComp_1_t::clone() { - mod_t* cloned = new VerifSuite_CppAssertComp_1_t(*this); - return cloned; -} -bool VerifSuite_CppAssertComp_1_t::set_circuit_from ( mod_t* src ) { - VerifSuite_CppAssertComp_1_t* mod_typed = dynamic_cast(src); - assert(mod_typed); - VerifSuite_CppAssertComp_1__io_y = mod_typed->VerifSuite_CppAssertComp_1__io_y; - VerifSuite_CppAssertComp_1__io_x = mod_typed->VerifSuite_CppAssertComp_1__io_x; - VerifSuite_CppAssertComp_1__io_z = mod_typed->VerifSuite_CppAssertComp_1__io_z; - T0 = mod_typed->T0; - clk = mod_typed->clk; - clk_cnt = mod_typed->clk_cnt; - return true; -} void VerifSuite_CppAssertComp_1_t::print ( FILE* f ) { } void VerifSuite_CppAssertComp_1_t::print ( std::ostream& s ) { } void VerifSuite_CppAssertComp_1_t::dump_init ( FILE* f ) { } -void VerifSuite_CppAssertComp_1_t::dump ( FILE* f, int t ) { +void VerifSuite_CppAssertComp_1_t::dump ( FILE* f, val_t t, dat_t<1> reset ) { } -void VerifSuite_CppAssertComp_1_t::clock_lo ( dat_t<1> reset ) { - val_t T1; - { T1 = VerifSuite_CppAssertComp_1__io_y.values[0] | VerifSuite_CppAssertComp_1__io_x.values[0] << 8;} - { VerifSuite_CppAssertComp_1__io_z.values[0] = T1;} +void VerifSuite_CppAssertComp_1_t::clock_lo ( dat_t<1> reset, bool assert_fire ) { + val_t T0; + { T0 = VerifSuite_CppAssertComp_1__io_y.values[0] | VerifSuite_CppAssertComp_1__io_x.values[0] << 8;} + { VerifSuite_CppAssertComp_1__io_z.values[0] = T0;} ASSERT(reset.values[0], "failure"); } void VerifSuite_CppAssertComp_1_t::clock_hi ( dat_t<1> reset ) { } -void VerifSuite_CppAssertComp_1_api_t::init_mapping_table ( ) { - dat_table.clear(); - mem_table.clear(); - VerifSuite_CppAssertComp_1_t* mod_typed = dynamic_cast(module); - assert(mod_typed); - dat_table["VerifSuite_CppAssertComp_1.io_y"] = new dat_api<8>(&mod_typed->VerifSuite_CppAssertComp_1__io_y, "VerifSuite_CppAssertComp_1.io_y", ""); - dat_table["VerifSuite_CppAssertComp_1.io_x"] = new dat_api<8>(&mod_typed->VerifSuite_CppAssertComp_1__io_x, "VerifSuite_CppAssertComp_1.io_x", ""); - dat_table["VerifSuite_CppAssertComp_1.io_z"] = new dat_api<16>(&mod_typed->VerifSuite_CppAssertComp_1__io_z, "VerifSuite_CppAssertComp_1.io_z", ""); -} diff --git a/src/test/resources/VerifSuite_CppPrintfComp_1.cpp b/src/test/resources/VerifSuite_CppPrintfComp_1.cpp index 366b4cca..2703daf0 100644 --- a/src/test/resources/VerifSuite_CppPrintfComp_1.cpp +++ b/src/test/resources/VerifSuite_CppPrintfComp_1.cpp @@ -2,34 +2,20 @@ void VerifSuite_CppPrintfComp_1_t::init ( val_t rand_init ) { this->__srand(rand_init); + clk.len = 1; + clk.cnt = 0; + clk.values[0] = 0; } int VerifSuite_CppPrintfComp_1_t::clock ( dat_t<1> reset ) { uint32_t min = ((uint32_t)1<<31)-1; - if (clk_cnt < min) min = clk_cnt; - clk_cnt-=min; - if (clk_cnt == 0) clock_hi( reset ); - if (clk_cnt == 0) clock_lo( reset ); - if (clk_cnt == 0) clk_cnt = clk; + if (clk.cnt < min) min = clk.cnt; + clk.cnt-=min; + if (clk.cnt == 0) clock_lo( reset ); + if (!reset.to_bool()) print( std::cerr ); + if (clk.cnt == 0) clock_hi( reset ); + if (clk.cnt == 0) clk.cnt = clk.len; return min; } -mod_t* VerifSuite_CppPrintfComp_1_t::clone() { - mod_t* cloned = new VerifSuite_CppPrintfComp_1_t(*this); - return cloned; -} -bool VerifSuite_CppPrintfComp_1_t::set_circuit_from ( mod_t* src ) { - VerifSuite_CppPrintfComp_1_t* mod_typed = dynamic_cast(src); - assert(mod_typed); - VerifSuite_CppPrintfComp_1__io_y = mod_typed->VerifSuite_CppPrintfComp_1__io_y; - VerifSuite_CppPrintfComp_1__io_x = mod_typed->VerifSuite_CppPrintfComp_1__io_x; - VerifSuite_CppPrintfComp_1__io_z = mod_typed->VerifSuite_CppPrintfComp_1__io_z; - T1 = mod_typed->T1; - T2 = mod_typed->T2; - T3 = mod_typed->T3; - T4 = mod_typed->T4; - clk = mod_typed->clk; - clk_cnt = mod_typed->clk_cnt; - return true; -} void VerifSuite_CppPrintfComp_1_t::print ( FILE* f ) { #if __cplusplus >= 201103L if (T1.values[0]) dat_fprintf<104>(f, "display %h %h", T3, T2); @@ -44,9 +30,9 @@ s.flush(); } void VerifSuite_CppPrintfComp_1_t::dump_init ( FILE* f ) { } -void VerifSuite_CppPrintfComp_1_t::dump ( FILE* f, int t ) { +void VerifSuite_CppPrintfComp_1_t::dump ( FILE* f, val_t t, dat_t<1> reset ) { } -void VerifSuite_CppPrintfComp_1_t::clock_lo ( dat_t<1> reset ) { +void VerifSuite_CppPrintfComp_1_t::clock_lo ( dat_t<1> reset, bool assert_fire ) { val_t T0; { T0 = VerifSuite_CppPrintfComp_1__io_y.values[0] | VerifSuite_CppPrintfComp_1__io_x.values[0] << 8;} { VerifSuite_CppPrintfComp_1__io_z.values[0] = T0;} @@ -56,12 +42,3 @@ void VerifSuite_CppPrintfComp_1_t::clock_lo ( dat_t<1> reset ) { } void VerifSuite_CppPrintfComp_1_t::clock_hi ( dat_t<1> reset ) { } -void VerifSuite_CppPrintfComp_1_api_t::init_mapping_table ( ) { - dat_table.clear(); - mem_table.clear(); - VerifSuite_CppPrintfComp_1_t* mod_typed = dynamic_cast(module); - assert(mod_typed); - dat_table["VerifSuite_CppPrintfComp_1.io_y"] = new dat_api<8>(&mod_typed->VerifSuite_CppPrintfComp_1__io_y, "VerifSuite_CppPrintfComp_1.io_y", ""); - dat_table["VerifSuite_CppPrintfComp_1.io_x"] = new dat_api<8>(&mod_typed->VerifSuite_CppPrintfComp_1__io_x, "VerifSuite_CppPrintfComp_1.io_x", ""); - dat_table["VerifSuite_CppPrintfComp_1.io_z"] = new dat_api<16>(&mod_typed->VerifSuite_CppPrintfComp_1__io_z, "VerifSuite_CppPrintfComp_1.io_z", ""); -} diff --git a/src/test/resources/VerifSuite_CppPrintfComp_1.h b/src/test/resources/VerifSuite_CppPrintfComp_1.h index dc4bf8f4..1387c053 100644 --- a/src/test/resources/VerifSuite_CppPrintfComp_1.h +++ b/src/test/resources/VerifSuite_CppPrintfComp_1.h @@ -17,26 +17,19 @@ class VerifSuite_CppPrintfComp_1_t : public mod_t { dat_t<8> T3; dat_t<16> VerifSuite_CppPrintfComp_1__io_z; dat_t<104> T4; - int clk; - int clk_cnt; + clk_t clk; void init ( val_t rand_init = 0 ); - void clock_lo ( dat_t<1> reset ); + void clock_lo ( dat_t<1> reset, bool assert_fire=true ); void clock_hi ( dat_t<1> reset ); int clock ( dat_t<1> reset ); - mod_t* clone(); - bool set_circuit_from(mod_t* src); void print ( FILE* f ); void print ( std::ostream& s ); - void dump ( FILE* f, int t ); + void dump ( FILE* f, val_t t, dat_t<1> reset=LIT<1>(0) ); void dump_init ( FILE* f ); }; -class VerifSuite_CppPrintfComp_1_api_t : public mod_api_t { - void init_mapping_table(); -}; - #endif diff --git a/src/test/resources/VerifSuite_VerilogAssertComp_1.v b/src/test/resources/VerifSuite_VerilogAssertComp_1.v index 075979f1..9db8aa55 100644 --- a/src/test/resources/VerifSuite_VerilogAssertComp_1.v +++ b/src/test/resources/VerifSuite_VerilogAssertComp_1.v @@ -4,7 +4,7 @@ module VerifSuite_VerilogAssertComp_1(input clk, input reset, output[15:0] io_z ); - reg[0:0] T0; + reg T0; wire[15:0] T1; `ifndef SYNTHESIS diff --git a/src/test/resources/VerifSuite_VerilogPrintfComp_1.v b/src/test/resources/VerifSuite_VerilogPrintfComp_1.v index 1e44c7a1..e174be89 100644 --- a/src/test/resources/VerifSuite_VerilogPrintfComp_1.v +++ b/src/test/resources/VerifSuite_VerilogPrintfComp_1.v @@ -29,7 +29,7 @@ module VerifSuite_VerilogPrintfComp_1(input clk, input reset, assign T1 = io_y; assign T2 = io_x; assign T3 = T4; - assign T4 = tsc_reg[5'h1f:1'h0]; + assign T4 = tsc_reg; assign T8 = reset ? 32'h0 : T5; assign T5 = tsc_reg + 32'h1; assign io_z = T7; diff --git a/src/test/resources/ZeroWidthTest_MulZS_1.dot b/src/test/resources/ZeroWidthTest_MulZS_1.dot new file mode 100644 index 00000000..ebdd27a5 --- /dev/null +++ b/src/test/resources/ZeroWidthTest_MulZS_1.dot @@ -0,0 +1,7 @@ +digraph ZeroWidthTest_MulZS_1{ +rankdir = LR; + io_z[label="io_z:SInt"]; + io_y[label="io_y:SInt"]; + io_x[label="io_x:UInt"]; + io_y -> io_z[label="32"]; +} \ No newline at end of file diff --git a/src/test/resources/ZeroWidthTest_ZeroWidthForceMatching_1.v b/src/test/resources/ZeroWidthTest_ZeroWidthForceMatching_1.v new file mode 100644 index 00000000..79c95794 --- /dev/null +++ b/src/test/resources/ZeroWidthTest_ZeroWidthForceMatching_1.v @@ -0,0 +1,9 @@ +module ZeroWidthTest_ZeroWidthForceMatching_1( + output io +); + + + + assign io = 1'h0; +endmodule + diff --git a/src/test/scala/ArbiterTest.scala b/src/test/scala/ArbiterTest.scala new file mode 100644 index 00000000..8d5a0b2b --- /dev/null +++ b/src/test/scala/ArbiterTest.scala @@ -0,0 +1,647 @@ +/* + Copyright (c) 2011 - 2016 The Regents of the University of + California (Regents). All Rights Reserved. Redistribution and use in + source and binary forms, with or without modification, are permitted + provided that the following conditions are met: + + * Redistributions of source code must retain the above + copyright notice, this list of conditions and the following + two paragraphs of disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + two paragraphs of disclaimer in the documentation and/or other materials + provided with the distribution. + * Neither the name of the Regents nor the names of its contributors + may be used to endorse or promote products derived from this + software without specific prior written permission. + + IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, + SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, + ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF + REGENTS HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF + ANY, PROVIDED HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION + TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR + MODIFICATIONS. +*/ + +import org.junit.Test + +import Chisel._ + +/** This testsuite checks all arbiter class. +*/ +class ArbiterSuite extends TestSuite { + + @Test def testArbiter() { + class MyArbiter extends Arbiter(UInt(width=4), 4) + + class ArbiterTests(c: MyArbiter) extends Tester(c) { + + // driver + val in0_val = Array[BigInt](0,0,0,0,1,0,0,0,0) + val in1_val = Array[BigInt](0,0,0,1,0,0,0,0,0) + val in2_val = Array[BigInt](0,0,1,1,1,1,1,0,0) + val in3_val = Array[BigInt](0,0,1,1,1,1,1,1,0) + val out_rdy = Array[BigInt](0,1,0,1,1,0,1,1,0) + + // expected output + val in0_rdy = Array[BigInt](0,1,0,1,1,0,1,1,0) + val in1_rdy = Array[BigInt](0,1,0,1,0,0,1,1,0) + val in2_rdy = Array[BigInt](0,1,0,0,0,0,1,1,0) + val in3_rdy = Array[BigInt](0,1,0,0,0,0,0,1,0) + val out_val = Array[BigInt](0,0,1,1,1,1,1,1,0) + + val out_dat = Array[BigInt](3,3,2,1,0,2,2,3,3) + + val trails = 9 + + for(i <- 0 until 4) { + poke(c.io.in(i).bits, i) + poke(c.io.in(i).valid, 0) + } + + for(t <- 0 until trails) { + poke(c.io.in(0).valid, in0_val(t)) + poke(c.io.in(1).valid, in1_val(t)) + poke(c.io.in(2).valid, in2_val(t)) + poke(c.io.in(3).valid, in3_val(t)) + poke(c.io.out.ready, out_rdy(t)) + + expect(c.io.in(0).ready, in0_rdy(t)) + expect(c.io.in(1).ready, in1_rdy(t)) + expect(c.io.in(2).ready, in2_rdy(t)) + expect(c.io.in(3).ready, in3_rdy(t)) + expect(c.io.out.valid, out_val(t)) + + expect(c.io.out.bits, out_dat(t)) + + step(1) + } + } + + launchCppTester((c: MyArbiter) => new ArbiterTests(c)) + } + + @Test def testStableArbiter() { + class MyStableArbiter extends Arbiter(UInt(width=4), 4, true) + + class ArbiterTests(c: MyStableArbiter) extends Tester(c) { + + // driver + val in0_val = Array[BigInt](0,0,0,0,1,0,0,0,0) + val in1_val = Array[BigInt](0,0,0,1,1,1,1,0,1) + val in2_val = Array[BigInt](0,0,1,1,0,0,0,0,0) + val in3_val = Array[BigInt](0,0,1,1,1,1,1,1,0) + val out_rdy = Array[BigInt](0,1,0,1,1,0,1,1,1) + + // expected output + val in0_rdy = Array[BigInt](0,1,0,0,1,0,0,1,1) + val in1_rdy = Array[BigInt](0,1,0,0,0,0,1,1,1) + val in2_rdy = Array[BigInt](0,1,0,1,0,0,0,1,0) + val in3_rdy = Array[BigInt](0,1,0,0,0,0,0,1,0) + val out_val = Array[BigInt](0,0,1,1,1,1,1,1,1) + + val out_dat = Array[BigInt](3,3,2,2,0,1,1,3,1) + + val trails = 9 + + for(i <- 0 until 4) { + poke(c.io.in(i).bits, i) + poke(c.io.in(i).valid, 0) + } + + for(t <- 0 until trails) { + poke(c.io.in(0).valid, in0_val(t)) + poke(c.io.in(1).valid, in1_val(t)) + poke(c.io.in(2).valid, in2_val(t)) + poke(c.io.in(3).valid, in3_val(t)) + poke(c.io.out.ready, out_rdy(t)) + + expect(c.io.in(0).ready, in0_rdy(t)) + expect(c.io.in(1).ready, in1_rdy(t)) + expect(c.io.in(2).ready, in2_rdy(t)) + expect(c.io.in(3).ready, in3_rdy(t)) + expect(c.io.out.valid, out_val(t)) + + expect(c.io.out.bits, out_dat(t)) + + step(1) + } + } + + launchCppTester((c: MyStableArbiter) => new ArbiterTests(c)) + } + + @Test def testDefaultLockingArbiter() { + class MyDefaultLockingArbiter extends LockingArbiter(UInt(width=4), 4, 2) + + class ArbiterTests(c: MyDefaultLockingArbiter) extends Tester(c) { + + // driver + val in0_val = Array[BigInt](0,0,0,0,1,1,1,1,1,0) + val in1_val = Array[BigInt](0,0,0,1,0,1,1,0,0,0) + val in2_val = Array[BigInt](0,0,1,1,1,1,1,1,1,1) + val in3_val = Array[BigInt](0,0,1,1,1,1,1,1,1,1) + val out_rdy = Array[BigInt](0,1,0,1,1,0,1,1,1,1) + + // expected output + val in0_rdy = Array[BigInt](0,1,0,1,0,0,0,1,1,1) + val in1_rdy = Array[BigInt](0,1,0,1,1,0,1,0,0,1) + val in2_rdy = Array[BigInt](0,1,0,0,0,0,0,0,0,1) + val in3_rdy = Array[BigInt](0,1,0,0,0,0,0,0,0,0) + val out_val = Array[BigInt](0,0,1,1,0,1,1,1,1,1) + + val out_dat = Array[BigInt](3,3,2,1,1,1,1,0,0,2) + + val trails = 10 + + for(i <- 0 until 4) { + poke(c.io.in(i).bits, i) + poke(c.io.in(i).valid, 0) + } + + for(t <- 0 until trails) { + poke(c.io.in(0).valid, in0_val(t)) + poke(c.io.in(1).valid, in1_val(t)) + poke(c.io.in(2).valid, in2_val(t)) + poke(c.io.in(3).valid, in3_val(t)) + poke(c.io.out.ready, out_rdy(t)) + + expect(c.io.in(0).ready, in0_rdy(t)) + expect(c.io.in(1).ready, in1_rdy(t)) + expect(c.io.in(2).ready, in2_rdy(t)) + expect(c.io.in(3).ready, in3_rdy(t)) + expect(c.io.out.valid, out_val(t)) + + expect(c.io.out.bits, out_dat(t)) + + step(1) + } + } + + launchCppTester((c: MyDefaultLockingArbiter) => new ArbiterTests(c)) + } + + @Test def testDefaultStableLockingArbiter() { + class MyDefaultStableLockingArbiter extends LockingArbiter(UInt(width=4), 4, 2, None, true) + + class ArbiterTests(c: MyDefaultStableLockingArbiter) extends Tester(c) { + + // driver + val in0_val = Array[BigInt](0,0,0,0,1,1,1,1,1,0) + val in1_val = Array[BigInt](0,0,0,1,1,1,1,1,1,1) + val in2_val = Array[BigInt](0,0,1,1,0,1,1,0,0,0) + val in3_val = Array[BigInt](0,0,1,1,1,1,1,1,1,1) + val out_rdy = Array[BigInt](0,1,0,1,1,0,1,1,1,1) + + // expected output + val in0_rdy = Array[BigInt](0,1,0,0,0,0,0,1,1,1) + val in1_rdy = Array[BigInt](0,1,0,0,0,0,0,0,0,1) + val in2_rdy = Array[BigInt](0,1,0,1,1,0,1,0,0,0) + val in3_rdy = Array[BigInt](0,1,0,0,0,0,0,0,0,0) + val out_val = Array[BigInt](0,0,1,1,0,1,1,1,1,1) + + val out_dat = Array[BigInt](3,3,2,2,2,2,2,0,0,1) + + val trails = 10 + + for(i <- 0 until 4) { + poke(c.io.in(i).bits, i) + poke(c.io.in(i).valid, 0) + } + + for(t <- 0 until trails) { + poke(c.io.in(0).valid, in0_val(t)) + poke(c.io.in(1).valid, in1_val(t)) + poke(c.io.in(2).valid, in2_val(t)) + poke(c.io.in(3).valid, in3_val(t)) + poke(c.io.out.ready, out_rdy(t)) + + expect(c.io.in(0).ready, in0_rdy(t)) + expect(c.io.in(1).ready, in1_rdy(t)) + expect(c.io.in(2).ready, in2_rdy(t)) + expect(c.io.in(3).ready, in3_rdy(t)) + expect(c.io.out.valid, out_val(t)) + + expect(c.io.out.bits, out_dat(t)) + + step(1) + } + } + + launchCppTester((c: MyDefaultStableLockingArbiter) => new ArbiterTests(c)) + } + + @Test def testLockingArbiter() { + + //def hasDat(d: UInt):Bool = d === 0.U + class MyLockingArbiter extends LockingArbiter[UInt](UInt(width=4), 4, 2, Some((d:UInt) => d === 0.U)) + + class ArbiterTests(c: MyLockingArbiter) extends Tester(c) { + + // driver + val in0_val = Array[BigInt](0,0,0,0,1,0,1,0,0,0) + val in1_val = Array[BigInt](0,0,0,1,0,0,1,1,0,0) + val in2_val = Array[BigInt](0,0,1,1,1,1,1,1,1,0) + val in3_val = Array[BigInt](0,0,1,1,1,1,1,1,1,1) + val out_rdy = Array[BigInt](0,1,0,1,1,1,1,1,1,1) + + // expected output + val in0_rdy = Array[BigInt](0,1,0,1,1,1,1,1,1,1) + val in1_rdy = Array[BigInt](0,1,0,1,0,0,0,1,1,1) + val in2_rdy = Array[BigInt](0,1,0,0,0,0,0,0,1,1) + val in3_rdy = Array[BigInt](0,1,0,0,0,0,0,0,0,1) + val out_val = Array[BigInt](0,0,1,1,1,0,1,1,1,1) + + val out_dat = Array[BigInt](3,3,2,1,0,0,0,1,2,3) + + val trails = 10 + + for(i <- 0 until 4) { + poke(c.io.in(i).bits, i) + poke(c.io.in(i).valid, 0) + } + + for(t <- 0 until trails) { + poke(c.io.in(0).valid, in0_val(t)) + poke(c.io.in(1).valid, in1_val(t)) + poke(c.io.in(2).valid, in2_val(t)) + poke(c.io.in(3).valid, in3_val(t)) + poke(c.io.out.ready, out_rdy(t)) + + expect(c.io.in(0).ready, in0_rdy(t)) + expect(c.io.in(1).ready, in1_rdy(t)) + expect(c.io.in(2).ready, in2_rdy(t)) + expect(c.io.in(3).ready, in3_rdy(t)) + expect(c.io.out.valid, out_val(t)) + + expect(c.io.out.bits, out_dat(t)) + + step(1) + } + } + + launchCppTester((c: MyLockingArbiter) => new ArbiterTests(c)) + } + + @Test def testStableLockingArbiter() { + + //def hasDat(d: UInt):Bool = d === 0.U + class MyStableLockingArbiter extends LockingArbiter[UInt](UInt(width=4), 4, 2, Some((d:UInt) => d === 0.U), true) + + class ArbiterTests(c: MyStableLockingArbiter) extends Tester(c) { + + // driver + val in0_val = Array[BigInt](0,0,0,0,1,0,1,0,0,0) + val in1_val = Array[BigInt](0,0,0,1,1,1,1,1,0,0) + val in2_val = Array[BigInt](0,0,1,1,0,0,0,1,1,0) + val in3_val = Array[BigInt](0,0,1,1,1,1,1,1,1,1) + val out_rdy = Array[BigInt](0,1,0,1,1,1,1,1,1,1) + + // expected output + val in0_rdy = Array[BigInt](0,1,0,0,1,1,1,1,1,1) + val in1_rdy = Array[BigInt](0,1,0,0,0,0,0,1,1,1) + val in2_rdy = Array[BigInt](0,1,0,1,0,0,0,0,1,1) + val in3_rdy = Array[BigInt](0,1,0,0,0,0,0,0,0,1) + val out_val = Array[BigInt](0,0,1,1,1,0,1,1,1,1) + + val out_dat = Array[BigInt](3,3,2,2,0,0,0,1,2,3) + + val trails = 10 + + for(i <- 0 until 4) { + poke(c.io.in(i).bits, i) + poke(c.io.in(i).valid, 0) + } + + for(t <- 0 until trails) { + poke(c.io.in(0).valid, in0_val(t)) + poke(c.io.in(1).valid, in1_val(t)) + poke(c.io.in(2).valid, in2_val(t)) + poke(c.io.in(3).valid, in3_val(t)) + poke(c.io.out.ready, out_rdy(t)) + + expect(c.io.in(0).ready, in0_rdy(t)) + expect(c.io.in(1).ready, in1_rdy(t)) + expect(c.io.in(2).ready, in2_rdy(t)) + expect(c.io.in(3).ready, in3_rdy(t)) + expect(c.io.out.valid, out_val(t)) + + expect(c.io.out.bits, out_dat(t)) + + step(1) + } + } + + launchCppTester((c: MyStableLockingArbiter) => new ArbiterTests(c)) + } + + @Test def testRRArbiter() { + class MyRRArbiter extends RRArbiter(UInt(width=4), 4) + + class ArbiterTests(c: MyRRArbiter) extends Tester(c) { + + // driver + val in0_val = Array[BigInt](0,0,0,0,1,1,1,1,0) + val in1_val = Array[BigInt](0,0,0,1,0,0,0,0,0) + val in2_val = Array[BigInt](0,0,1,1,1,0,0,1,1) + val in3_val = Array[BigInt](0,0,1,1,1,1,1,0,0) + val out_rdy = Array[BigInt](0,1,0,1,1,0,1,1,1) + + // expected output + val in0_rdy = Array[BigInt](0,1,0,0,0,0,0,1,0) + val in1_rdy = Array[BigInt](0,1,0,1,0,0,0,0,1) + val in2_rdy = Array[BigInt](0,1,0,0,1,0,0,0,1) + val in3_rdy = Array[BigInt](0,1,0,0,0,0,1,0,0) + val out_val = Array[BigInt](0,0,1,1,1,1,1,1,1) + + val out_dat = Array[BigInt](3,3,2,1,2,3,3,0,2) + + val trails = 9 + + for(i <- 0 until 4) { + poke(c.io.in(i).bits, i) + poke(c.io.in(i).valid, 0) + } + + for(t <- 0 until trails) { + poke(c.io.in(0).valid, in0_val(t)) + poke(c.io.in(1).valid, in1_val(t)) + poke(c.io.in(2).valid, in2_val(t)) + poke(c.io.in(3).valid, in3_val(t)) + poke(c.io.out.ready, out_rdy(t)) + + expect(c.io.in(0).ready, in0_rdy(t)) + expect(c.io.in(1).ready, in1_rdy(t)) + expect(c.io.in(2).ready, in2_rdy(t)) + expect(c.io.in(3).ready, in3_rdy(t)) + expect(c.io.out.valid, out_val(t)) + + expect(c.io.out.bits, out_dat(t)) + + step(1) + } + } + + launchCppTester((c: MyRRArbiter) => new ArbiterTests(c)) + } + + @Test def testStableRRArbiter() { + class MyStableRRArbiter extends RRArbiter(UInt(width=4), 4, true) + + class ArbiterTests(c: MyStableRRArbiter) extends Tester(c) { + + // driver + val in0_val = Array[BigInt](0,0,0,0,1,1,1,0,0) + val in1_val = Array[BigInt](0,0,0,1,1,1,1,1,0) + val in2_val = Array[BigInt](0,0,1,1,0,0,0,0,0) + val in3_val = Array[BigInt](0,0,1,1,1,0,1,1,1) + val out_rdy = Array[BigInt](0,1,0,1,1,0,1,1,1) + + // expected output + val in0_rdy = Array[BigInt](0,1,0,0,0,0,1,0,0) + val in1_rdy = Array[BigInt](0,1,0,0,0,0,0,1,0) + val in2_rdy = Array[BigInt](0,1,0,1,0,0,0,0,1) + val in3_rdy = Array[BigInt](0,1,0,0,1,0,0,0,1) + val out_val = Array[BigInt](0,0,1,1,1,1,1,1,1) + + val out_dat = Array[BigInt](3,3,2,2,3,0,0,1,3) + + val trails = 9 + + for(i <- 0 until 4) { + poke(c.io.in(i).bits, i) + poke(c.io.in(i).valid, 0) + } + + for(t <- 0 until trails) { + poke(c.io.in(0).valid, in0_val(t)) + poke(c.io.in(1).valid, in1_val(t)) + poke(c.io.in(2).valid, in2_val(t)) + poke(c.io.in(3).valid, in3_val(t)) + poke(c.io.out.ready, out_rdy(t)) + + expect(c.io.in(0).ready, in0_rdy(t)) + expect(c.io.in(1).ready, in1_rdy(t)) + expect(c.io.in(2).ready, in2_rdy(t)) + expect(c.io.in(3).ready, in3_rdy(t)) + expect(c.io.out.valid, out_val(t)) + + expect(c.io.out.bits, out_dat(t)) + + step(1) + } + } + + launchCppTester((c: MyStableRRArbiter) => new ArbiterTests(c)) + } + + @Test def testDefaultRRLockingArbiter() { + class MyDefaultRRLockingArbiter extends LockingRRArbiter(UInt(width=4), 4, 2) + + class ArbiterTests(c: MyDefaultRRLockingArbiter) extends Tester(c) { + + // driver + val in0_val = Array[BigInt](0,0,0,0,1,1,1,1,1,1) + val in1_val = Array[BigInt](0,0,0,1,0,1,1,0,0,0) + val in2_val = Array[BigInt](0,0,1,1,1,1,1,1,1,0) + val in3_val = Array[BigInt](0,0,1,1,1,1,1,1,1,1) + val out_rdy = Array[BigInt](0,1,0,1,1,0,1,1,1,1) + + // expected output + val in0_rdy = Array[BigInt](0,1,0,0,0,0,0,0,0,0) + val in1_rdy = Array[BigInt](0,1,0,1,1,0,1,0,0,0) + val in2_rdy = Array[BigInt](0,1,0,0,0,0,0,1,1,0) + val in3_rdy = Array[BigInt](0,1,0,0,0,0,0,0,0,1) + val out_val = Array[BigInt](0,0,1,1,0,1,1,1,1,1) + + val out_dat = Array[BigInt](3,3,2,1,1,1,1,2,2,3) + + val trails = 10 + + for(i <- 0 until 4) { + poke(c.io.in(i).bits, i) + poke(c.io.in(i).valid, 0) + } + + for(t <- 0 until trails) { + poke(c.io.in(0).valid, in0_val(t)) + poke(c.io.in(1).valid, in1_val(t)) + poke(c.io.in(2).valid, in2_val(t)) + poke(c.io.in(3).valid, in3_val(t)) + poke(c.io.out.ready, out_rdy(t)) + + expect(c.io.in(0).ready, in0_rdy(t)) + expect(c.io.in(1).ready, in1_rdy(t)) + expect(c.io.in(2).ready, in2_rdy(t)) + expect(c.io.in(3).ready, in3_rdy(t)) + expect(c.io.out.valid, out_val(t)) + + expect(c.io.out.bits, out_dat(t)) + + step(1) + } + } + + launchCppTester((c: MyDefaultRRLockingArbiter) => new ArbiterTests(c)) + } + + @Test def testDefaultStableRRLockingArbiter() { + class MyDefaultStableRRLockingArbiter extends LockingRRArbiter(UInt(width=4), 4, 2, None, true) + + class ArbiterTests(c: MyDefaultStableRRLockingArbiter) extends Tester(c) { + + // driver + val in0_val = Array[BigInt](0,0,0,0,1,1,1,1,1,1) + val in1_val = Array[BigInt](0,0,0,1,1,1,1,1,1,1) + val in2_val = Array[BigInt](0,0,1,1,0,1,1,0,0,0) + val in3_val = Array[BigInt](0,0,1,1,1,1,1,1,1,0) + val out_rdy = Array[BigInt](0,1,0,1,1,0,1,1,1,1) + + // expected output + val in0_rdy = Array[BigInt](0,1,0,0,0,0,0,0,0,1) + val in1_rdy = Array[BigInt](0,1,0,0,0,0,0,0,0,0) + val in2_rdy = Array[BigInt](0,1,0,1,1,0,1,0,0,0) + val in3_rdy = Array[BigInt](0,1,0,0,0,0,0,1,1,0) + val out_val = Array[BigInt](0,0,1,1,0,1,1,1,1,1) + + val out_dat = Array[BigInt](3,3,2,2,2,2,2,3,3,0) + + val trails = 10 + + for(i <- 0 until 4) { + poke(c.io.in(i).bits, i) + poke(c.io.in(i).valid, 0) + } + + for(t <- 0 until trails) { + poke(c.io.in(0).valid, in0_val(t)) + poke(c.io.in(1).valid, in1_val(t)) + poke(c.io.in(2).valid, in2_val(t)) + poke(c.io.in(3).valid, in3_val(t)) + poke(c.io.out.ready, out_rdy(t)) + + expect(c.io.in(0).ready, in0_rdy(t)) + expect(c.io.in(1).ready, in1_rdy(t)) + expect(c.io.in(2).ready, in2_rdy(t)) + expect(c.io.in(3).ready, in3_rdy(t)) + expect(c.io.out.valid, out_val(t)) + + expect(c.io.out.bits, out_dat(t)) + + step(1) + } + } + + launchCppTester((c: MyDefaultStableRRLockingArbiter) => new ArbiterTests(c)) + } + + @Test def testRRLockingArbiter() { + + //def hasDat(d: UInt):Bool = d === 0.U + class MyRRLockingArbiter extends LockingRRArbiter[UInt](UInt(width=4), 4, 2, Some((d:UInt) => d === 3.U)) + + class ArbiterTests(c: MyRRLockingArbiter) extends Tester(c) { + + // driver + val in0_val = Array[BigInt](0,0,0,0,1,1,1,1,0) + val in1_val = Array[BigInt](0,0,0,1,0,0,0,0,0) + val in2_val = Array[BigInt](0,0,0,0,0,1,1,1,1) + val in3_val = Array[BigInt](0,0,1,1,1,0,1,1,0) + val out_rdy = Array[BigInt](0,1,0,1,1,1,1,1,1) + + // expected output + val in0_rdy = Array[BigInt](0,1,0,0,0,0,0,1,0) + val in1_rdy = Array[BigInt](0,1,0,1,0,0,0,0,1) + val in2_rdy = Array[BigInt](0,1,0,0,1,0,0,0,1) + val in3_rdy = Array[BigInt](0,1,0,0,1,1,1,0,0) + val out_val = Array[BigInt](0,0,1,1,1,0,1,1,1) + + val out_dat = Array[BigInt](3,3,3,1,3,3,3,0,2) + + val trails = 9 + + for(i <- 0 until 4) { + poke(c.io.in(i).bits, i) + poke(c.io.in(i).valid, 0) + } + + for(t <- 0 until trails) { + poke(c.io.in(0).valid, in0_val(t)) + poke(c.io.in(1).valid, in1_val(t)) + poke(c.io.in(2).valid, in2_val(t)) + poke(c.io.in(3).valid, in3_val(t)) + poke(c.io.out.ready, out_rdy(t)) + + expect(c.io.in(0).ready, in0_rdy(t)) + expect(c.io.in(1).ready, in1_rdy(t)) + expect(c.io.in(2).ready, in2_rdy(t)) + expect(c.io.in(3).ready, in3_rdy(t)) + expect(c.io.out.valid, out_val(t)) + + expect(c.io.out.bits, out_dat(t)) + + step(1) + } + } + + launchCppTester((c: MyRRLockingArbiter) => new ArbiterTests(c)) + } + + @Test def testStableRRLockingArbiter() { + + //def hasDat(d: UInt):Bool = d === 0.U + class MyStableRRLockingArbiter extends LockingRRArbiter[UInt](UInt(width=4), 4, 2, Some((d:UInt) => d === 3.U), true) + + class ArbiterTests(c: MyStableRRLockingArbiter) extends Tester(c) { + + // driver + val in0_val = Array[BigInt](0,0,0,0,1,1,1,0,0) + val in1_val = Array[BigInt](0,0,0,1,1,1,0,0,0) + val in2_val = Array[BigInt](0,0,0,0,0,0,0,1,0) + val in3_val = Array[BigInt](0,0,1,1,0,1,0,0,0) + val out_rdy = Array[BigInt](0,1,0,1,1,1,1,1,1) + + // expected output + val in0_rdy = Array[BigInt](0,1,0,0,0,0,1,0,1) + val in1_rdy = Array[BigInt](0,1,0,0,0,0,0,1,1) + val in2_rdy = Array[BigInt](0,1,0,0,0,0,0,1,1) + val in3_rdy = Array[BigInt](0,1,0,1,1,1,0,0,1) + val out_val = Array[BigInt](0,0,1,1,0,1,1,1,0) + + val out_dat = Array[BigInt](3,3,3,3,3,3,0,2,3) + + val trails = 9 + + for(i <- 0 until 4) { + poke(c.io.in(i).bits, i) + poke(c.io.in(i).valid, 0) + } + + for(t <- 0 until trails) { + poke(c.io.in(0).valid, in0_val(t)) + poke(c.io.in(1).valid, in1_val(t)) + poke(c.io.in(2).valid, in2_val(t)) + poke(c.io.in(3).valid, in3_val(t)) + poke(c.io.out.ready, out_rdy(t)) + + expect(c.io.in(0).ready, in0_rdy(t)) + expect(c.io.in(1).ready, in1_rdy(t)) + expect(c.io.in(2).ready, in2_rdy(t)) + expect(c.io.in(3).ready, in3_rdy(t)) + expect(c.io.out.valid, out_val(t)) + + expect(c.io.out.bits, out_dat(t)) + + step(1) + } + } + + launchCppTester((c: MyStableRRLockingArbiter) => new ArbiterTests(c)) + } + +} diff --git a/src/test/scala/AssertSuite.scala b/src/test/scala/AssertSuite.scala new file mode 100644 index 00000000..be08ef17 --- /dev/null +++ b/src/test/scala/AssertSuite.scala @@ -0,0 +1,100 @@ +/* + Copyright (c) 2011 - 2016 The Regents of the University of + California (Regents). All Rights Reserved. Redistribution and use in + source and binary forms, with or without modification, are permitted + provided that the following conditions are met: + + * Redistributions of source code must retain the above + copyright notice, this list of conditions and the following + two paragraphs of disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + two paragraphs of disclaimer in the documentation and/or other materials + provided with the distribution. + * Neither the name of the Regents nor the names of its contributors + may be used to endorse or promote products derived from this + software without specific prior written permission. + + IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, + SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, + ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF + REGENTS HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF + ANY, PROVIDED HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION + TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR + MODIFICATIONS. +*/ + +import org.junit.Assert._ +import org.junit.Test +import org.junit.Ignore +import org.scalatest._ + +import Chisel._ + +class AssertSuite extends TestSuite with ShouldMatchers { + @Test def testAssert() { + println("\ntestAssert...") + class AssertModule extends Module { + class IO extends Bundle { + val in0 = SInt(INPUT, width=32) + val out0 = SInt(OUTPUT, width=32) + } + val io = new IO() + io.in0.setIsTypeNode + } + + val testArgs = chiselEnvironmentArguments() ++ Array("--targetDir", dir.getPath.toString()) + intercept[AssertionError] { + // This should fail since io.out does not have a default value. + chiselMain(testArgs, () => Module(new AssertModule)) + } + assertTrue(ChiselError.hasErrors) + } + + @Test def testRTAssert() { + println("\ntestRTAssert...") + val assertMessage = "io.dataIn == 8.U" + class mkAssert extends Module{ + val io = new Bundle{ + val dataIn = UInt(INPUT,8) + val dataOut = UInt(OUTPUT,width=3) + } + + io.dataOut := OHToUInt(io.dataIn) + assert(io.dataIn =/= 8.U, assertMessage) + } + + class TBAssert(c: mkAssert) extends Tester(c) { + step(1) + poke(c.io.dataIn, 32) + peek(c.io.dataOut) + step(1) + poke(c.io.dataIn, 16) + peek(c.io.dataOut) + step(1) + poke(c.io.dataIn,8) + peek(c.io.dataOut) + step(1) + poke(c.io.dataIn, 0) + peek(c.io.dataOut) + } + + val swArgs = Array("--backend", "c", "--genHarness","--targetDir","cpp","--compile","--test","--debug"/*, "--assertWarn"*/) + val hwArgs = Array("--backend", "v","--genHarness","--targetDir","rtl") + + "sw" match { + case "sw" => { + val ex = intercept[TestApplicationException] { + chiselMainTest(swArgs, () => Module(new mkAssert)){ c => new TBAssert(c)} + } + // Verify the exception message contains our assertion message. + ex.getMessage should endWith (assertMessage) + } + case "hw" => chiselMain(hwArgs, () => Module(new mkAssert)) + } + } +} diff --git a/src/test/scala/BitPatSuite.scala b/src/test/scala/BitPatSuite.scala new file mode 100644 index 00000000..9749b7e2 --- /dev/null +++ b/src/test/scala/BitPatSuite.scala @@ -0,0 +1,89 @@ +/* + Copyright (c) 2011 - 2016 The Regents of the University of + California (Regents). All Rights Reserved. Redistribution and use in + source and binary forms, with or without modification, are permitted + provided that the following conditions are met: + + * Redistributions of source code must retain the above + copyright notice, this list of conditions and the following + two paragraphs of disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + two paragraphs of disclaimer in the documentation and/or other materials + provided with the distribution. + * Neither the name of the Regents nor the names of its contributors + may be used to endorse or promote products derived from this + software without specific prior written permission. + + IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, + SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, + ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF + REGENTS HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF + ANY, PROVIDED HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION + TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR + MODIFICATIONS. +*/ + +import org.junit.Assert._ +import org.junit.Test +import org.junit.Ignore + +import Chisel._ + +class BitPatSuite extends TestSuite { + // BitPat ? literals + @Test def testBitPat() { + println("\ntestBitPat...") + class BitPatModule extends Module { + val io = new Bundle { + val in = UInt(INPUT,4) + val out = Bool(OUTPUT) + } + io.out := Bool(false) + switch(io.in) { + is(0.U) { io.out := Bool(true) } + is(BitPat("b???1")) { io.out := Bool(true) } + } + } + + class BitPatModuleTests(m: BitPatModule) extends Tester(m) { + (0 until 8).map { i => + poke(m.io.in, i) + step(1) + expect(m.io.out, if(i == 0) (1) else (i % 2)) + } + } + + launchCppTester((m: BitPatModule) => new BitPatModuleTests(m)) + } + + @Test def testBitPatBool() { + println("\ntestBitPatBool...") + class BitPatBoolModule extends Module { + val io = new Bundle { + val in = Bool(INPUT) + val out = Bool(OUTPUT) + } + io.out := Bool(false) + val testDC = Bool.DC + val testTrue = Bool(true) + switch(io.in) { + is(testDC) { io.out := Bool(true) } + } + } + + class BitPatBoolModuleTests(m: BitPatBoolModule) extends Tester(m) { + (0 until 8).map { i => + poke(m.io.in, i) + step(1) + expect(m.io.out, 1) + } + } + + launchCppTester((m: BitPatBoolModule) => new BitPatBoolModuleTests(m)) + } +} diff --git a/src/test/scala/BitsTest.scala b/src/test/scala/BitsTest.scala index 0b5f3e0a..e12d3df9 100644 --- a/src/test/scala/BitsTest.scala +++ b/src/test/scala/BitsTest.scala @@ -1,5 +1,5 @@ /* - Copyright (c) 2011, 2012, 2013, 2014 The Regents of the University of + Copyright (c) 2011 - 2016 The Regents of the University of California (Regents). All Rights Reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: @@ -44,94 +44,149 @@ class BitsSuite extends TestSuite { /** Extract a bit from a constant at a fixed position */ @Test def testExtractConstantFixed() { - val res = UInt(5)(0) - assertTrue( res.getWidth == 1 ) - assertTrue( res.litOf.value == 1 ) + class Dummy extends Module { + val io = UInt(INPUT, 0) + val res = 5.U(0) + assertTrue( res.getWidth == 1 ) + assertTrue( res.litValue() == 1 ) + } + val dummyInst = Module(new Dummy) } /** Extract from a constant a fixed range of bits */ @Test def testExtractConstantRangeFixed() { - val res = UInt(5)((1, 0)) - assertTrue( res.getWidth == 2 ) + class Dummy extends Module { + val io = UInt(INPUT, 0) + val res = 5.U((1, 0)) + assertTrue( res.getWidth == 2 ) + } + val dummyInst = Module(new Dummy) } /** Equality */ @Test def testEql() { - val res = Bits(2) === Bits(2) - assertTrue( res.getWidth == 1 ) - assertTrue( res.litOf.value == 1 ) + class Dummy extends Module { + val io = UInt(INPUT, 0) + val res = Bits(2) === Bits(2) + assertTrue( res.getWidth == 1 ) + assertTrue( res.litValue() == 1 ) + } + val dummyInst = Module(new Dummy) } @Test def testEqlBundle() { - val res = Bits(2) === new Bundle{ val abc = Bits(2) }.toBits - assertTrue( res.getWidth == 1 ) + class Dummy extends Module { + val io = UInt(INPUT, 0) + val res = Bits(2) === new Bundle{ val abc = Bits(2) }.toBits + assertTrue( res.getWidth == 1 ) + } + val dummyInst = Module(new Dummy) } @Test def testEqlVec() { - val res = Bits(2) === Vec(Bits(2) :: Nil).toBits - assertTrue( res.getWidth == 1 ) + class Dummy extends Module { + val io = UInt(INPUT, 0) + val res = Bits(2) === Vec(Bits(2) :: Nil).toBits + assertTrue( res.getWidth == 1 ) + } + val dummyInst = Module(new Dummy) } @Test def testNeg() { - val res = ~Bits(2) - assertTrue( res.getWidth == 2 ) - assertTrue( res.litOf.value == 1 ) + class Dummy extends Module { + val io = UInt(INPUT, 0) + val res = ~Bits(2) + assertTrue( res.getWidth == 2 ) + assertTrue( res.litValue() == 1 ) + } + val dummyInst = Module(new Dummy) } /* AND Reduction */ @Test def testAndR() { - val res = Bits(5).andR - assertTrue( res.getWidth == 1 ) + class Dummy extends Module { + val io = UInt(INPUT, 0) + val res = Bits(5).andR + assertTrue( res.getWidth == 1 ) + } + val dummyInst = Module(new Dummy) } /* OR Reduction */ @Test def testOrR() { - val res = Bits(5).orR - assertTrue( res.getWidth == 1) + class Dummy extends Module { + val io = UInt(INPUT, 0) + val res = Bits(5).orR + assertTrue( res.getWidth == 1) + } + val dummyInst = Module(new Dummy) } /* XOR Reduction */ @Test def testXorR() { - val res = Bits(5).xorR - assertTrue( res.getWidth == 1) + class Dummy extends Module { + val io = UInt(INPUT, 0) + val res = Bits(5).xorR + assertTrue( res.getWidth == 1) + } + val dummyInst = Module(new Dummy) } /* inequality */ @Test def testNeq() { - val res = Bits(5) != Bits(4) - assertTrue( res.getWidth == 1 ) - assertTrue( res.litOf.value == 1 ) + class Dummy extends Module { + val io = UInt(INPUT, 0) + val res = Bits(5) =/= Bits(4) + assertTrue( res.getWidth == 1 ) + assertTrue( res.litValue() == 1 ) + } + val dummyInst = Module(new Dummy) } /* bitwise and */ @Test def testAnd() { - val res = Bits(5) & Bits(4) - assertTrue( res.getWidth == 3 ) - assertTrue( res.litOf.value == 4 ) + class Dummy extends Module { + val io = UInt(INPUT, 0) + val res = Bits(5) & Bits(4) + assertTrue( res.getWidth == 3 ) + assertTrue( res.litValue() == 4 ) + } + val dummyInst = Module(new Dummy) } /* bitwise or */ @Test def testOr() { - val res = Bits(5) | Bits(4) - assertTrue( res.getWidth == 3 ) - assertTrue( res.litOf.value == 5 ) + class Dummy extends Module { + val io = UInt(INPUT, 0) + val res = Bits(5) | Bits(4) + assertTrue( res.getWidth == 3 ) + assertTrue( res.litValue() == 5 ) + } + val dummyInst = Module(new Dummy) } /* bitwise xor */ @Test def testXor() { - val res = Bits(5) ^ Bits(4) - assertTrue( res.getWidth == 3 ) - assertTrue( res.litOf.value == 1 ) + class Dummy extends Module { + val io = UInt(INPUT, 0) + val res = Bits(5) ^ Bits(4) + assertTrue( res.getWidth == 3 ) + assertTrue( res.litValue() == 1 ) + } } /* Concatenation */ @Test def testCat() { - try { - val res = Bits(5) ## Bits(4) - assertTrue( res.getWidth == 6 ) - assertTrue( res.litOf.value == 44 ) - } catch { - case e : Throwable => e.printStackTrace() + class Dummy extends Module { + val io = UInt(INPUT, 0) + try { + val res = Bits(5) ## Bits(4) + assertTrue( res.getWidth == 6 ) + assertTrue( res.litValue() == 44 ) + } catch { + case e : Throwable => e.printStackTrace() + } } + val dummyInst = Module(new Dummy) } } diff --git a/src/test/scala/BundleWire.scala b/src/test/scala/BundleWire.scala new file mode 100644 index 00000000..33ee7a25 --- /dev/null +++ b/src/test/scala/BundleWire.scala @@ -0,0 +1,105 @@ +//package ChiselTests +import Chisel._ +import org.junit.Assert._ +import org.junit.Test +import org.junit.Ignore + +class Coord extends Bundle { + val x = UInt(width = 32) + val y = UInt(width = 32) + // We leave this as "clone" (we support the more correct "cloneType") + // to ensure that the "old" usage is still supported. + override def clone: this.type = { + val res = new Coord() + res.x.dir = this.x.dir + res.y.dir = this.y.dir + res.asInstanceOf[this.type] + } +} + + class BundleWireSuite extends TestSuite { + + @Test def testBundleWire() { + println("\ntestBundleWire ...") + + class BundleWire extends Module { + val io = new Bundle { + val in = (new Coord).asInput + val outs = Vec(4, (new Coord).asOutput) + } + val coords = Wire(Vec(4, new Coord)) + for (i <- 0 until 4) { + coords(i) := io.in + io.outs(i) := coords(i) + } + } + + trait BundleWireTests extends Tests { + def tests(c: BundleWire) { + for (t <- 0 until 4) { + val test_in_x = rnd.nextInt(256) + val test_in_y = rnd.nextInt(256) + poke(c.io.in.x, test_in_x) + poke(c.io.in.y, test_in_y) + step(1) + for (i <- 0 until 4) { + expect(c.io.outs(i).x, test_in_x) + expect(c.io.outs(i).y, test_in_y) + } + } + } + } + + class BundleWireTester(c: BundleWire) extends Tester(c) with BundleWireTests { + tests(c) + } + val args = chiselEnvironmentArguments() ++ Array[String]("--backend", "c", + "--targetDir", dir.getPath.toString(), "--genHarness", "--compile", "--test") + chiselMainTest(args, () => Module(new BundleWire())) {m => new BundleWireTester(m)} + } + + @Test def testBundleWire2() { + println("\ntestBundleWire2 ...") + + class BundleWire extends Module { + val io = new Bundle { + val in = (new Coord).asInput + val outs = Vec(4, (new Coord).asOutput) + } + val coords = Wire(new Bundle { + val a0 = new Coord + val a1 = new Coord + val a2 = new Coord + val a3 = new Coord + def apply(i: Int) = i match { + case 0 => a0 + case 1 => a1 + case 2 => a2 + case 3 => a3 + } + }) + for (i <- 0 until 4) { + coords(i) := io.in + io.outs(i) := coords(i) + } + } + + class BundleWireTester(c: BundleWire) extends Tester(c) { + for (t <- 0 until 4) { + val test_in_x = rnd.nextInt(256) + val test_in_y = rnd.nextInt(256) + poke(c.io.in.x, test_in_x) + poke(c.io.in.y, test_in_y) + step(1) + for (i <- 0 until 4) { + expect(c.io.outs(i).x, test_in_x) + expect(c.io.outs(i).y, test_in_y) + } + } + } + + val args = chiselEnvironmentArguments() ++ Array[String]("--backend", "c", + "--targetDir", dir.getPath.toString(), "--genHarness", "--compile", "--test") + chiselMainTest(args, () => Module(new BundleWire())) {m => new BundleWireTester(m)} + } +} diff --git a/src/test/scala/Chisel3Compatibility.scala b/src/test/scala/Chisel3Compatibility.scala new file mode 100644 index 00000000..e334c0dc --- /dev/null +++ b/src/test/scala/Chisel3Compatibility.scala @@ -0,0 +1,307 @@ +/* + Copyright (c) 2011 - 2016 The Regents of the University of + California (Regents). All Rights Reserved. Redistribution and use in + source and binary forms, with or without modification, are permitted + provided that the following conditions are met: + + * Redistributions of source code must retain the above + copyright notice, this list of conditions and the following + two paragraphs of disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + two paragraphs of disclaimer in the documentation and/or other materials + provided with the distribution. + * Neither the name of the Regents nor the names of its contributors + may be used to endorse or promote products derived from this + software without specific prior written permission. + + IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, + SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, + ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF + REGENTS HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF + ANY, PROVIDED HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION + TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR + MODIFICATIONS. +*/ + +import Chisel._ +import org.junit.Assert._ +import org.junit.Test +import org.junit.Ignore + +class Chisel3CompatibilitySuite extends TestSuite { + @Test def testMissingWire() { + println("\ntestMissingWire ...") + + class OptionalWire(noWire: Boolean) extends Module { + + val io = IO(new Bundle { + val out = UInt(OUTPUT, 16) + }) + + val aLit = UInt(42, 16) + // The following should fail without a Wire wrapper. + if (noWire) { + val aTemp = UInt(width=16) + aTemp := aLit + io.out := aTemp + } else { + val aTemp = Wire(UInt(width=16)) + aTemp := aLit + io.out := aTemp + } + } + + class WireTester(c: OptionalWire) extends Tester(c) { + expect(c.io.out, 42) + } + + val testArgs = chiselEnvironmentArguments() ++ Array("--targetDir", dir.getPath.toString(), + "--minimumCompatibility", "3.0.0", "--wError", "--backend", "c", "--genHarness", "--compile", "--test") + intercept[IllegalStateException] { + // This should fail since we don't use a Wire wrapper + chiselMainTest(testArgs, () => Module(new OptionalWire(true))){ c => new WireTester(c) } + } + assertTrue(ChiselError.hasErrors) + + // This should pass + chiselMainTest(testArgs, () => Module(new OptionalWire(false))){ c => new WireTester(c) } + assertFalse(ChiselError.hasErrors) + } + + @Test def testMissingIO() { + println("\ntestMissingIO ...") + + class OptionalIO(noIO: Boolean) extends Module { + + val io = if (noIO) { + // The following should fail without an IO wrapper. + new Bundle { + val out = UInt(OUTPUT, 16) + } + } else { + IO(new Bundle { + val out = UInt(OUTPUT, 16) + }) + } + + val aLit = UInt(42, 16) + io.out := aLit + } + + class IOTester(c: OptionalIO) extends Tester(c) { + expect(c.io.out, 42) + } + + val testArgs = chiselEnvironmentArguments() ++ Array("--targetDir", dir.getPath.toString(), + "--minimumCompatibility", "3.0.0", "--wError", "--backend", "c", "--genHarness", "--compile", "--test") + intercept[IllegalStateException] { + // This should fail since we don't use a Wire wrapper + chiselMainTest(testArgs, () => Module(new OptionalIO(true))){ c => new IOTester(c) } + } + assertTrue(ChiselError.hasErrors) + + // This should pass + chiselMainTest(testArgs, () => Module(new OptionalIO(false))){ c => new IOTester(c) } + assertFalse(ChiselError.hasErrors) + } + + @Test def testBadWireWrap() { + println("\ntestBadWireWrap ...") + + class OptionalWire(noWire: Boolean) extends Module { + + val io = IO(new Bundle { + val out = UInt(OUTPUT, 16) + }) + + val aLit = UInt(42, 16) + // The following should pass without a Wire wrapper. + if (noWire) { + val aTemp = aLit + io.out := aTemp + } else { + val aTemp = Wire(aLit) + io.out := aTemp + } + } + + class WireTester(c: OptionalWire) extends Tester(c) { + expect(c.io.out, 42) + } + + val testArgs = chiselEnvironmentArguments() ++ Array("--targetDir", dir.getPath.toString(), + "--minimumCompatibility", "3.0.0", "--wError", "--backend", "c", "--genHarness", "--compile", "--test") + + // This should pass (no Wire() wrapper) + chiselMainTest(testArgs, () => Module(new OptionalWire(true))){ c => new WireTester(c) } + assertFalse(ChiselError.hasErrors) + + // This should fail since we use a Wire wrapper around a node with data + intercept[IllegalStateException] { + chiselMainTest(testArgs, () => Module(new OptionalWire(false))){ c => new WireTester(c) } + } + assertTrue(ChiselError.hasErrors) + } + + @Test def testBadMixedMux() { + println("\ntestBadMixedMux ...") + + class OptionalMux(mixedTypes: Boolean) extends Module { + + val io = IO(new Bundle { + val t = Bool(INPUT) + val c = UInt(INPUT, 8) + val ua = UInt(INPUT, 8) + val sa = SInt(INPUT, 8) + val out = UInt(OUTPUT) + }) + + // The following should fail if mixedTypes is true. + if (mixedTypes) { + io.out := Mux(io.t, io.c, io.sa) + } else { + io.out := Mux(io.t, io.c, io.ua) + } + } + + class OptionalMuxTester(c: OptionalMux) extends Tester(c) { + poke(c.io.c, 42) + poke(c.io.ua, 1) + poke(c.io.sa, 1) + poke(c.io.t, 1) + step(1) + expect(c.io.out, 42) + } + + val testArgs = chiselEnvironmentArguments() ++ Array("--targetDir", dir.getPath.toString(), + "--minimumCompatibility", "3.0.0", "--wError", "--backend", "c", "--genHarness", "--compile", "--test") + + // This should pass (mixedTypes is false) + chiselMainTest(testArgs, () => Module(new OptionalMux(false))){ c => new OptionalMuxTester(c) } + assertFalse(ChiselError.hasErrors) + + // This should fail since we use mixed types. + intercept[IllegalStateException] { + chiselMainTest(testArgs, () => Module(new OptionalMux(true))){ c => new OptionalMuxTester(c) } + } + assertTrue(ChiselError.hasErrors) + } + + @Test def testSubwordNoWireWrap() { + println("\ntestSubwordNoWireWrap ...") + + class SubwordNoWire() extends Module { + + val io = IO(new Bundle { + val out = UInt(OUTPUT, 16) + }) + + // The following should pass without a Wire wrapper. + val foo = Reg(Bits(width = 16)) + foo(0) := 1.U + io.out := foo + } + + class WireTester(c: SubwordNoWire) extends Tester(c) { + expect(c.io.out, 1) + } + + val testArgs = chiselEnvironmentArguments() ++ Array("--targetDir", dir.getPath.toString(), + "--minimumCompatibility", "3.0.0", "--wError", "--backend", "c", "--genHarness", "--compile", "--test") + + // This should pass (no Wire() wrapper) + chiselMainTest(testArgs, () => Module(new SubwordNoWire())){ c => new WireTester(c) } + assertFalse(ChiselError.hasErrors) + } + + @Test def testSeqWire() { + println("\ntestSeqWire ...") + + class SeqWire() extends Module { + val io = IO(new Bundle { + }) + val nBools = 4 + val seqBool = (0 until nBools).map ( a => + Bool() + ) + + for (i <- 0 until nBools) { + seqBool(i) := Bool(true) + } + } + + val testArgs = chiselEnvironmentArguments() ++ Array("--targetDir", dir.getPath.toString(), + "--minimumCompatibility", "3.0.0", "--wError", "--backend", "c") + intercept[IllegalStateException] { + // This should fail since we don't use a Wire wrapper + chiselMain(testArgs, () => Module(new SeqWire())) + } + assertTrue(ChiselError.hasErrors) + } + + @Test def testNoCloneType() { + println("\ntestNoCloneType ...") + + class NoCloneType() extends Module { + class MyBundle(aWidth: Int) extends Bundle { + val aVal = UInt(width = aWidth) + } + val io = IO(new Bundle { + val ins = Vec(3, new MyBundle(8).asInput) + }) + } + + val testArgs = chiselEnvironmentArguments() ++ Array("--targetDir", dir.getPath.toString(), + "--minimumCompatibility", "3.0.0", "--wError", "--backend", "c") + intercept[IllegalStateException] { + // This should fail since we don't define a cloneType method for MyBundle and it is needed for Vec. + chiselMain(testArgs, () => Module(new NoCloneType())) + } + assertTrue(ChiselError.hasErrors) + } + + @Test def testUIntSIntConnect() { + println("\ntestUIntSIntConnect ...") + + class UIntSIntConnect() extends Module { + val io = IO(new Bundle { + val inU = UInt(width = 4).asInput() + val outS = SInt(width = 4).asOutput() + }) + io.outS := io.inU + } + + val testArgs = chiselEnvironmentArguments() ++ Array("--targetDir", dir.getPath.toString(), + "--minimumCompatibility", "3.0.0", "--wError", "--backend", "c") + intercept[IllegalStateException] { + // This should fail since UInt <-> SInt connections are illegal in Chisel3. + chiselMain(testArgs, () => Module(new UIntSIntConnect())) + } + assertTrue(ChiselError.hasErrors) + } + + @Test def testSIntUIntConnect() { + println("\ntestSIntUIntConnect ...") + + class SIntUIntConnect() extends Module { + val io = IO(new Bundle { + val inS = SInt(width = 4).asInput() + val outU = UInt(width = 4).asOutput() + }) + io.outU := io.inS + } + + val testArgs = chiselEnvironmentArguments() ++ Array("--targetDir", dir.getPath.toString(), + "--minimumCompatibility", "3.0.0", "--wError", "--backend", "c") + intercept[IllegalStateException] { + // This should fail since UInt <-> SInt connections are illegal in Chisel3. + chiselMain(testArgs, () => Module(new SIntUIntConnect())) + } + assertTrue(ChiselError.hasErrors) + } +} diff --git a/src/test/scala/CombLoopTests.scala b/src/test/scala/CombLoopTests.scala new file mode 100644 index 00000000..5db96b01 --- /dev/null +++ b/src/test/scala/CombLoopTests.scala @@ -0,0 +1,71 @@ +/* + Copyright (c) 2011 - 2016 The Regents of the University of + California (Regents). All Rights Reserved. Redistribution and use in + source and binary forms, with or without modification, are permitted + provided that the following conditions are met: + + * Redistributions of source code must retain the above + copyright notice, this list of conditions and the following + two paragraphs of disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + two paragraphs of disclaimer in the documentation and/or other materials + provided with the distribution. + * Neither the name of the Regents nor the names of its contributors + may be used to endorse or promote products derived from this + software without specific prior written permission. + + IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, + SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, + ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF + REGENTS HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF + ANY, PROVIDED HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION + TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR + MODIFICATIONS. +*/ + +import Chisel._ +import org.junit.Assert._ +import org.junit.Test +import org.junit.Ignore + +class CombLoopSuite extends TestSuite { + @Test def testCombLoop() { + println("\ntestCombLoop ...") + + class CombLoopModule extends Module { + val io = new Bundle { + val in = Decoupled(UInt(width=16)).flip + val out = Decoupled(UInt(width=16)) + } + io.in <> io.out + } + + class CombLoopWrapper extends Module { + val io = new Bundle { + val out = Decoupled(UInt(width=16)) + } + val mod1 = Module(new CombLoopModule) + val mod2 = Module(new CombLoopModule) + val mod3 = Module(new CombLoopModule) + mod1.io.out <> mod2.io.in + mod2.io.out <> mod3.io.in + mod3.io.out <> mod1.io.in + io.out.bits := mod3.io.out.bits + io.out.valid := mod3.io.out.valid + mod3.io.out.ready := io.out.ready + } + + val testArgs = chiselEnvironmentArguments() ++ Array("--targetDir", dir.getPath.toString(), + "--minimumCompatibility", "3.0.0", "--wError", "--backend", "c") + intercept[IllegalStateException] { + // This should fail since we don't use a Wire wrapper + chiselMain(testArgs, () => Module(new CombLoopWrapper)) + } + assertTrue(ChiselError.hasErrors) + } +} diff --git a/src/test/scala/ComplexSuite.scala b/src/test/scala/ComplexSuite.scala new file mode 100644 index 00000000..9d2094a5 --- /dev/null +++ b/src/test/scala/ComplexSuite.scala @@ -0,0 +1,154 @@ +/* + Copyright (c) 2011 - 2016 The Regents of the University of + California (Regents). All Rights Reserved. Redistribution and use in + source and binary forms, with or without modification, are permitted + provided that the following conditions are met: + + * Redistributions of source code must retain the above + copyright notice, this list of conditions and the following + two paragraphs of disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + two paragraphs of disclaimer in the documentation and/or other materials + provided with the distribution. + * Neither the name of the Regents nor the names of its contributors + may be used to endorse or promote products derived from this + software without specific prior written permission. + + IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, + SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, + ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF + REGENTS HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF + ANY, PROVIDED HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION + TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR + MODIFICATIONS. +*/ +import org.junit.Assert._ +import org.junit.Test +import org.junit.Ignore + +//package ChiselTests +import Chisel._ + + +/** This testsuite checks the Complex class implementation. +*/ +class ComplexSuite extends TestSuite { + // Test Complex assignment + @Test def testComplexAssignment() { + class ComplexAssign(W: Int) extends Module { + val io = new Bundle { + val e = /* new */ Bool(INPUT) + val in = new Complex(Bits(width = W), Bits(width = W)).asInput + val out = new Complex(Bits(width = W), Bits(width = W)).asOutput + } + when (io.e) { +// val w = Wire(new Complex(Bits(width = W), Bits(width = W))) +// w := io.in + io.out.real := io.in.real + io.out.imag := io.in.imag + } .otherwise { + io.out.real := Bits(0) + io.out.imag := Bits(0) + } + } + + trait ComplexAssignTests extends Tests { + def tests(c: ComplexAssign) { + for (t <- 0 until 4) { + val test_e = rnd.nextInt(2) + val test_in_real = rnd.nextInt(256) + val test_in_imag = rnd.nextInt(256) + + poke(c.io.e, test_e) + poke(c.io.in.real, test_in_real) + poke(c.io.in.imag, test_in_imag) + step(1) + expect(c.io.out.real, if (test_e == 1) test_in_real else 0) + expect(c.io.out.imag, if (test_e == 1) test_in_imag else 0) + } + } + } + + class ComplexAssignTester(c: ComplexAssign) extends Tester(c) with ComplexAssignTests { + tests(c) + } + + val testArgs = chiselEnvironmentArguments() ++ Array("--compile", "--genHarness", "--test", "--targetDir", dir.getPath) + chiselMainTest(testArgs.toArray, () => Module(new ComplexAssign(16))) { + c => new ComplexAssignTester(c) + } + } + + // Test Complex arithmetic + @Test def testComplex() { + class ComplexTest(W: Int) extends Module { + val io = new Bundle { + val in_t = Complex(SInt(width=W),SInt(width=W)).asInput + val in_f = Complex(SInt(width=W),SInt(width=W)).asInput + val cond = Bool(INPUT) + val out = Complex(SInt(width=W),SInt(width=W)).asOutput + + val b_t = UInt(width=1).asInput + val b_f = UInt(width=1).asInput + val b_o = UInt(width=1).asOutput + } + + val myLit = Complex(SInt(1, W), SInt(1, W)) + + io.out := Mux(io.cond, io.in_t + io.in_f, io.in_t - io.in_f) + myLit + + io.b_o := Mux(io.cond, io.b_t, Bool(false)) + + } + + trait ComplexTests extends Tests { + def tests(c: ComplexTest) { + for (t <- 0 until 4) { + val test_cond = rnd.nextInt(2) + val test_in_t_real = rnd.nextInt(256) + val test_in_t_imag = rnd.nextInt(256) + val test_in_f_real = rnd.nextInt(256) + val test_in_f_imag = rnd.nextInt(256) + val test_b_t = rnd.nextInt(2) + val test_b_f = rnd.nextInt(2) + + poke(c.io.cond, test_cond) + poke(c.io.in_t.real, test_in_t_real) + poke(c.io.in_t.imag, test_in_t_imag) + poke(c.io.in_f.real, test_in_f_real) + poke(c.io.in_f.imag, test_in_f_imag) + poke(c.io.b_t, test_b_t) + poke(c.io.b_f, test_b_f) + step(1) + val result_real = if (test_cond == 1) { + test_in_t_real + test_in_f_real + 1 + } else { + test_in_t_real - test_in_f_real + 1 + } + val result_imag = if (test_cond == 1) { + test_in_t_imag + test_in_f_imag + 1 + } else { + test_in_t_imag - test_in_f_imag + 1 + } + expect(c.io.out.real, result_real) + expect(c.io.out.imag, result_imag) + expect(c.io.b_o, if (test_cond == 1) test_b_t else 0) + } + } + } + + class ComplexTester(c: ComplexTest) extends Tester(c) with ComplexTests { + tests(c) + } + + val testArgs = chiselEnvironmentArguments() ++ Array("--compile", "--genHarness", "--test", "--targetDir", dir.getPath) + chiselMainTest(testArgs.toArray, () => Module(new ComplexTest(16))) { + c => new ComplexTester(c) + } + } +} diff --git a/src/test/scala/ConnectTest.scala b/src/test/scala/ConnectTest.scala index 1065e406..d16640c6 100644 --- a/src/test/scala/ConnectTest.scala +++ b/src/test/scala/ConnectTest.scala @@ -1,5 +1,5 @@ /* - Copyright (c) 2011, 2012, 2013, 2014 The Regents of the University of + Copyright (c) 2011 - 2016 The Regents of the University of California (Regents). All Rights Reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: @@ -50,7 +50,7 @@ class ConnectSuite extends TestSuite { class UsesShim extends Module { val io = new DecoupledUIntIO def makeShim(in: DecoupledIO[UInt]): DecoupledIO[UInt] = { - val out = Decoupled(UInt()) + val out = Wire(Decoupled(UInt())) out.bits := in.bits + UInt(1) out.valid := in.valid in.ready := out.ready @@ -75,7 +75,7 @@ class ConnectSuite extends TestSuite { step(1) expect(m.io.out.valid, int(true)) expect(m.io.in.ready, int(true)) - expect(m.io.out.bits, i+1) + expect(m.io.out.bits, i + 1) } } launchCppTester((m: UsesShimParent) => new ShimConnectionsTests(m)) @@ -230,7 +230,7 @@ class ConnectSuite extends TestSuite { val wdata = UInt(INPUT, 4) val status = new RegStatus().asOutput } - val reg_status = Reg(new RegStatus) + val reg_status = Reg(new RegStatus, init = new RegStatus().fromBits(UInt(0))) when (io.wen) { reg_status := new RegStatus().fromBits(io.wdata) } @@ -279,13 +279,13 @@ class ConnectSuite extends TestSuite { } catch { case _ : Throwable => ; } - assertTrue(!ChiselError.ChiselErrors.isEmpty); + assertTrue(ChiselError.hasErrors); } @Test def testVecInput() { class VecInput extends Module { val io = new Bundle { - val in = Vec.fill(2){ UInt(INPUT, 8) } + val in = Vec(2, UInt(INPUT, 8) ) val out0 = UInt(OUTPUT, 8) val out1 = UInt(OUTPUT, 8) } @@ -308,7 +308,7 @@ class ConnectSuite extends TestSuite { val io = new Bundle { val in0 = UInt(INPUT, 8) val in1 = UInt(INPUT, 8) - val out = Vec.fill(2){ UInt(OUTPUT, 8) } + val out = Vec(2, UInt(OUTPUT, 8) ) } io.out(0) := io.in0 @@ -351,7 +351,7 @@ class ConnectSuite extends TestSuite { } catch { case _ : Throwable => ; } - assertTrue(!ChiselError.ChiselErrors.isEmpty); + assertTrue(ChiselError.hasErrors); } /** Test Unspecified Bundle Values. @@ -359,43 +359,43 @@ class ConnectSuite extends TestSuite { */ @Test def testUnspecifiedBundleValues () { println("\ntestUnspecifiedBundleValues ...") - + class myBundle extends Bundle { val a = Bool() val b = Bool() - override def clone = new myBundle().asInstanceOf[this.type] + override def cloneType = new myBundle().asInstanceOf[this.type] } - + class UnspecifiedBundleValues extends Module { - - val io = new Bundle + + val io = new Bundle { val in = new myBundle().asInput val something = Bool(INPUT) val out = Bool(OUTPUT) } - + def NullMyBundle(): myBundle = { val bun = new myBundle bun.a := Bool(false) bun } - + val my_reg = Reg(init= NullMyBundle) - + when (io.something) { my_reg := io.in - } - + } + io.out := my_reg.a || my_reg.b - - + + printf("Hello World!\n") - } - + } + chiselMain(Array[String]("--backend", "v", "--targetDir", dir.getPath.toString()), () => Module(new UnspecifiedBundleValues())) @@ -404,7 +404,7 @@ class ConnectSuite extends TestSuite { /* Signals only used as resets are trimmed (#346) * - * + * */ @Test def testUnconnectedResets() { class SubModule(reset: Bool) extends Module(null, reset) { @@ -413,24 +413,24 @@ class ConnectSuite extends TestSuite { val out = Bool(OUTPUT) } val io = new IO - + val r = Reg(init = Bool(true)) r := io.in io.out := r } - + class UnconnectedResets extends Module { class IO extends Bundle { val in = Bool(INPUT) val out = Bool(OUTPUT) } val io = new IO - - val regs = Vec.fill(3){ Reg(Bool()) } + + val regs = Reg(Vec(3, Bool())) regs(0) := reset for (i <- 1 until 3) regs(i) := regs(i-1) - + val sub = Module(new SubModule(regs(2))) sub.io.in := io.in io.out := sub.io.out /* | regs(2) */ @@ -439,7 +439,207 @@ class ConnectSuite extends TestSuite { chiselMain(Array[String]("--backend", "v", "--targetDir", dir.getPath.toString()), () => Module(new UnconnectedResets())) - + assertFile("ConnectSuite_UnconnectedResets_1.v") } + + // Should be able to use submodule inputs to drive own logic + @Test def testSubmoduleInputUse() { + class PassThrough extends Module { + val io = new Bundle { + val ptin = UInt(width=8).asInput + val ptout = UInt(width=8).asOutput + } + io.ptout := io.ptin + } + class SubmoduleInputUse extends Module { + val io = new Bundle { + val in = UInt(width=8).asInput + val out1 = UInt(width=8).asOutput + val out2a = UInt(width=8).asOutput + val out2b = UInt(width=8).asOutput + val out3 = UInt(width=8).asOutput + } + // The ordering of these vals is important + // as this order triggered an old (fixed) bug + val pt3 = Module(new PassThrough) + val pt2b = Module(new PassThrough) + val pt2a = Module(new PassThrough) + val pt1 = Module(new PassThrough) + + pt1.io.ptin := io.in + pt2a.io.ptin := pt1.io.ptout + pt2b.io.ptin := pt2a.io.ptin + pt3.io.ptin := io.out2b + + io.out3 := pt3.io.ptout + io.out2b := pt2b.io.ptout + io.out2a := pt2a.io.ptout + io.out1 := pt2a.io.ptin + } + + chiselMain(Array[String]("--backend", "v", + "--targetDir", dir.getPath.toString()), + () => Module(new SubmoduleInputUse())) + + assertFile("ConnectSuite_SubmoduleInputUse_1.v") + } + + // More extensive test that submodule bindings are connected to appropriate logic + @Test def testAddBindings() { + class CrossingBlock extends Module { + val io = new Bundle { + val i1 = UInt(width=8).asInput + val i2 = UInt(width=8).asInput + val o1 = UInt(width=8).asOutput + val o2 = UInt(width=8).asOutput + } + io.o2 := io.o1 + io.i2 + io.o1 := io.i1 + } + class BindingTestInternal extends Module { + val io = new Bundle { + val in1 = UInt(width=8).asInput + val in2 = UInt(width=8).asInput + val in3 = UInt(width=8).asInput + val in4 = UInt(width=8).asInput + val out1 = UInt(width=8).asOutput + val out2 = UInt(width=8).asOutput + val out3 = UInt(width=8).asOutput + val out4 = UInt(width=8).asOutput + val out5 = UInt(width=8).asOutput + val out6 = UInt(width=8).asOutput + val out7 = UInt(width=8).asOutput + val out8 = UInt(width=8).asOutput + val out9 = UInt(width=8).asOutput + } + val cb5 = Module(new CrossingBlock) + val cb4 = Module(new CrossingBlock) + val cb3 = Module(new CrossingBlock) + val cb2 = Module(new CrossingBlock) + val cb1 = Module(new CrossingBlock) + + cb1.io.i1 := io.in1 + cb1.io.i2 := io.in2 + io.out1 := cb1.io.o1 + io.out2 := cb1.io.i2 + + cb2.io.i1 := cb1.io.o2 + cb2.io.i2 := io.out1 + io.out3 := cb2.io.o1 + io.out4 := cb2.io.o2 + + cb3.io.i1 := cb1.io.i1 + UInt(1) + cb3.io.i2 := cb2.io.i1 + io.out5 := cb3.io.o1 + cb3.io.o2 + io.out4 + + cb4.io.i1 := io.in3 + cb4.io.i2 := cb4.io.i1 + io.out6 := cb4.io.o1 + io.out7 := cb4.io.o2 + + cb5.io.i1 := io.in4 + cb5.io.i2 := cb5.io.o1 + io.out8 := cb5.io.o2 + + io.out9 := io.out7 + } + + class BindingTest extends Module { + val io = new Bundle { + val in1 = UInt(width=8).asInput + val in2 = UInt(width=8).asInput + val in3 = UInt(width=8).asInput + val in4 = UInt(width=8).asInput + val out1 = UInt(width=8).asOutput + val out2 = UInt(width=8).asOutput + val out3 = UInt(width=8).asOutput + val out4 = UInt(width=8).asOutput + val out5 = UInt(width=8).asOutput + val out6 = UInt(width=8).asOutput + val out7 = UInt(width=8).asOutput + val out8 = UInt(width=8).asOutput + val out9 = UInt(width=8).asOutput + } + val myTest = Module(new BindingTestInternal) + myTest.io <> io + } + + chiselMain(Array[String]("--backend", "v", + "--targetDir", dir.getPath.toString()), + () => Module(new BindingTest())) + + assertFile("ConnectSuite_BindingTest_1.v") + } + + /* Unused top level IOs are preserved (#172) + * + * + */ + @Test def testUnconnectedIOs() { + println("\ntestUnconnectedIOs ...") + class SubModule(reset: Bool) extends Module(null, reset) { + class IO extends Bundle { + val in = Bool(INPUT) + val out = Bool(OUTPUT) + val ncIn = Bool(INPUT) + val ncOut = Bool(OUTPUT) + } + val io = new IO + + val r = Reg(init = Bool(true)) + r := io.in + io.out := r + } + + class UnconnectedIOs extends Module { + class IO extends Bundle { + val in = Bool(INPUT) + val out = Bool(OUTPUT) + val ncIn = Bool(INPUT) + val ncOut = Bool(OUTPUT) + } + val io = new IO + + val regs = Reg(Vec(3, Bool())) + regs(0) := reset + for (i <- 1 until 3) + regs(i) := regs(i-1) + + val sub = Module(new SubModule(regs(2))) + sub.io.in := io.in + io.out := sub.io.out /* | regs(2) */ + } + + chiselMain(Array[String]("--backend", "c", + "--targetDir", dir.getPath.toString()), + () => Module(new UnconnectedIOs())) + + assertFile("ConnectSuite_UnconnectedIOs_1.h") + } + + /* Missing default produces reasonable error message + * (and not a bare "java.lang.IllegalArgumentException: Flat hash tables cannot contain null elements." + * Issue #513 + */ + @Test def testNoDefaultIOs() { + println("\ntestNoDefaultIOs ...") + class NoDefaultIOs extends Module { + class IO extends Bundle { + val in = Bool(INPUT) + val out = Bool(OUTPUT) + } + val io = new IO + when(io.in) { + io.out := Bool(true) + } + } + + val testArgs = chiselEnvironmentArguments() ++ Array("--targetDir", dir.getPath.toString()) + intercept[IllegalStateException] { + // This should fail since io.out does not have a default value. + chiselMain(testArgs, () => Module(new NoDefaultIOs)) + } + assertTrue(ChiselError.hasErrors) + } } diff --git a/src/test/scala/ConnectTestWire.scala b/src/test/scala/ConnectTestWire.scala new file mode 100644 index 00000000..e40390b3 --- /dev/null +++ b/src/test/scala/ConnectTestWire.scala @@ -0,0 +1,367 @@ +/* + Copyright (c) 2011 - 2016 The Regents of the University of + California (Regents). All Rights Reserved. Redistribution and use in + source and binary forms, with or without modification, are permitted + provided that the following conditions are met: + + * Redistributions of source code must retain the above + copyright notice, this list of conditions and the following + two paragraphs of disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + two paragraphs of disclaimer in the documentation and/or other materials + provided with the distribution. + * Neither the name of the Regents nor the names of its contributors + may be used to endorse or promote products derived from this + software without specific prior written permission. + + IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, + SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, + ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF + REGENTS HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF + ANY, PROVIDED HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION + TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR + MODIFICATIONS. +*/ + +import scala.collection.mutable.ArrayBuffer +import org.junit.Assert._ +import org.junit.Test +import org.junit.Ignore + +import Chisel._ + +/** This testsuite checks interaction of component class + and runtime hierarchies. +*/ +/** The `CWTRegStatus` class is defined at the top level so we can clone it: + * automatically construct it without requiring parameters. + */ +class CWTRegStatus extends Bundle { + val im0 = UInt(width = 2) + val im1 = UInt(width = 2) +} + +// Generic wiring module used in following tests. +case class GenWiring[SB <: Bundle](val newStatusInstance: () => SB) extends Module { + val io = new Bundle { + val wen = Bool(INPUT) + val wdata = UInt(INPUT, 4) + val status = newStatusInstance().asOutput + } + val wire_status = Reg(newStatusInstance()) + when (io.wen) { + wire_status := newStatusInstance().fromBits(io.wdata) + } + io.status := wire_status + + // Since we're parameterized, we need a clone method. + def cloneType = { + new GenWiring[SB](newStatusInstance).asInstanceOf[this.type] + } +} + +class ConnectWireSuite extends TestSuite { + // Test out wiring to a shim made via a scala def + @Test def testWireShimConnections() { + class UsesShim extends Module { + val io = new DecoupledUIntIO + def makeShim(in: DecoupledIO[UInt]): DecoupledIO[UInt] = { + val out = Wire(Decoupled(UInt())) + out.bits := in.bits + UInt(1) + out.valid := in.valid + in.ready := out.ready + out + } + val s = makeShim(io.in) + io.out.bits := s.bits + io.out.valid := s.valid + s.ready := io.out.ready + } + class UsesShimParent extends Module { + val io = new DecoupledUIntIO + val us = Module(new UsesShim) + us.io.in <> io.in + io.out <> us.io.out + } + class ShimConnectionsTests(m: UsesShimParent) extends Tester(m) { + (0 until 4).map { i => + poke(m.io.in.bits, i) + poke(m.io.in.valid, int(true)) + poke(m.io.out.ready, int(true)) + step(1) + expect(m.io.out.valid, int(true)) + expect(m.io.in.ready, int(true)) + expect(m.io.out.bits, i + 1) + } + } + launchCppTester((m: UsesShimParent) => new ShimConnectionsTests(m)) + } + + /** Test failure using a Wire with no default in a when(). */ + @Ignore @Test def testWireHookNoDefaultSpecifiedForWire() { + try { + class WireHookNoDefaultSpecifiedForWire extends Module { + case class WireStatus() extends Bundle { + val im0 = Wire(UInt(width = 2)) + val im1 = Wire(UInt(width = 2)) + } + + val io = new Bundle { + val wen = Bool(INPUT) + val wdata = UInt(INPUT, 4) + val status = new WireStatus().asOutput + } + val subModule = new GenWiring[WireStatus](WireStatus) + io <> subModule.io + } + chiselMain(Array[String]("--backend", "c", "--compile", + "--targetDir", dir.getPath.toString()), + () => Module(new WireHookNoDefaultSpecifiedForWire())) + } catch { + case _ : Throwable => ; + } + assertTrue(ChiselError.hasErrors) + } + + /** Test failure for reassignment to Wire in a when(). */ + @Ignore @Test def testWireHookReassignmentToWire() { + try { + class WireHookReassignmentToWire extends Module { + case class WireStatus() extends Bundle { + val im0 = UInt(0, 2) + val im1 = UInt(1, 2) + } + + val io = new Bundle { + val wen = Bool(INPUT) + val wdata = UInt(INPUT, 4) + val status = new WireStatus().asOutput + } + val subModule = new GenWiring[WireStatus](WireStatus) + io <> subModule.io + } + chiselMain(Array[String]("--backend", "c", "--compile", + "--targetDir", dir.getPath.toString()), + () => Module(new WireHookReassignmentToWire())) + } catch { + case _ : Throwable => ; + } + assertTrue(ChiselError.hasErrors) + } + + @Test def testRegisterHook() { + try { + class RegHook extends Module { + val io = new Bundle { + val wen = Bool(INPUT) + val wdata = UInt(INPUT, 4) + val status = new CWTRegStatus().asOutput + } + val reg_status = Reg(new CWTRegStatus) + when (io.wen) { + reg_status := new CWTRegStatus().fromBits(io.wdata) + } + io.status := reg_status + } + + class RegisterHookTests(m: RegHook) extends Tester(m) { + List(1, 2, 4, 6, 8, 12, 15, 15).zip( + List(false, true, true, false, true, false, true, false)).zip( + List((0,0), (0,2), (1,0), (1,0), (2,0), (2,0), (3,3), (3,3))).map { + case ((in, en), (im0, im1)) => + poke(m.io.wdata, in) + poke(m.io.wen, int(en)) + step(1) + expect(m.io.status.im0, im0) + expect(m.io.status.im1, im1) + } + } + launchCppTester((m: RegHook) => new RegisterHookTests(m)) + } catch { + case e : Throwable => { + val cause = e.getCause() + println("exception: %s".format(cause)) + } + } + } + + /** Test hooking-up Wires. */ + @Ignore @Test def testWireHook() { + try { + + class WireHook extends Module { + val io = new Bundle { + val wen = Bool(INPUT) + val wdata = UInt(INPUT, 4) + val status = new CWTRegStatus().asOutput + } + val subModule = Module(new GenWiring[CWTRegStatus](() => new CWTRegStatus) ) + val subModuleIOWire = subModule.io + if (false) { + io <> subModule.io + } else if (true) { + io <> subModule.io + } else { + subModule.io.wen := io.wen.asOutput + subModule.io.wdata := io.wdata.asOutput + io.status := subModule.io.status.asInput + } + } + + + class WireHookTests(m: WireHook) extends Tester(m) { + List(1, 2, 4, 6, 8, 12, 15, 15).zip( + List(false, true, true, false, true, false, true, false)).zip( + List((0,0), (0,2), (1,0), (1,0), (2,0), (2,0), (3,3), (3,3))).map { + case ((in, en), (im0, im1)) => + poke(m.io.wdata, in) + poke(m.io.wen, int(en)) + step(1) + expect(m.io.status.im0, im0) + expect(m.io.status.im1, im1) + } + } + launchCppTester((m: WireHook) => new WireHookTests(m)) + } catch { + case e : Throwable => { + val cause = e.getCause() + fail("exception: %s".format(cause)) + } + } + } + + @Test def testWireVecInput() { + class VecInput extends Module { + val io = new Bundle { + val in = Vec(2, UInt(INPUT, 8) ) + val out0 = UInt(OUTPUT, 8) + val out1 = UInt(OUTPUT, 8) + } + io.out0 := io.in(0) + io.out1 := io.in(1) + } + + class VecInputTests(c: VecInput) extends Tester(c) { + poke(c.io.in, Array[BigInt](0, 1)) + step(1) + expect(c.io.out0, 0) + expect(c.io.out1, 1) + } + + launchCppTester((m: VecInput) => new VecInputTests(m)) + } + + @Test def testVecWireOutput() { + class VecOutput extends Module { + val io = new Bundle { + val in0 = UInt(INPUT, 8) + val in1 = UInt(INPUT, 8) + val out = Vec(2, UInt(OUTPUT, 8) ) + } + + io.out(0) := io.in0 + io.out(1) := io.in1 + } + + class VecOutputTests(c: VecOutput) extends Tester(c) { + poke(c.io.in0, 0) + poke(c.io.in1, 1) + step(1) + expect(c.io.out, Array[BigInt](0, 1)) + } + + launchCppTester((m: VecOutput) => new VecOutputTests(m)) + } + + // More extensive test that submodule bindings are connected to appropriate logic + @Test def testWireAddBindings() { + class CrossingBlock extends Module { + val io = new Bundle { + val i1 = UInt(width=8).asInput + val i2 = UInt(width=8).asInput + val o1 = UInt(width=8).asOutput + val o2 = UInt(width=8).asOutput + } + io.o2 := io.o1 + io.i2 + io.o1 := io.i1 + } + class BindingTestInternal extends Module { + val io = new Bundle { + val in1 = UInt(width=8).asInput + val in2 = UInt(width=8).asInput + val in3 = UInt(width=8).asInput + val in4 = UInt(width=8).asInput + val out1 = UInt(width=8).asOutput + val out2 = UInt(width=8).asOutput + val out3 = UInt(width=8).asOutput + val out4 = UInt(width=8).asOutput + val out5 = UInt(width=8).asOutput + val out6 = UInt(width=8).asOutput + val out7 = UInt(width=8).asOutput + val out8 = UInt(width=8).asOutput + val out9 = UInt(width=8).asOutput + } + val cb5 = Module(new CrossingBlock) + val cb4 = Module(new CrossingBlock) + val cb3 = Module(new CrossingBlock) + val cb2 = Module(new CrossingBlock) + val cb1 = Module(new CrossingBlock) + + cb1.io.i1 := io.in1 + cb1.io.i2 := io.in2 + io.out1 := cb1.io.o1 + io.out2 := cb1.io.i2 + + cb2.io.i1 := cb1.io.o2 + cb2.io.i2 := io.out1 + io.out3 := cb2.io.o1 + io.out4 := cb2.io.o2 + + cb3.io.i1 := cb1.io.i1 + UInt(1) + cb3.io.i2 := cb2.io.i1 + io.out5 := cb3.io.o1 + cb3.io.o2 + io.out4 + + cb4.io.i1 := io.in3 + cb4.io.i2 := cb4.io.i1 + io.out6 := cb4.io.o1 + io.out7 := cb4.io.o2 + + cb5.io.i1 := io.in4 + cb5.io.i2 := cb5.io.o1 + io.out8 := cb5.io.o2 + + io.out9 := io.out7 + } + + class BindingTest extends Module { + val io = new Bundle { + val in1 = UInt(width=8).asInput + val in2 = UInt(width=8).asInput + val in3 = UInt(width=8).asInput + val in4 = UInt(width=8).asInput + val out1 = UInt(width=8).asOutput + val out2 = UInt(width=8).asOutput + val out3 = UInt(width=8).asOutput + val out4 = UInt(width=8).asOutput + val out5 = UInt(width=8).asOutput + val out6 = UInt(width=8).asOutput + val out7 = UInt(width=8).asOutput + val out8 = UInt(width=8).asOutput + val out9 = UInt(width=8).asOutput + } + val myTest = Module(new BindingTestInternal) + myTest.io <> io + } + + chiselMain(Array[String]("--backend", "v", + "--targetDir", dir.getPath.toString()), + () => Module(new BindingTest())) + + assertFile("ConnectWireSuite_BindingTest_1.v") + } +} diff --git a/src/test/scala/DataTest.scala b/src/test/scala/DataTest.scala index 8bce8d9c..b873c939 100644 --- a/src/test/scala/DataTest.scala +++ b/src/test/scala/DataTest.scala @@ -1,5 +1,5 @@ /* - Copyright (c) 2011, 2012, 2013, 2014 The Regents of the University of + Copyright (c) 2011 - 2016 The Regents of the University of California (Regents). All Rights Reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: @@ -55,125 +55,185 @@ import Chisel._ class DataSuite extends TestSuite { @Test def testBoolFromValue() { - val tested = Bool(true); -// assertTrue( tested.isInstanceOf[Literal] ); - assertFalse( tested.named ); + class Dummy extends Module { + val io = UInt(INPUT, 0) + val tested = Bool(true); + // assertTrue( tested.isInstanceOf[Literal] ); + assertFalse( tested.named ); + } + val dummyInst = Module(new Dummy) } @Test def testBoolFromDir() { - val tested = Bool(dir = INPUT); - assertTrue( tested.dir == INPUT ); - assertFalse( tested.named ); + class Dummy extends Module { + val io = UInt(INPUT, 0) + val tested = Bool(dir = INPUT); + assertTrue( tested.dir == INPUT ); + assertFalse( tested.named ); + } + val dummyInst = Module(new Dummy) } @Test def testBoolFromDefault() { - val tested = Bool(); - assertTrue( tested.dir == null ) - assertFalse( tested.named ); + class Dummy extends Module { + val io = UInt(INPUT, 0) + val tested = Bool(); + assertTrue( tested.dir == NODIR ); + assertFalse( tested.named ); + } + val dummyInst = Module(new Dummy) } @Test def testSIntFromLit() { - val fixFromLit = SInt(42); + class Dummy extends Module { + val io = UInt(INPUT, 0) + val fixFromLit = SInt(42); - // assertTrue( fixFromLit.isInstanceOf[Literal] ); - assertFalse( fixFromLit.named ); + // assertTrue( fixFromLit.isInstanceOf[Literal] ); + assertFalse( fixFromLit.named ); + } + val dummyInst = Module(new Dummy) } @Test def testSIntFromLitWithWidth() { - val fixFromLitWithWidth = SInt(42, width = 16); - // assertTrue( fixFromLitWithWidth.isInstanceOf[Literal] ); - assertFalse( fixFromLitWithWidth.named ); - /* XXX width was -1 here for some reason */ - assertTrue( fixFromLitWithWidth.getWidth() == 16 ); + class Dummy extends Module { + val io = UInt(INPUT, 0) + val fixFromLitWithWidth = SInt(42, width = 16); + // assertTrue( fixFromLitWithWidth.isInstanceOf[Literal] ); + assertFalse( fixFromLitWithWidth.named ); + /* XXX width was -1 here for some reason */ + assertTrue( fixFromLitWithWidth.getWidth() == 16 ); + } + val dummyInst = Module(new Dummy) } @Test def testSIntFromWidthDir() { - val fixFromWidthDir = SInt(width = 8, dir = INPUT); - assertTrue( fixFromWidthDir.getWidth() == 8 ); - assertTrue( fixFromWidthDir.dir == INPUT ); - assertFalse( fixFromWidthDir.named ); + class Dummy extends Module { + val io = UInt(INPUT, 0) + val fixFromWidthDir = SInt(width = 8, dir = INPUT); + assertTrue( fixFromWidthDir.getWidth() == 8 ); + assertTrue( fixFromWidthDir.dir == INPUT ); + assertFalse( fixFromWidthDir.named ); + } + val dummyInst = Module(new Dummy) } // Testing the UInt factory methods @Test def testUIntVal() { - // apply(x: Int): UInt - val dat = UInt(5) - assertTrue( dat.getWidth() == 3 ); - // assertTrue( dat.isInstanceOf[Literal] ); - assertFalse( dat.named ); + class Dummy extends Module { + val io = UInt(INPUT, 0) + // apply(x: Int): UInt + val dat = UInt(5) + assertTrue( dat.getWidth() == 3 ); + // assertTrue( dat.isInstanceOf[Literal] ); + assertFalse( dat.named ); + } + val dummyInst = Module(new Dummy) } @Test def testUIntValWidth() { - // def apply(x: Int, width: Int): UInt - val dat = UInt(5, 4) - assertTrue( dat.getWidth() == 4 ) - // assertTrue( dat.isInstanceOf[Literal] ) - assertFalse( dat.named ); + class Dummy extends Module { + val io = UInt(INPUT, 0) + // def apply(x: Int, width: Int): UInt + val dat = UInt(5, 4) + assertTrue( dat.getWidth() == 4 ) + // assertTrue( dat.isInstanceOf[Literal] ) + assertFalse( dat.named ); + } + val dummyInst = Module(new Dummy) } /* XXX This test interfers with others declared in NameTest.scala @Test def testUIntString() { - // def apply(x: String): UInt - val dat = UInt("1010") - assertTrue( dat.width == -1 ); // XXX - assertTrue( dat.dir == OUTPUT ); - assertFalse( dat.isSigned ); - assertTrue( dat.assigned ); - assertFalse( dat.named ); + class Dummy extends Module { + val io = UInt(INPUT, 0) + // def apply(x: String): UInt + val dat = UInt("1010") + assertTrue( dat.width == -1 ); // XXX + assertTrue( dat.dir == OUTPUT ); + assertFalse( dat.isSigned ); + assertTrue( dat.assigned ); + assertFalse( dat.named ); + } + val dummyInst = Module(new Dummy) } */ @Test def testUIntStringWidth() { - // def apply(x: String, width: Int): UInt - val dat = UInt("101", 4) - assertTrue( dat.getWidth() == 4 ) - // assertTrue( dat.isInstanceOf[Literal] ) - assertFalse( dat.named ) + class Dummy extends Module { + val io = UInt(INPUT, 0) + // def apply(x: String, width: Int): UInt + val dat = UInt("101", 4) + assertTrue( dat.getWidth() == 4 ) + // assertTrue( dat.isInstanceOf[Literal] ) + assertFalse( dat.named ) + } + val dummyInst = Module(new Dummy) } @Test def testUIntStringBaseBinary() { - // def apply(x: String, base: Char): UInt - val dat = UInt("1010", 'b') - assertTrue( dat.getWidth() == 4 ) - // assertTrue( dat.isInstanceOf[Literal] ) - assertFalse( dat.named ) + class Dummy extends Module { + val io = UInt(INPUT, 0) + // def apply(x: String, base: Char): UInt + val dat = UInt("1010", 'b') + assertTrue( dat.getWidth() == 4 ) + // assertTrue( dat.isInstanceOf[Literal] ) + assertFalse( dat.named ) + } + val dummyInst = Module(new Dummy) } @Test def testUIntStringBaseOctal() { - // def apply(x: String, base: Char): UInt - val dat = UInt("644", 'o') - assertTrue( dat.getWidth() == 9 ); - // assertTrue( dat.isInstanceOf[Literal] ) - assertFalse( dat.named ); + class Dummy extends Module { + val io = UInt(INPUT, 0) + // def apply(x: String, base: Char): UInt + val dat = UInt("644", 'o') + assertTrue( dat.getWidth() == 9 ); + // assertTrue( dat.isInstanceOf[Literal] ) + assertFalse( dat.named ); + } + val dummyInst = Module(new Dummy) } /* XXX This test interfers with others declared in NameTest.scala @Test def testUIntStringBaseDec() { - // def apply(x: String, base: Char): UInt - val dat = UInt("199", 'd') - assertFalse( dat.width.isSet ); - assertTrue( dat.dir == OUTPUT ); - assertFalse( dat.isSigned ); - assertTrue( dat.assigned ); - assertFalse( dat.named ); + class Dummy extends Module { + val io = UInt(INPUT, 0) + // def apply(x: String, base: Char): UInt + val dat = UInt("199", 'd') + assertFalse( dat.width.isSet ); + assertTrue( dat.dir == OUTPUT ); + assertFalse( dat.isSigned ); + assertTrue( dat.assigned ); + assertFalse( dat.named ); + } + val dummyInst = Module(new Dummy) } */ @Test def testUIntStringBaseHex() { - // def apply(x: String, base: Char): UInt - val dat = UInt("abc", 'h') - assertTrue( dat.getWidth() == 12 ) - // assertTrue( dat.isInstanceOf[Literal] ) - assertFalse( dat.named ) + class Dummy extends Module { + val io = UInt(INPUT, 0) + // def apply(x: String, base: Char): UInt + val dat = UInt("abc", 'h') + assertTrue( dat.getWidth() == 12 ) + // assertTrue( dat.isInstanceOf[Literal] ) + assertFalse( dat.named ) + } + val dummyInst = Module(new Dummy) } @Test def testUIntDirWidth() { - // def apply(dir: IODirection = null, width: Int = -1): UInt - val dat = UInt(INPUT, 4) - assertTrue( dat.getWidth() == 4 ); - assertTrue( dat.dir == INPUT ); - assertFalse( dat.named ); + class Dummy extends Module { + val io = UInt(INPUT, 0) + // def apply(dir: IODirection = None, width: Int = -1): UInt + val dat = UInt(INPUT, 4) + assertTrue( dat.getWidth() == 4 ); + assertTrue( dat.dir == INPUT ); + assertFalse( dat.named ); + } + val dummyInst = Module(new Dummy) } /** The code used to bypass the width initialization resulting @@ -188,7 +248,7 @@ class DataSuite extends TestSuite { try { class BypassDataIO(num_bypass_ports:Int) extends Bundle() { val data = UInt(INPUT, width=num_bypass_ports) - val valid = Vec.fill(num_bypass_ports){ Bool() } + val valid = Vec(num_bypass_ports, Bool() ) // XXX Module.findRoots does not support Vec as a graph root. def get_num_ports: Int = num_bypass_ports } @@ -203,7 +263,7 @@ class DataSuite extends TestSuite { } catch { case _ : Throwable => ; } - assertTrue(!ChiselError.ChiselErrors.isEmpty); + assertTrue(ChiselError.hasErrors); } // tests assigning to non parent's outputs @@ -233,7 +293,7 @@ class DataSuite extends TestSuite { } catch { case _ : Throwable => ; } - assertTrue(!ChiselError.ChiselErrors.isEmpty); + assertTrue(ChiselError.hasErrors); } /** Test case derived from issue #1 reported on github. @@ -259,7 +319,7 @@ class DataSuite extends TestSuite { } catch { case _ : Throwable => ; } - assertTrue(!ChiselError.ChiselErrors.isEmpty); + assertTrue(ChiselError.hasErrors); } @@ -267,8 +327,8 @@ class DataSuite extends TestSuite { @Test def testVecWidth() { val io = new Bundle{ - val in = Vec.fill(4)(UInt(INPUT,4)) - val out = Vec.fill(4)(UInt(OUTPUT,4)) + val in = Vec(4, UInt(INPUT,4)) + val out = Vec(4, UInt(OUTPUT,4)) } assertTrue( io.in.getWidth() == 16 ) @@ -284,10 +344,10 @@ class DataSuite extends TestSuite { val num_entries = 2 val debug = new Bundle { - val entry = Vec.fill(num_entries) { new Bundle { + val entry = Vec(num_entries, new Bundle { val valid = Bool() val eflags = UInt() // THIS IS THE CULPRIT - }} + }) }.asOutput } } diff --git a/src/test/scala/DecoupledGCD.scala b/src/test/scala/DecoupledGCD.scala new file mode 100644 index 00000000..a0e72489 --- /dev/null +++ b/src/test/scala/DecoupledGCD.scala @@ -0,0 +1,187 @@ +/* + Copyright (c) 2011 - 2016 The Regents of the University of + California (Regents). All Rights Reserved. Redistribution and use in + source and binary forms, with or without modification, are permitted + provided that the following conditions are met: + + * Redistributions of source code must retain the above + copyright notice, this list of conditions and the following + two paragraphs of disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + two paragraphs of disclaimer in the documentation and/or other materials + provided with the distribution. + * Neither the name of the Regents nor the names of its contributors + may be used to endorse or promote products derived from this + software without specific prior written permission. + + IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, + SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, + ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF + REGENTS HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF + ANY, PROVIDED HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION + TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR + MODIFICATIONS. +*/ + +import Chisel._ +import Chisel.testers.TesterDriver +import Chisel.iotesters.{SteppedHWIOTester, OrderedDecoupledHWIOTester} +import org.junit.Assert._ +import org.junit.Test +import org.junit.Ignore +import TestHelpers._ + +object GCDCalculator { + def computeGcdResultsAndCycles(a: Int, b: Int, depth: Int = 1): (Int, Int) = { + if(b == 0) { + (a, depth) + } + else { + computeGcdResultsAndCycles(b, a%b, depth + 1 ) + } + } +} + +// Test the Chisel3 UnitTester interface. +class GCDDecoupledTest extends TestSuite { + + @Test def testGCDDecoupledTester() { + println("\ntestGCDDecoupledTester ...") + + class RealGCDInput extends Bundle { + val a = Bits(width = 16) + val b = Bits(width = 16) + override def cloneType = new RealGCDInput().asInstanceOf[this.type] + } + + class RealGCD extends Module { + val io = new Bundle { + val in = Decoupled(new RealGCDInput()).flip() + val out = Decoupled(UInt(width = 16)) + } + + val x = Reg(UInt()) + val y = Reg(UInt()) + val p = Reg(init=Bool(false)) + + val ti = Reg(init=UInt(0, width = 16)) + ti := ti + UInt(1) + + io.in.ready := !p + + when (io.in.valid && !p) { + x := io.in.bits.a + y := io.in.bits.b + p := Bool(true) + } + + when (p) { + when (x > y) { x := y; y := x } + .otherwise { y := y - x } + } + +// printf("RealGCD: ti %d x %d y %d in_ready %d in_valid %d out %d out_ready %d out_valid %d==============\n", +// ti, x, y, io.in.ready, io.in.valid, io.out.bits, io.out.ready, io.out.valid) + + io.out.bits := x + io.out.valid := y === Bits(0) && p + when (io.out.valid) { + p := Bool(false) + } + } + + class RealGCDTests extends SteppedHWIOTester { + val device_under_test = Module( new RealGCD ) + val c = device_under_test + + val inputs = List( (48, 32), (7, 3), (100, 10) ) + val outputs = List( 16, 1, 10) + + for( (input_1, input_2) <- inputs) { + val (output, cycles) = GCDCalculator.computeGcdResultsAndCycles(input_1, input_2) + + poke(c.io.in.bits.a, input_1) + poke(c.io.in.bits.b, input_2) + poke(c.io.in.valid, 1) + + step(1) + expect(c.io.in.ready, 1) + poke(c.io.in.valid, 0) + step(1) + + step(cycles-2) + expect(c.io.out.bits, output) + } + } + + class DecoupledRealGCDTestHandCodedExample extends OrderedDecoupledHWIOTester { + val device_under_test = Module(new RealGCD()) + val c = device_under_test + + val a_values = Vec(Array(UInt(12, width = 16), UInt(33, width = 16))) + val b_values = Vec(Array(UInt(24, width = 16), UInt(24, width = 16))) + + val ti = Reg(init=UInt(0, width = 16)) + val pc = Reg(init=UInt(0, width = 16)) + val oc = Reg(init=UInt(0, width = 16)) + + val in_done = Reg(init=Bool(false)) + val out_done = Reg(init=Bool(false)) + + ti := ti + UInt(1) + when(ti >= UInt(40)) { stop() } + when(in_done && out_done) { stop() } + + //printf("ti %d pc %d oc %d in_ready %d out_valid %d==============", + // ti, pc, oc, c.io.in.ready, c.io.out.valid) + when(!in_done && c.io.in.ready) { + // printf(s"pc %d a %d b %d", pc, a_values(pc), b_values(pc)) + c.io.in.bits.a := a_values(pc) + c.io.in.bits.b := b_values(pc) + c.io.in.valid := Bool(true) + pc := pc + UInt(1) + when(pc >= UInt(a_values.length)) { + in_done := Bool(true) + } + } + + val c_values = Vec(Array(UInt(12, width = 16), UInt(3, width = 16))) + c.io.out.ready := Bool(true) + + when(!out_done && c.io.out.valid) { + printf("oc %d got %d expected %d", oc, c.io.out.bits, c_values(oc)) + assert(c.io.out.bits === c_values(oc), "got != expected") + c.io.out.ready := Bool(true) + oc := oc + UInt(1) + when(oc >= UInt(c_values.length)) { + out_done := Bool(true) + } + } + // finish() + // io_info.show_ports("".r) + } + + class DecoupledRealGCDTests4 extends OrderedDecoupledHWIOTester { + val device_under_test = Module(new RealGCD()) + val c = device_under_test + + for { + i <- Array(12, 33) + j <- Array(24, 24) + } { + val (gcd_value, cycles) = GCDCalculator.computeGcdResultsAndCycles(i, j) + + inputEvent(c.io.in.bits.a -> i, c.io.in.bits.b -> j) + outputEvent(c.io.out.bits -> gcd_value) + } + } + + implicit val args = Array[String]("--backend", "c", "--compile", "--genHarness", "--test", "--targetDir", TestHelpers.dir.getPath.toString()) + TesterDriver.execute { () => new DecoupledRealGCDTests4 } + } +} diff --git a/src/test/scala/DelayBetween.scala b/src/test/scala/DelayBetween.scala new file mode 100644 index 00000000..ae688f50 --- /dev/null +++ b/src/test/scala/DelayBetween.scala @@ -0,0 +1,192 @@ +/* + Copyright (c) 2011 - 2016 The Regents of the University of + Sydney. All Rights Reserved. Redistribution and use in + source and binary forms, with or without modification, are permitted + provided that the following conditions are met: + + * Redistributions of source code must retain the above + copyright notice, this list of conditions and the following + two paragraphs of disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + two paragraphs of disclaimer in the documentation and/or other materials + provided with the distribution. + * Neither the name of the Regents nor the names of its contributors + may be used to endorse or promote products derived from this + software without specific prior written permission. + + IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, + SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, + ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF + REGENTS HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF + ANY, PROVIDED HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION + TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR + MODIFICATIONS. +*/ + +import scala.collection.mutable.ArrayBuffer +import scala.collection.mutable.ListBuffer +import scala.util.Random +import org.junit.Assert._ +import org.junit.Test +import org.junit.Ignore + +import Chisel._ + +/** This test suite tests measurement of Delays with DelayBetween + */ +class DelayBetweenSuite extends TestSuite { + + @Test def testZero() { + class ZeroDelay extends Module { + val io = new Bundle { + val in = UInt(INPUT, 4) + val out = UInt(OUTPUT, 4) + } + io.out := io.in + } + val myInst = Module(new ZeroDelay) + + val delayDepth = DelayBetween(myInst.io.in, myInst.io.out) + assertTrue("Should only find exactly one path", delayDepth.length == 1) + assertTrue("Delay should be 0", delayDepth(0) == 0) + + val delayShort = DelayBetween.findShortest(myInst.io.in, myInst.io.out) + assertTrue("Shortest Delay should be 0", delayShort == 0) + } + + @Test def testOne() { + class OneDelay extends Module { + val io = new Bundle { + val in = UInt(INPUT, 4) + val out = UInt(OUTPUT, 4) + } + io.out := RegNext(io.in) + } + val myInst = Module(new OneDelay) + + val delayDepth = DelayBetween(myInst.io.in, myInst.io.out) + assertTrue("Should only find exactly one path", delayDepth.length == 1) + assertTrue("Delay should be 1", delayDepth(0) == 1) + + val delayBreadth = DelayBetween(myInst.io.in, myInst.io.out, true) + assertTrue("Should only find exactly one path", delayBreadth.length == 1) + assertTrue("Delay should be 1", delayBreadth(0) == 1) + + val delayShort = DelayBetween.findShortest(myInst.io.in, myInst.io.out) + assertTrue("Shortest Delay should be 1", delayShort == 1) + } + + @Test def testInf() { + class InfDelay extends Module { + val io = new Bundle { + val in = UInt(INPUT, 4) + val out = UInt(OUTPUT, 4) + } + io.out := UInt(0, 4) + } + val myInst = Module(new InfDelay) + + val delayDepth = DelayBetween(myInst.io.in, myInst.io.out) + assertTrue("Should only find no paths", delayDepth.length == 0) + + val delayBreadth = DelayBetween(myInst.io.in, myInst.io.out, true) + assertTrue("Should only find no paths", delayBreadth.length == 0) + + val delayShort = DelayBetween.findShortest(myInst.io.in, myInst.io.out) + assertTrue("No Path: Shortest Delay should be -1", delayShort == -1) + } + + @Test def testMultiple() { + class MultDelay extends Module { + val io = new Bundle { + val in = UInt(INPUT, 4) + val en = Bool(INPUT) + val out = UInt(OUTPUT, 4) + } + val reg1 = RegNext(io.in) + io.out := Mux(io.en, reg1, io.in) + } + val myInst = Module(new MultDelay) + + val delayDepth = DelayBetween(myInst.io.in, myInst.io.out) + assertTrue("Should only find exactly two paths", delayDepth.length == 2) + assertTrue("Delay should contain 0 and 1", delayDepth.contains(0) && delayDepth.contains(1) ) + + val delayBreadth = DelayBetween(myInst.io.in, myInst.io.out, true) + assertTrue("Should only find exactly two paths", delayBreadth.length == 2) + assertTrue("Delay should contain 0 and 1", delayBreadth.contains(0) && delayBreadth.contains(1)) + + val delayShort = DelayBetween.findShortest(myInst.io.in, myInst.io.out) + assertTrue("Shortest Delay should be 0", delayShort == 0) + } + + @Test def testBundle() { + class BundleDelay extends Module { + val io = new Bundle { + val in = UInt(INPUT, 4) + val en = Bool(INPUT) + val out = UInt(OUTPUT, 4) + } + val RegMod = Module(new RegModule()).io + RegMod.in := Reg(next=io.in) + io.out := RegMod.out + } + + class RegModule extends Module { + val io = new Bundle { + val in = UInt(INPUT, 4) + val out = UInt(OUTPUT, 4) + } + io.out := Reg(next=io.in) + } + + val myInst = Module(new BundleDelay) + + val delayDepth = DelayBetween(myInst.io.in, myInst.io.out) + assertTrue("Should only find exactly one path", delayDepth.length == 1) + assertTrue("Delay should contain 2 ", delayDepth.contains(2)) + + val delayBreadth = DelayBetween(myInst.io.in, myInst.io.out, true) + assertTrue("Should only find exactly one paths", delayBreadth.length == 1) + assertTrue("Delay should contain 2", delayBreadth.contains(2)) + + val delayShort = DelayBetween.findShortest(myInst.io.in, myInst.io.out) + assertTrue("Shortest Delay should be 2", delayShort == 2) + } + + @Test def testRegLoop() { + /** This test has a Delay loop in it + * The Loop should find that it is back at the same node and terminate + */ + class RegLoopDelay extends Module { + val io = new Bundle { + val in = UInt(INPUT, 4) + val en = Bool(INPUT) + val out = UInt(OUTPUT, 4) + } + val reg1 = RegNext(io.in) + val reg2 = RegNext(reg1) + val reg3 = RegNext(Mux(io.en, reg1, reg2)) + reg2 := reg3 // override for a logical loop + io.out := reg3 + } + val myInst = Module(new RegLoopDelay) + + val delayDepth = DelayBetween(myInst.io.in, myInst.io.out) + assertTrue("Should only find exactly one path", delayDepth.length == 1) + assertTrue("Delay should contain 2", delayDepth.contains(2) ) + + val delayBreadth = DelayBetween(myInst.io.in, myInst.io.out, true) + assertTrue("Should only find exactly one path", delayBreadth.length == 1) + assertTrue("Delay should contain 2", delayBreadth.contains(2)) + + val delayShort = DelayBetween.findShortest(myInst.io.in, myInst.io.out) + assertTrue("Shortest Delay should be 2", delayShort == 2) + } + +} diff --git a/src/test/scala/DelayTest.scala b/src/test/scala/DelayTest.scala index 82006887..5a483568 100644 --- a/src/test/scala/DelayTest.scala +++ b/src/test/scala/DelayTest.scala @@ -1,5 +1,5 @@ /* - Copyright (c) 2011, 2012, 2013, 2014 The Regents of the University of + Copyright (c) 2011 - 2016 The Regents of the University of California (Regents). All Rights Reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: @@ -108,7 +108,7 @@ class DelaySuite extends TestSuite { val addr = UInt(INPUT, width=32) val out = UInt(OUTPUT) } - val mem= Mem(UInt(width=32), 8) + val mem= Mem(8, UInt(width=32)) io.out := mem(io.addr) } chiselMain(Array[String]("--v", "--inlineMem", @@ -125,7 +125,7 @@ class DelaySuite extends TestSuite { val addr = UInt(INPUT, width=32) val out = UInt(OUTPUT) } - val mem = Mem(UInt(width=32), 8) + val mem = Mem(8, UInt(width=32)) mem(io.addr) := mem(io.addr) + UInt(1) io.out := mem(io.addr) } @@ -144,7 +144,7 @@ class DelaySuite extends TestSuite { val addr = UInt(INPUT, width=32) val out = UInt(OUTPUT) } - val mem= Mem(UInt(width=32), 8) + val mem= Mem(8, UInt(width=32)) when( io.enable ) { mem(io.addr) := mem(io.addr) + UInt(1) } @@ -167,7 +167,7 @@ class DelaySuite extends TestSuite { val addr = UInt(INPUT, width=32) val out = UInt(OUTPUT) } - val mem= Mem(UInt(width=32), 8) + val mem= Mem(8, UInt(width=32)) when( io.enable ) { mem.write(io.addr, mem(io.addr), UInt(0xff00)) } @@ -186,7 +186,7 @@ class DelaySuite extends TestSuite { val b = UInt(width = 16) } val a_b = UInt(width = 32) // this tests name mangling - override def clone = new A().asInstanceOf[this.type] + override def cloneType = new A().asInstanceOf[this.type] } class SeqReadBundle extends Module { val io = new Bundle { @@ -194,10 +194,10 @@ class DelaySuite extends TestSuite { val raddr = UInt(INPUT, width = 4) val wen = Bool(INPUT) val waddr = UInt(INPUT, width = 4) - val in = Vec.fill(2)(new A()).asInput - val out = Vec.fill(2)(new A()).asOutput + val in = Vec(2, new A()).asInput + val out = Vec(2, new A()).asOutput } - val mem = Mem(io.in.clone, 16, seqRead = true) + val mem = Mem(io.in.cloneType, 16, seqRead = true) when (io.wen) { mem(io.waddr) := io.in } io.out := mem(RegEnable(io.raddr, io.ren)) } diff --git a/src/test/scala/DotBackendTest.scala b/src/test/scala/DotBackendTest.scala index 20b92b41..d37124ea 100644 --- a/src/test/scala/DotBackendTest.scala +++ b/src/test/scala/DotBackendTest.scala @@ -1,5 +1,5 @@ /* - Copyright (c) 2011, 2012, 2013, 2014 The Regents of the University of + Copyright (c) 2011 - 2016 The Regents of the University of California (Regents). All Rights Reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: diff --git a/src/test/scala/DoubleSuite.scala b/src/test/scala/DoubleSuite.scala new file mode 100644 index 00000000..c0efc0c4 --- /dev/null +++ b/src/test/scala/DoubleSuite.scala @@ -0,0 +1,78 @@ +/* + Copyright (c) 2011 - 2016 The Regents of the University of + California (Regents). All Rights Reserved. Redistribution and use in + source and binary forms, with or without modification, are permitted + provided that the following conditions are met: + + * Redistributions of source code must retain the above + copyright notice, this list of conditions and the following + two paragraphs of disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + two paragraphs of disclaimer in the documentation and/or other materials + provided with the distribution. + * Neither the name of the Regents nor the names of its contributors + may be used to endorse or promote products derived from this + software without specific prior written permission. + + IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, + SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, + ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF + REGENTS HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF + ANY, PROVIDED HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION + TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR + MODIFICATIONS. +*/ + +import org.junit.Test + +import Chisel._ + +class DoubleSuite extends TestSuite { + @Test def testCompareDbl() { + println("\ntestCompareDbl...") + class CompareDblModule extends Module { + class IO extends Bundle { + val in1 = Dbl(INPUT) + val in2 = Dbl(INPUT) + val outLT = Bool(OUTPUT) + val outLE = Bool(OUTPUT) + val outGT = Bool(OUTPUT) + val outGE = Bool(OUTPUT) + } + val io = new IO() + val dbl1 = io.in1 + val dbl2 = io.in2 + io.outLT := dbl1 < dbl2 + io.outLE := dbl1 <= dbl2 + io.outGT := dbl1 > dbl2 + io.outGE := dbl1 >= dbl2 + } + + trait CompareDblModuleTests extends Tests { + def tests(m: CompareDblModule) { + for (i <- 0 to 100) { + val dbl1 = rnd.nextDouble + val dbl2 = rnd.nextDouble + + poke(m.io.in1, dbl1) + poke(m.io.in2, dbl2) + expect(m.io.outLT, if (dbl1 < dbl2) 1 else 0) + expect(m.io.outLE, if (dbl1 <= dbl2) 1 else 0) + expect(m.io.outGT, if (dbl1 > dbl2) 1 else 0) + expect(m.io.outGE, if (dbl1 >= dbl2) 1 else 0) + } + } + } + + class CompareDblModuleTester(m: CompareDblModule) extends Tester(m) with CompareDblModuleTests { + tests(m) + } + + launchCppTester((m: CompareDblModule) => new CompareDblModuleTester(m)) + } +} diff --git a/src/test/scala/ExtractSuite.scala b/src/test/scala/ExtractSuite.scala new file mode 100644 index 00000000..25ca10b1 --- /dev/null +++ b/src/test/scala/ExtractSuite.scala @@ -0,0 +1,495 @@ +/* + Copyright (c) 2011 - 2016 The Regents of the University of + California (Regents). All Rights Reserved. Redistribution and use in + source and binary forms, with or without modification, are permitted + provided that the following conditions are met: + + * Redistributions of source code must retain the above + copyright notice, this list of conditions and the following + two paragraphs of disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + two paragraphs of disclaimer in the documentation and/or other materials + provided with the distribution. + * Neither the name of the Regents nor the names of its contributors + may be used to endorse or promote products derived from this + software without specific prior written permission. + + IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, + SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, + ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF + REGENTS HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF + ANY, PROVIDED HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION + TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR + MODIFICATIONS. +*/ + +import scala.util.Random +import org.scalatest.Args +import org.scalatest.tagobjects.Slow + +import Chisel._ + +// We use the ScalaTest Suite non-JUint classes in order to be able to tag the more extensive tests as Slow. +// Trying to tag them with the @Slow annotation does not seem to work. +class ExtractSuite extends FunTestSuite { + val maxWidth = 1024 + var testMultiplier = 4 + var runMultiplier = 4 + lazy val testCount = 1 * testMultiplier + lazy val runCount = 1 * runMultiplier + + // Provide a run method so we can access the arguments (specifically the filter) + // used when running the tests. + override def run(testName: Option[String], args: Args): org.scalatest.Status = { + // If we're excluding Slow tests, reduce the test and run multipliers. + if (args.filter.tagsToExclude.contains("org.scalatest.tags.Slow")) { + testMultiplier = 1 + runMultiplier = 1 + } + super.run(testName, args) + } + + // Generate a list of test widths from 1 to maxWidth. + // If we're generating enough values, use variations (-1, 0, +1) on the special powers of 2 for the 2nd through 4th elements. + def genMaxWidths(rnd: Random, maxWidth: Int, nTests: Int): List[Int] = { + val specialPow2 = rnd.shuffle(List(8, 16, 32, 64, 128, 256)).head + // Pick a random power of 2 from 4 to maxWidth - 1 + val range = 4 to maxWidth + for { + t <- List.range(0, nTests) + pow2 = t match { + case 1 if (nTests > 2) => specialPow2 - 1 + case 2 => specialPow2 + case 3 => specialPow2 + 1 + case _ => range(rnd.nextInt(range.length)) + } + inputWidth = pow2 + } + yield inputWidth + } + + // Generate a list of hi, lo specs where hi >= lo and (hi - lo + 1) <= inputWidth. + // The second element in the list will have hi == lo, and the third will have lo = 0, hi = inputWidth - 1 + // All other elements (including the first) will have random values. + def genHiLo(rnd: Random, inputWidth: Int, nTests: Int): List[(Int, Int)] = { + for { + t <- List.range(0, nTests) + extractWidth = t match { + case 1 => 1 + case 2 => inputWidth + case _ => rnd.nextInt(inputWidth - 1) + 1 // first and remaining cases. + } + lo = t match { + case 2 => 0 + case _ => rnd.nextInt(inputWidth - extractWidth) + } + hi = lo + extractWidth - 1 + } + yield (hi, lo) + } + + // Generate a list of widths where 1 < width <= inputWidth, ensuring widths of 1 and inputWidth are in the list, + // (assuming the list is long enough). + def genExtractWidths(rnd: Random, inputWidth: Int, nTests: Int): List[Int] = { + var l1 = false + var lmax = false + val l1Test = nTests - 1 + val lmaxTest = nTests - 2 + val result = for { + t <- List.range(0, nTests) + extractWidth = { + val ni = t match { + case `l1Test` if (!l1 && nTests > l1Test + 1) => 1 + case `lmaxTest` if (!lmax && nTests > lmaxTest + 2) => inputWidth + case _ => rnd.nextInt(inputWidth) + 1 + } + ni match { + case 1 => l1 = true + case `inputWidth` => lmax = true + case _ => + } + ni + } + } + yield extractWidth + + result + } + + /** Bad Width Inference in Extract #621 + * + */ + test("extractWidthInfer") { + println("\nextractWidthInfer ...") + class ExtractWidthInfer extends Module { + val io = new Bundle { + val in = UInt(INPUT, width = 64) + val data = UInt(OUTPUT) + } + val offset = Reg(UInt(width = 32)) + io.data := io.in(UInt(63) - offset, UInt(0)) + } + + class TestExtractWidthInfer(m: ExtractWidthInfer) extends Tester(m) { + List(0, 16, 4, 7, 12, 64).map { i => + val data = BigInt(i) + poke(m.io.in, data) + step(1) + expect(m.io.data, data & 0xffffffff) + } + } + + for (backend <- Array("c", "v")) { + if (backend == "v" && !Driver.isVCSAvailable) { + println("vcs unavailable - skipping Verilog test") + } else { + chiselMainTest(chiselEnvironmentArguments() ++ Array[String]("--backend", backend, "--compile", "--genHarness", "--test", "--targetDir", dir.getPath.toString()), + () => Module(new ExtractWidthInfer)) { + c => new TestExtractWidthInfer(c) + } + } + } + } + + // Test static hi, lo. + test("extractStatic") { + println("\nextractStatic ...") + class ExtractStatic(w: Int, hi: Int, lo: Int) extends Module { + val io = new Bundle { + val in = UInt(INPUT, width = w) + val data = UInt(OUTPUT) + } + io.data := io.in(UInt(hi), UInt(lo)) + } + + class TestExtractStaticWidthHiLo(m: ExtractStatic, maxWidth: Int, hi: Int, lo: Int, nRuns: Int) extends Tester(m) { + val mask = (BigInt(1) << (hi - lo + 1)) - 1 + println("width: %d, hi: %d, lo: %d".format(maxWidth, hi, lo)) + for (r <- 1 to nRuns) { + val data = BigInt(maxWidth, rnd) + + poke(m.io.in, data) + step(1) + expect(m.io.data, (data >> lo) & mask) + } + } + + class TestExtractStatic(rnd: Random, maxWidth: Int, nTests: Int, nRuns: Int) { + + // Pick a random power of 2 from 4 to maxWidth + for (inputWidth <- genMaxWidths(rnd, maxWidth, nTests)) { + for ((hi, lo) <- genHiLo(rnd, inputWidth, nRuns)) { + for (tester <- Array("c", "v")) { + if (tester == "v" && !Driver.isVCSAvailable) { + println("vcs unavailable - skipping Verilog test") + } else { + chiselMainTest(chiselEnvironmentArguments() ++ Array[String]("--backend", tester, "--compile", "--genHarness", "--test", "--targetDir", dir.getPath.toString()), + () => Module(new ExtractStatic(inputWidth, hi, lo))) { + c => new TestExtractStaticWidthHiLo(c, inputWidth, hi, lo, nRuns) + } + } + } + } + } + } + + val t = new TestExtractStatic(new Random(Driver.testerSeed), maxWidth, testCount, runCount) + } + + // Test dynamic hi, lo. + test("extractDynamic", Slow) { + println("\nextractDynamic ...") + class ExtractDynamic(w: Int) extends Module { + val io = new Bundle { + val in = UInt(INPUT, width = w) + val data = UInt(OUTPUT) + val hi = UInt(INPUT, width = 16) + val lo = UInt(INPUT, width = 16) + } + io.data := UInt(0) + + // Protect against bad random startup values. + val hi = UInt(INPUT, 16) + val lo = UInt(INPUT, 16) + hi := UInt(0, 16) + lo := UInt(0, 16) + when(io.hi >= io.lo && io.hi < UInt(w)) { + hi := io.hi + lo := io.lo + } + io.data := io.in(hi, lo) + } + + class TestExtractDynamicHiLo(m: ExtractDynamic, maxWidth: Int, nRuns: Int) extends Tester(m) { + for ((hi, lo) <- genHiLo(rnd, maxWidth, nRuns)) { + val data = BigInt(maxWidth, rnd) + val mask = (BigInt(1) << (hi - lo + 1)) - 1 + println("width: %d, hi: %d, lo: %d, mask: 0x%x".format(maxWidth, hi, lo, mask)) + poke(m.io.in, data) + poke(m.io.hi, hi) + poke(m.io.lo, lo) + step(1) + expect(m.io.data, (data >> lo) & mask) + } + } + + + class TestExtractDynamic(rnd: Random, maxWidth: Int, nTests: Int, nRuns: Int) { + + // Pick a random power of 2 from 4 to maxWidth + for (inputWidth <- genMaxWidths(rnd, maxWidth, nTests)) { + for (tester <- Array("c", "v")) { + if (tester == "v" && !Driver.isVCSAvailable) { + println("vcs unavailable - skipping Verilog test") + } else { + chiselMainTest(chiselEnvironmentArguments() ++ Array[String]("--backend", tester, "--compile", "--genHarness", "--test", "--targetDir", dir.getPath.toString()), + () => Module(new ExtractDynamic(inputWidth))) { + c => new TestExtractDynamicHiLo(c, inputWidth, nRuns) + } + } + } + } + } + + val t = new TestExtractDynamic(new Random(Driver.testerSeed), maxWidth, testCount, runCount) + } + + // Test dynamic hi, static lo. + test("extractDynamicHi", Slow) { + println("\nextractDynamicHi ...") + class ExtractDynamic(w: Int, lo: Int) extends Module { + val io = new Bundle { + val in = UInt(INPUT, width = w) + val data = UInt(OUTPUT) + val hi = UInt(INPUT, width = 16) + } + io.data := UInt(0) + + // Protect against bad random startup values. + val hi = UInt(INPUT, 16) + hi := UInt(lo) + when(io.hi >= UInt(lo) && io.hi < UInt(w)) { + hi := io.hi + } + io.data := io.in(hi, UInt(lo)) + } + + class TestExtractDynamicHi(m: ExtractDynamic, maxWidth: Int, nRuns: Int, lo: Int) extends Tester(m) { + for (width <- genExtractWidths(rnd, maxWidth - lo, nRuns)) { + val hi = lo + width - 1 + val data = BigInt(maxWidth, rnd) + val mask = (BigInt(1) << width) - 1 + println("width: %d, hi: %d, lo: %d, mask: 0x%x".format(maxWidth, hi, lo, mask)) + poke(m.io.in, data) + poke(m.io.hi, hi) + step(1) + expect(m.io.data, (data >> lo) & mask) + } + } + + class TestExtractDynamic(rnd: Random, maxWidth: Int, nTests: Int, nRuns: Int) { + + // Pick a random power of 2 from 4 to maxWidth + for (inputWidth <- genMaxWidths(rnd, maxWidth, nTests)) { + for (width <- genExtractWidths(rnd, inputWidth, nRuns)) { + val lo = inputWidth - width + for (tester <- Array("c", "v")) { + if (tester == "v" && !Driver.isVCSAvailable) { + println("vcs unavailable - skipping Verilog test") + } else { + chiselMainTest(chiselEnvironmentArguments() ++ Array[String]("--backend", tester, "--compile", "--genHarness", "--test", "--targetDir", dir.getPath.toString()), + () => Module(new ExtractDynamic(inputWidth, lo))) { + c => new TestExtractDynamicHi(c, inputWidth, nRuns, lo) + } + } + } + } + } + } + + val t = new TestExtractDynamic(new Random(Driver.testerSeed), maxWidth, testCount, runCount) + } + + // Test static hi, dynmic lo. + test("extractDynamicLo", Slow) { + println("\nextractDynamicLo ...") + class ExtractDynamic(w: Int, hi: Int) extends Module { + val io = new Bundle { + val in = UInt(INPUT, width = w) + val data = UInt(OUTPUT) + val lo = UInt(INPUT, width = 16) + } + io.data := UInt(0) + + // Protect against bad random startup values. + val lo = UInt(INPUT, 16) + lo := UInt(0, 16) + when(UInt(hi) >= io.lo) { + lo := io.lo + } + io.data := io.in(UInt(hi), lo) + } + + class TestExtractDynamicLo(m: ExtractDynamic, maxWidth: Int, nRuns: Int, hi: Int) extends Tester(m) { + for (width <- genExtractWidths(rnd, hi + 1, nRuns)) { + val lo = hi - width + 1 + val data = BigInt(maxWidth, rnd) + val mask = (BigInt(1) << width) - 1 + println("width: %d, hi: %d, lo: %d, mask: 0x%x".format(maxWidth, hi, lo, mask)) + poke(m.io.in, data) + poke(m.io.lo, lo) + step(1) + expect(m.io.data, (data >> lo) & mask) + } + } + + + class TestExtractDynamic(rnd: Random, maxWidth: Int, nTests: Int, nRuns: Int) { + + // Pick a random power of 2 from 4 to maxWidth + for (inputWidth <- genMaxWidths(rnd, maxWidth, nTests)) { + for (width <- genExtractWidths(rnd, inputWidth, nRuns)) { + val hi = width - 1 + for (tester <- Array("c", "v")) { + if (tester == "v" && !Driver.isVCSAvailable) { + println("vcs unavailable - skipping Verilog test") + } else { + chiselMainTest(chiselEnvironmentArguments() ++ Array[String]("--backend", tester, "--compile", "--genHarness", "--test", "--targetDir", dir.getPath.toString()), + () => Module(new ExtractDynamic(inputWidth, hi))) { + c => new TestExtractDynamicLo(c, inputWidth, nRuns, hi) + } + } + } + } + } + } + + val t = new TestExtractDynamic(new Random(Driver.testerSeed), maxWidth, testCount, runCount) + } + + // Test dynamic onebit (hi == lo). + test("extractDynamicOneBit") { + println("\nextractDynamicOneBit ...") + class ExtractDynamic(w: Int) extends Module { + val io = new Bundle { + val in = UInt(INPUT, width = w) + val data = UInt(OUTPUT) + val hi = UInt(INPUT, width = 16) + } + io.data := UInt(0) + + // Protect against bad random startup values. + val hi = UInt(INPUT, 16) + hi := UInt(0, 16) + when(io.hi < UInt(w)) { + hi := io.hi + } + io.data := io.in(hi, hi) + } + + class TestExtractDynamicOneBit(m: ExtractDynamic, maxWidth: Int, nRuns: Int) extends Tester(m) { + val width = 1 + for ((hi, dummy) <- genHiLo(rnd, maxWidth, nRuns)) { + val lo = hi + val data = BigInt(maxWidth, rnd) + val mask = (BigInt(1) << width) - 1 + println("width: %d, hi: %d, lo: %d, mask: 0x%x".format(maxWidth, hi, lo, mask)) + poke(m.io.in, data) + poke(m.io.hi, hi) + step(1) + expect(m.io.data, (data >> lo) & mask) + } + } + + class TestExtractDynamic(rnd: Random, maxWidth: Int, nTests: Int, nRuns: Int) { + + // Pick a random power of 2 from 4 to maxWidth + for (inputWidth <- genMaxWidths(rnd, maxWidth, nTests)) { + for (tester <- Array("c", "v")) { + if (tester == "v" && !Driver.isVCSAvailable) { + println("vcs unavailable - skipping Verilog test") + } else { + chiselMainTest(chiselEnvironmentArguments() ++ Array[String]("--backend", tester, "--compile", "--genHarness", "--test", "--targetDir", dir.getPath.toString()), + () => Module(new ExtractDynamic(inputWidth))) { + c => new TestExtractDynamicOneBit(c, inputWidth, nRuns) + } + } + } + } + } + + val t = new TestExtractDynamic(new Random(Driver.testerSeed), maxWidth, testCount, runCount) + } + + // Test dynamic val_t (extract bits from a created temporary). + test("extractDynamicVal_t") { + println("\nextractDynamicVal_t ...") + class ExtractDynamic(w: Int) extends Module { + val wTop = w/2 + val wBottom = w - wTop + val io = new Bundle { + val inTop = UInt(INPUT, width = wTop) + val inBottom = UInt(INPUT, width = wBottom) + val data = UInt(OUTPUT) + val hi = UInt(INPUT, width = 16) + val lo = UInt(INPUT, width = 16) + } + io.data := UInt(0) + + // Protect against bad random startup values. + val hi = UInt(INPUT, 16) + hi := UInt(0, 16) + val lo = UInt(INPUT, 16) + lo := UInt(0, 16) + when(io.hi >= io.lo && io.hi < UInt(w)) { + hi := io.hi + lo := io.lo + } + val in = Cat(io.inTop, io.inBottom) + io.data := in(hi, lo) + } + + class TestExtractDynamicVal_t(m: ExtractDynamic, maxWidth: Int, nRuns: Int) extends Tester(m) { + for ((hi, lo) <- genHiLo(rnd, maxWidth, nRuns)) { + val width = hi - lo + 1 + val wTop = maxWidth/2 + val wBottom = maxWidth - wTop + val data = BigInt(maxWidth, rnd) + val mask = (BigInt(1) << width) - 1 + val maskTop = (BigInt(1) << wTop) - 1 + val maskBottom = (BigInt(1) << wBottom) - 1 + println("maxWidth: %d, data: 0x%x, hi: %d, lo: %d, mask: 0x%x, wTop: %d, maskTop 0x%x, wBottom: %d, maskBottom: 0x%x".format(maxWidth, data, hi, lo, mask, wTop, maskTop, wBottom, maskBottom)) + poke(m.io.inBottom, data & maskBottom) + poke(m.io.inTop, (data >> wBottom) & maskTop) + poke(m.io.hi, hi) + poke(m.io.lo, lo) + step(1) + expect(m.io.data, (data >> lo) & mask) + } + } + + class TestExtractDynamic(rnd: Random, maxWidth: Int, nTests: Int, nRuns: Int) { + + // Pick a random power of 2 from 4 to maxWidth + for (inputWidth <- genMaxWidths(rnd, maxWidth, nTests)) { + for (tester <- Array("c", "v")) { + if (tester == "v" && !Driver.isVCSAvailable) { + println("vcs unavailable - skipping Verilog test") + } else { + chiselMainTest(chiselEnvironmentArguments() ++ Array[String]("--backend", tester, "--compile", "--genHarness", "--test", "--targetDir", dir.getPath.toString()), + () => Module(new ExtractDynamic(inputWidth))) { + c => new TestExtractDynamicVal_t(c, inputWidth, nRuns) + } + } + } + } + } + + val t = new TestExtractDynamic(new Random(Driver.testerSeed), maxWidth, testCount, runCount) + } +} diff --git a/src/test/scala/FillApp.scala b/src/test/scala/FillApp.scala new file mode 100644 index 00000000..2f76f0a9 --- /dev/null +++ b/src/test/scala/FillApp.scala @@ -0,0 +1,26 @@ +//package ChiselTests +import Chisel._ +import org.junit.Test +import org.junit.Assert._ + +class FillSuite extends TestSuite { + + // Issue #Chisel3/233 - Fill(Chisel.UInt, Int) + @Test def testFillArgOrder() { + println("\ntestFillArgOrder ...") + + class FillApp() extends Module { + val io = new Bundle { + val a = UInt(INPUT, 4) + } + val f = Fill(3, UInt(1,1)) + } + + val testArgs = chiselEnvironmentArguments() ++ Array("--targetDir", dir.getPath.toString(), + "--minimumCompatibility", "3.0.0", "--wError", "--backend", "null") + intercept[IllegalStateException] { + chiselMain(testArgs, () => Module(new FillApp())) + } + assertTrue(ChiselError.hasErrors) + } +} diff --git a/src/test/scala/FixedTest.scala b/src/test/scala/FixedTest.scala new file mode 100644 index 00000000..1736d070 --- /dev/null +++ b/src/test/scala/FixedTest.scala @@ -0,0 +1,585 @@ +/* + Copyright (c) 2011 - 2016 The Regents of the University of + California (Regents). All Rights Reserved. Redistribution and use in + source and binary forms, with or without modification, are permitted + provided that the following conditions are met: + + * Redistributions of source code must retain the above + copyright notice, this list of conditions and the following + two paragraphs of disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + two paragraphs of disclaimer in the documentation and/or other materials + provided with the distribution. + * Neither the name of the Regents nor the names of its contributors + may be used to endorse or promote products derived from this + software without specific prior written permission. + + IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, + SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, + ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF + REGENTS HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF + ANY, PROVIDED HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION + TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR + MODIFICATIONS. +*/ + +import scala.collection.mutable.ArrayBuffer +import scala.collection.mutable.ListBuffer +import org.junit.Assert._ +import org.junit.Test +import org.junit.Ignore + + +import Chisel._ + + +/** This testsuite checks all methods in the Bits class. +*/ +class FixedSuite extends TestSuite { + + def toFixedT(x : Double, fracWidth : Int) : BigInt = BigInt((x*scala.math.pow(2, fracWidth)).toInt) + def toFixed(x : Double, fracWidth : Int) : BigInt = BigInt(scala.math.round(x*scala.math.pow(2, fracWidth))) + def toDouble(x : BigInt, fracWidth : Int) : Double = x.toDouble/scala.math.pow(2, fracWidth) + + @Test def testConversion() { + class Dummy extends Module { + val io = UInt(INPUT, 0) + val r = scala.util.Random + val in = BigInt(r.nextInt(1 << 30)) + assertTrue(toFixed(toDouble(in, 16), 16) == in) + } + val dummyInst = Module(new Dummy) + } + + /** Extract a bit from a constant at a fixed position */ + @Test def testFixedConstructor() { + class Dummy extends Module { + val io = UInt(INPUT, 0) + val res = Fixed(0, 16, 8) + assertTrue( res.getWidth == 16 ) + assertTrue( res.getFractionalWidth == 8 ) + } + val dummyInst = Module(new Dummy) + } + + @Test def testFixedColonEqual() { + class FixedColonEqual extends Module { + val io = new Bundle { + val a = Fixed(INPUT, 32, 16) + val b = Fixed(OUTPUT, 16, 8) + } + io.b := io.a + assertTrue( io.a.getWidth() == 32) + assertTrue( io.a.getFractionalWidth() == 16) + assertTrue( io.b.getWidth() == 16) + assertTrue( io.b.getFractionalWidth() == 8) + } + + trait FixedColonEqualTests extends Tests { + val trials = 10 + def tests(c: FixedColonEqual) { + for (i <- 0 until trials) { + val inA = BigInt(rnd.nextInt(1 << 30)) + poke(c.io.a, inA) + expect(c.io.b, toFixedT(toDouble(inA, 16), 8)) + } + } + } + + class FixedColonEqualTester(c : FixedColonEqual) extends Tester(c) with FixedColonEqualTests { + tests(c) + } + + launchCppTester((c: FixedColonEqual) => new FixedColonEqualTester(c)) + } + + @Test def testFixedEqual() { + class FixedEqual extends Module { + val io = new Bundle { + val a = Fixed(INPUT, 32, 16) + val b = Fixed(INPUT, 32, 16) + val c = Bool(OUTPUT) + } + io.c := io.a === io.b + } + + trait FixedEqualTests extends Tests { + val trials = 10 + def tests(c: FixedEqual) { + for (i <- 0 until trials) { + val inA = BigInt(rnd.nextInt(1 << 30)) + val inB = if (i%2 == 0) inA else BigInt(rnd.nextInt(1 << 30)) + poke(c.io.a, inA) + poke(c.io.b, inB) + expect(c.io.c, Bool(inA == inB).litValue()) + } + } + } + + class FixedEqualTester(c : FixedEqual) extends Tester(c) with FixedEqualTests { + tests(c) + } + + launchCppTester((c: FixedEqual) => new FixedEqualTester(c)) + } + + @Test def testFixedAdd() { + class FixedAdd extends Module { + val io = new Bundle { + val a = Fixed(INPUT, 32, 16) + val b = Fixed(INPUT, 32, 16) + val c = Fixed(OUTPUT, 32, 16) + } + io.c := io.a + io.b + } + + trait FixedAddTests extends Tests { + val trials = 10 + def tests(c: FixedAdd) { + for (i <- 0 until trials) { + val inA = BigInt(rnd.nextInt(1 << 30)) * scala.math.pow(-1, rnd.nextInt(2)).toInt + val inB = BigInt(rnd.nextInt(1 << 30)) * scala.math.pow(-1, rnd.nextInt(2)).toInt + poke(c.io.a, inA) + poke(c.io.b, inB) + expect(c.io.c, toFixed(toDouble(inA, 16) + toDouble(inB, 16), 16)) + } + } + } + + class FixedAddTester(c: FixedAdd) extends Tester(c) with FixedAddTests { + tests(c) + } + + launchCppTester((c: FixedAdd) => new FixedAddTester(c)) + } + + @Test def testFixedSub() { + class FixedSub extends Module { + val io = new Bundle { + val a = Fixed(INPUT, 32, 16) + val b = Fixed(INPUT, 32, 16) + val c = Fixed(OUTPUT, 32, 16) + } + io.c := io.a - io.b + } + + trait FixedSubTests extends Tests { + val trials = 10 + def tests(c: FixedSub) { + for (i <- 0 until trials) { + val inA = BigInt(rnd.nextInt(1 << 30)) * scala.math.pow(-1, rnd.nextInt(2)).toInt + val inB = BigInt(rnd.nextInt(1 << 30)) * scala.math.pow(-1, rnd.nextInt(2)).toInt + poke(c.io.a, inA) + poke(c.io.b, inB) + expect(c.io.c, toFixed(toDouble(inA, 16) - toDouble(inB, 16), 16)) + } + } + } + + class FixedSubTester(c : FixedSub) extends Tester(c) with FixedSubTests { + tests(c) + } + + launchCppTester((c: FixedSub) => new FixedSubTester(c)) + } + + @Test def testFixedReg() { + class FixedReg extends Module { + val io = new Bundle { + val a = Fixed(INPUT, 32, 16) + val c = Fixed(OUTPUT, 32, 16) + } + io.c := Reg(init=Fixed(0, 32, 16), next=io.a) + } + + trait FixedRegTests extends Tests { + val trials = 10 + def tests(c: FixedReg) { + for (i <- 0 until trials) { + val inA = BigInt(rnd.nextInt(1 << 30)) * scala.math.pow(-1, rnd.nextInt(2)).toInt + poke(c.io.a, inA) + step(1) + expect(c.io.c, inA) + } + } + } + + class FixedRegTester(c : FixedReg) extends Tester(c) with FixedRegTests { + tests(c) + } + + launchCppTester((c: FixedReg) => new FixedRegTester(c)) + } + + @Test def testFixedUnary() { + class FixedUnary extends Module { + val io = new Bundle { + val a = Fixed(INPUT, 32, 16) + val c = Fixed(OUTPUT, 32, 16) + } + io.c := -io.a + } + + trait FixedUnaryTests extends Tests { + val trials = 10 + def tests(c: FixedUnary) { + for (i <- 0 until trials) { + val inA = BigInt(rnd.nextInt(1 << 30)) * scala.math.pow(-1, rnd.nextInt(2)).toInt + poke(c.io.a, inA) + expect(c.io.c, -inA) + } + } + } + + class FixedUnaryTester(c : FixedUnary) extends Tester(c) with FixedUnaryTests { + tests(c) + } + + launchCppTester((c: FixedUnary) => new FixedUnaryTester(c)) + } + + @Test def testFixedCompare() { + class FixedCompare extends Module { + val io = new Bundle { + val a = Fixed(INPUT, 32, 16) + val b = Fixed(INPUT, 32, 16) + val gt = Bool(OUTPUT) + val lt = Bool(OUTPUT) + val gte = Bool(OUTPUT) + val lte = Bool(OUTPUT) + } + io.gt := io.a > io.b + io.lt := io.a < io.b + io.gte := io.a >= io.b + io.lte := io.a <= io.b + } + + trait FixedCompareTests extends Tests { + val trials = 10 + def tests(c: FixedCompare) { + for (i <- 0 until trials) { + val inA = BigInt(rnd.nextInt(1 << 30)) * scala.math.pow(-1, rnd.nextInt(2)).toInt + val inB = BigInt(rnd.nextInt(1 << 30)) * scala.math.pow(-1, rnd.nextInt(2)).toInt + poke(c.io.a, inA) + poke(c.io.b, inB) + expect(c.io.gt, Bool(inA > inB).litValue()) + expect(c.io.lt, Bool(inA < inB).litValue()) + expect(c.io.gte, Bool(inA >= inB).litValue()) + expect(c.io.lte, Bool(inA <= inB).litValue()) + } + } + } + + class FixedCompareTester(c : FixedCompare) extends Tester(c) with FixedCompareTests { + tests(c) + } + + launchCppTester((c: FixedCompare) => new FixedCompareTester(c)) + } + + @Test def testFixedDiv() { + class FixedDiv extends Module { + val io = new Bundle { + val a = Fixed(INPUT, 32, 16) + val b = Fixed(INPUT, 32, 16) + val c = Fixed(OUTPUT, 32, 16) + } + io.c := io.a / io.b + } + + trait FixedDivTests extends Tests { + val trials = 10 + def tests(c: FixedDiv) { + for (i <- 0 until trials) { + + // For the testing find two numbers that we also give a number that is representable in fixed point + var inA = BigInt(rnd.nextInt(1 << 30)) * scala.math.pow(-1, rnd.nextInt(2)).toInt + var inB = BigInt(rnd.nextInt(1 << 30)) * scala.math.pow(-1, rnd.nextInt(2)).toInt + var doubleA = toDouble(inA, 16) + var doubleB = toDouble(inB, 16) + while( scala.math.abs(toDouble(toFixedT(doubleA / doubleB, 16), 16) - doubleA/doubleB) > scala.math.pow(2, -17)) { + inA = BigInt(rnd.nextInt(1 << 30)) * scala.math.pow(-1, rnd.nextInt(2)).toInt + inB = BigInt(rnd.nextInt(1 << 30)) * scala.math.pow(-1, rnd.nextInt(2)).toInt + doubleA = toDouble(inA, 16) + doubleB = toDouble(inB, 16) + } + poke(c.io.a, inA) + poke(c.io.b, inB) + expect(c.io.c, toFixedT(toDouble(inA, 16) / toDouble(inB, 16), 16)) + } + } + } + + class FixedDivTester(c : FixedDiv) extends Tester(c) with FixedDivTests { + tests(c) + } + + launchCppTester((c: FixedDiv) => new FixedDivTester(c)) + } + + @Test def testFixedMul() { + class FixedMul extends Module { + val io = new Bundle { + val a = Fixed(INPUT, 32, 16) + val b = Fixed(INPUT, 32, 16) + val c = Fixed(OUTPUT, 64, 32) + } + io.c := io.a * io.b + } + + trait FixedMulTests extends Tests { + val trials = 10 + def tests(c: FixedMul) { + for (i <- 0 until trials) { + val inA = BigInt(rnd.nextInt(1 << 15)) * scala.math.pow(-1, rnd.nextInt(2)).toInt + val inB = BigInt(rnd.nextInt(1 << 15)) * scala.math.pow(-1, rnd.nextInt(2)).toInt + poke(c.io.a, inA) + poke(c.io.b, inB) + expect(c.io.c, toFixedT(toDouble(inA, 16) * toDouble(inB, 16), 32)) + } + } + } + + class FixedMulTester(c : FixedMul) extends Tester(c) with FixedMulTests { + tests(c) + } + + launchCppTester((c: FixedMul) => new FixedMulTester(c)) + } + + @Test def testFixedMulT() { + class FixedMulT extends Module { + val io = new Bundle { + val a = Fixed(INPUT, 32, 16) + val b = Fixed(INPUT, 32, 16) + val c = Fixed(OUTPUT, 32, 16) + } + io.c := io.a *% io.b + } + + trait FixedMulTTests extends Tests { + val trials = 10 + def tests(c: FixedMulT) { + for (i <- 0 until trials) { + val inA = BigInt(rnd.nextInt(1 << 15)) * scala.math.pow(-1, rnd.nextInt(2)).toInt + val inB = BigInt(rnd.nextInt(1 << 15)) * scala.math.pow(-1, rnd.nextInt(2)).toInt + poke(c.io.a, inA) + poke(c.io.b, inB) + val expected = toFixedT(toDouble(inA, 16) * toDouble(inB, 16), 16) + val res = peek(c.io.c) + val errorVal = scala.math.abs(scala.math.abs(expected.toInt) - scala.math.abs(res.toInt)) + val error = errorVal > 1 + val errorMessage = if(error) "Error outside acceptiable Range: " + errorVal.toString else "Error within acceptiable range: " + errorVal.toString + expect(!error, errorMessage) + } + } + } + + class FixedMulTTester(c : FixedMulT) extends Tester(c) with FixedMulTTests { + tests(c) + } + + launchCppTester((c: FixedMulT) => new FixedMulTTester(c)) + } + + @Test def testFixedMulR() { + class FixedMulR extends Module { + val io = new Bundle { + val a = Fixed(INPUT, 32, 16) + val b = Fixed(INPUT, 32, 16) + val c = Fixed(OUTPUT, 32, 16) + } + io.c := io.a *& io.b + } + + trait FixedMulRTests extends Tests { + val trials = 10 + def tests(c: FixedMulR) { + for (i <- 0 until trials) { + val inA = BigInt(rnd.nextInt(1 << 15)) * scala.math.pow(-1, rnd.nextInt(2)).toInt + val inB = BigInt(rnd.nextInt(1 << 15)) * scala.math.pow(-1, rnd.nextInt(2)).toInt + poke(c.io.a, inA) + poke(c.io.b, inB) + expect(c.io.c, toFixed(toDouble(inA, 16) * toDouble(inB, 16), 16)) + } + } + } + + class FixedMulRTester(c : FixedMulR) extends Tester(c) with FixedMulRTests { + tests(c) + } + + launchCppTester((c: FixedMulR) => new FixedMulRTester(c)) + } + + @Test def testFixedLine() { + class FixedLine extends Module { + val io = new Bundle { + val a = Fixed(INPUT, 32, 16) + val b = Fixed(INPUT, 32, 16) + val c = Fixed(OUTPUT, 32, 16) + } + val temp = io.a + io.b + val temp2 = temp *& io.a + val temp3 = temp2 - io.b + io.c := temp3 + } + + trait FixedLineTests extends Tests { + val trials = 10 + def tests(c: FixedLine) { + for (i <- 0 until trials) { + val inA = BigInt(rnd.nextInt(1 << 15)) * scala.math.pow(-1, rnd.nextInt(2)).toInt + val inB = BigInt(rnd.nextInt(1 << 15)) * scala.math.pow(-1, rnd.nextInt(2)).toInt + poke(c.io.a, inA) + poke(c.io.b, inB) + expect(c.io.c, toFixed((toDouble(inA, 16) + toDouble(inB, 16)) * toDouble(inA, 16) - toDouble(inB, 16), 16)) + } + } + } + + class FixedLineTester(c : FixedLine) extends Tester(c) with FixedLineTests { + tests(c) + } + + launchCppTester((c: FixedLine) => new FixedLineTester(c)) + } + + @Test def testFixedMux() { + class FixedMux extends Module { + val io = new Bundle { + val a = Fixed(INPUT, 32, 16) + val b = Fixed(INPUT, 32, 16) + val c = Fixed(INPUT, 32, 16) + val sel = Bool(INPUT) + val res = Fixed(OUTPUT, 32, 16) + } + val muxSel = Mux(io.sel, io.a + io.b, io.a + io.c) + io.res := muxSel + } + + trait FixedMuxTests extends Tests { + val trials = 10 + def tests(c: FixedMux) { + for (i <- 0 until trials) { + val inA = BigInt(rnd.nextInt(1 << 15)) * scala.math.pow(-1, rnd.nextInt(2)).toInt + val inB = BigInt(rnd.nextInt(1 << 15)) * scala.math.pow(-1, rnd.nextInt(2)).toInt + val inC = BigInt(rnd.nextInt(1 << 15)) * scala.math.pow(-1, rnd.nextInt(2)).toInt + val inSel = rnd.nextInt(2) + poke(c.io.a, inA) + poke(c.io.b, inB) + poke(c.io.c, inC) + poke(c.io.sel, inSel) + val res = if(inSel == 1) toDouble(inA, 16) + toDouble(inB, 16) else toDouble(inA, 16) + toDouble(inC, 16) + expect(c.io.res, toFixed(res, 16)) + } + } + } + + class FixedMuxTester(c : FixedMux) extends Tester(c) with FixedMuxTests { + tests(c) + } + + launchCppTester((c: FixedMux) => new FixedMuxTester(c)) + } + + @Test def testFixedVec() { + class FixedVec extends Module { + val io = new Bundle { + val a = Vec.fill(8){Fixed(INPUT, 32, 16)} + val b = Vec.fill(8){Fixed(INPUT, 32, 16)} + val c = Fixed(OUTPUT, 32, 16) + } + io.c := (io.a, io.b).zipped.map(_ + _).reduce(_ + _) + } + + trait FixedVecTests extends Tests { + val trials = 10 + def tests(c: FixedVec) { + for (i <- 0 until trials) { + val inA = Array.fill(8){BigInt(rnd.nextInt(1 << 30)) * scala.math.pow(-1, rnd.nextInt(2)).toInt} + val inB = Array.fill(8){BigInt(rnd.nextInt(1 << 30)) * scala.math.pow(-1, rnd.nextInt(2)).toInt} + (c.io.a, inA).zipped.map((w, v) => poke(w, v)) + (c.io.b, inB).zipped.map((w, v) => poke(w, v)) + val res = (inA.map(v => toDouble(v, 16)), inB.map(v => toDouble(v, 16))).zipped.map(_ + _).reduce(_ + _) + expect(c.io.c, toFixed(res, 16)) + } + } + } + + class FixedVecTester(c : FixedVec) extends Tester(c) with FixedVecTests { + tests(c) + } + + launchCppTester((c: FixedVec) => new FixedVecTester(c)) + } + + @Test def testFixedVec2() { + class FixedVec2 extends Module { + val io = new Bundle { + val a = Vec.fill(8){Fixed(INPUT, 32, 16)} + val b = Vec.fill(8){Fixed(INPUT, 32, 16)} + val c = Vec.fill(8){Fixed(OUTPUT, 32, 16)} + } + io.c := (io.a, io.b).zipped.map(_*&_) + } + + trait FixedVec2Tests extends Tests { + val trials = 10 + def tests(c: FixedVec2) { + for (i <- 0 until trials) { + val inA = Array.fill(8){BigInt(rnd.nextInt(1 << 15)) * scala.math.pow(-1, rnd.nextInt(2)).toInt} + val inB = Array.fill(8){BigInt(rnd.nextInt(1 << 15)) * scala.math.pow(-1, rnd.nextInt(2)).toInt} + (c.io.a, inA).zipped.map((w, v) => poke(w, v)) + (c.io.b, inB).zipped.map((w, v) => poke(w, v)) + val res = (inA.map(v => toDouble(v, 16)), inB.map(v => toDouble(v, 16))).zipped.map(_*_) + (c.io.c, res).zipped.map((w, v) => expect(w, toFixed(v, 16))) + } + } + } + + class FixedVec2Tester(c : FixedVec2) extends Tester(c) with FixedVec2Tests { + tests(c) + } + + launchCppTester((c: FixedVec2) => new FixedVec2Tester(c)) + } + + @Test def testFixedMod() { + class FixedMod extends Module { + val io = new Bundle { + val a = Fixed(INPUT, 32, 16) + val b = Fixed(INPUT, 32, 16) + val c = Fixed(OUTPUT, 32, 16) + } + io.c := io.a % io.b + } + + trait FixedModTests extends Tests { + val trials = 10 + def tests(c: FixedMod) { + for (i <- 0 until trials) { + + // For the testing find two numbers that we also give a number that is representable in fixed point + var inA = BigInt(rnd.nextInt(1 << 30)) + var inB = BigInt(rnd.nextInt(1 << 30)) + poke(c.io.a, inA) + poke(c.io.b, inB) + val mod = inA % inB + expect(c.io.c, mod) + } + } + } + + class FixedModTester(c : FixedMod) extends Tester(c) with FixedModTests { + tests(c) + } + + launchCppTester((c: FixedMod) => new FixedModTester(c)) + } +} diff --git a/src/test/scala/FlushPrintfOutput.scala b/src/test/scala/FlushPrintfOutput.scala new file mode 100644 index 00000000..9c8f1545 --- /dev/null +++ b/src/test/scala/FlushPrintfOutput.scala @@ -0,0 +1,110 @@ +/* + Copyright (c) 2011 - 2016 The Regents of the University of + California (Regents). All Rights Reserved. Redistribution and use in + source and binary forms, with or without modification, are permitted + provided that the following conditions are met: + + * Redistributions of source code must retain the above + copyright notice, this list of conditions and the following + two paragraphs of disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + two paragraphs of disclaimer in the documentation and/or other materials + provided with the distribution. + * Neither the name of the Regents nor the names of its contributors + may be used to endorse or promote products derived from this + software without specific prior written permission. + + IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, + SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, + ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF + REGENTS HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF + ANY, PROVIDED HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION + TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR + MODIFICATIONS. +*/ + +import scala.util.matching.Regex +import scala.reflect.runtime.universe._ +import org.scalatest.Assertions._ +import org.scalatest.junit.JUnitSuite +import org.junit.Test +import org.junit.Ignore + +import Chisel._ +import FlushPrintfOutput._ + +object FlushPrintfOutput { + val whiteSpaceRE = """\s""".r + def eliminateWhiteSpace(s: String): String = whiteSpaceRE.replaceAllIn(s, "") +} + +class FlushPrintfOutput extends TestSuite { + + abstract class BasePrintfModule(theWidth: Int = 4) extends Module { + val io = new Bundle { + val in = Decoupled(UInt(width = theWidth)).flip + val out = Decoupled(UInt(width = theWidth)) + } + val counterString: String + val isFloat: Boolean + } + + class UIntPrintfModule extends BasePrintfModule { + val isFloat = false + val counterString: String = "counter = %d\n" + val counter = Reg(UInt(width = 8), init = UInt(0)) + counter := counter + UInt(1) + printf(counterString, counter); + } + + class FloPrintfModule extends BasePrintfModule { + val isFloat = true + val counterString = "counter = %e\n" + val counter = Reg(Flo(), init = Flo(0)) + counter := counter + Flo(1) + printf(counterString, counter); + } + + // TODO: better way to check logs? logging is lower than tests, so it sometimes fails... + trait FlushPrintfOutputTests extends Tests { + val expectedOutputs = collection.mutable.ArrayBuffer[String]() + def tests(m: BasePrintfModule) { + for (i <- 0 until 4) { + step(1) + Thread.sleep(10) + val output = printfs.last + val expected = m.counterString.format(if (m.isFloat) i.toFloat else i) + assertResult(true, "incorrect output - %s".format(output)) { + eliminateWhiteSpace(output) == eliminateWhiteSpace(expected) + } + } + } + } + + @Test def testFlushUIntPrintfOutput() { + println("\ntestFlushUIntPrintfOutput ...") + + class FlushPrintfOutputTester(m: UIntPrintfModule) extends Tester(m) with FlushPrintfOutputTests { + tests(m) + } + launchCppTester((m: UIntPrintfModule) => new FlushPrintfOutputTester(m)) + if (Driver.isVCSAvailable) { + launchVerilogTester((m: UIntPrintfModule) => new FlushPrintfOutputTester(m)) + } + } + + @Test def testFlushFlotPrintfOutput() { + println("\ntestFlushFloPrintfOutput ...") + + class FlushPrintfOutputTester(m: FloPrintfModule) extends Tester(m) with FlushPrintfOutputTests { + tests(m) + } + launchCppTester((m: FloPrintfModule) => new FlushPrintfOutputTester(m)) + } + +} diff --git a/src/test/scala/FunTestSuite.scala b/src/test/scala/FunTestSuite.scala new file mode 100644 index 00000000..42ea2999 --- /dev/null +++ b/src/test/scala/FunTestSuite.scala @@ -0,0 +1,40 @@ +/* + Copyright (c) 2011 - 2016 The Regents of the University of + California (Regents). All Rights Reserved. Redistribution and use in + source and binary forms, with or without modification, are permitted + provided that the following conditions are met: + + * Redistributions of source code must retain the above + copyright notice, this list of conditions and the following + two paragraphs of disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + two paragraphs of disclaimer in the documentation and/or other materials + provided with the distribution. + * Neither the name of the Regents nor the names of its contributors + may be used to endorse or promote products derived from this + software without specific prior written permission. + + IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, + SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, + ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF + REGENTS HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF + ANY, PROVIDED HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION + TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR + MODIFICATIONS. +*/ + +import org.scalatest.FunSuite + +// The launchers included in TestSuite do not work with ScalaTest tests, due to issues trying to +// instantiate instances of the device under test - the newInstance() method fails with an "invalid argument" +// exception apparently because the "this" argument is the enclosing Suite, +// whereas the module is defined in an anonymous function having its own class, and wants to be created with +// an instance of that class as the argument to the constructor. +// This could be resolved by moving all the DUT definitions up into the enclosing Suite, or by getting a handle +// on the particular ScalaTest test that is executing. +abstract class FunTestSuite extends FunSuite with TestHelpers {} diff --git a/src/test/scala/GCDUnitTest.scala b/src/test/scala/GCDUnitTest.scala new file mode 100644 index 00000000..bc8c3d8e --- /dev/null +++ b/src/test/scala/GCDUnitTest.scala @@ -0,0 +1,108 @@ +/* + Copyright (c) 2011 - 2016 The Regents of the University of + California (Regents). All Rights Reserved. Redistribution and use in + source and binary forms, with or without modification, are permitted + provided that the following conditions are met: + + * Redistributions of source code must retain the above + copyright notice, this list of conditions and the following + two paragraphs of disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + two paragraphs of disclaimer in the documentation and/or other materials + provided with the distribution. + * Neither the name of the Regents nor the names of its contributors + may be used to endorse or promote products derived from this + software without specific prior written permission. + + IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, + SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, + ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF + REGENTS HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF + ANY, PROVIDED HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION + TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR + MODIFICATIONS. +*/ + +import Chisel._ +import Chisel.testers.TesterDriver +import iotesters.SteppedHWIOTester +import org.junit.Assert._ +import org.junit.Test +import org.junit.Ignore +import TestHelpers._ + +// Test the Chisel3 UnitTester interface. + +class GCDUnitTest extends TestSuite { + + @Test def testGCDUnitTester() { + println("\ntestGCDUnitTester ...") + + class GCD extends Module { + val io = new Bundle { + val a = UInt(INPUT, 32) + val b = UInt(INPUT, 32) + val e = Bool(INPUT) + val z = UInt(OUTPUT, 32) + val v = Bool(OUTPUT) + } + val x = Reg(UInt(width = 32)) + val y = Reg(UInt(width = 32)) + when (x > y) { x := x -% y } + .otherwise { y := y -% x } + when (io.e) { x := io.a; y := io.b } + io.z := x + io.v := y === UInt(0) + } + + // We need to not only compute the GCD for test verification, + // we need to calculate the number of cycles it will take so we can + // structure out step()'s and expect()'s appropriately. + class GCDUnitTester extends SteppedHWIOTester { + def compute_gcd(a: Int, b: Int): Tuple2[Int, Int] = { + var x = a + var y = b + var depth = 1 + while(y > 0 ) { + if (x > y) { + x -= y + } + else { + y -= x + } + depth += 1 + } + return (x, depth) + } + + // Instantiate the GCD circuit. + val device_under_test = Module(new GCD) + val gcd = device_under_test + + for { + value_1 <- 4 to 8 + value_2 <- 2 to 4 + } { + poke(gcd.io.a, value_1) + poke(gcd.io.b, value_2) + poke(gcd.io.e, 1) + step(1) + poke(gcd.io.e, 0) + + val (expected_gcd, steps) = compute_gcd(value_1, value_2) + + step(steps-1) // -1 is because we step(1) already to toggle the enable + expect(gcd.io.z, expected_gcd) + expect(gcd.io.v, 1 ) + } + } + + implicit val args = Array[String]("--backend", "c", "--compile", "--genHarness", "--test", "--targetDir", TestHelpers.dir.getPath.toString()) + TesterDriver.execute { () => new GCDUnitTester } + } +} diff --git a/src/test/scala/LargeNumber.scala b/src/test/scala/LargeNumber.scala new file mode 100644 index 00000000..d305f1d0 --- /dev/null +++ b/src/test/scala/LargeNumber.scala @@ -0,0 +1,480 @@ +/* + Copyright (c) 2011 - 2016 The Regents of the University of + Sydney. All Rights Reserved. Redistribution and use in + source and binary forms, with or without modification, are permitted + provided that the following conditions are met: + + * Redistributions of source code must retain the above + copyright notice, this list of conditions and the following + two paragraphs of disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + two paragraphs of disclaimer in the documentation and/or other materials + provided with the distribution. + * Neither the name of the Regents nor the names of its contributors + may be used to endorse or promote products derived from this + software without specific prior written permission. + + IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, + SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, + ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF + REGENTS HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF + ANY, PROVIDED HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION + TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR + MODIFICATIONS. +*/ + +import scala.collection.mutable.ArrayBuffer +import scala.collection.mutable.ListBuffer +import scala.util.Random +import org.junit.Assert._ +import org.junit.Test +import org.junit.Ignore + +import Chisel._ + +/** This test suite tests the emulator with large integers ( > 64 bits ) + */ +class LargeNumberSuite extends TestSuite { + + val bitWidth = 130 + + def getBigRandom(rnd: Random, bitWidth : Int) : BigInt = { + val noWords = (bitWidth / 64).toInt + 1 + var myRand = BigInt( rnd.nextLong ) + for ( i <- 0 until noWords ) + myRand = ( myRand << 64 ) | BigInt( rnd.nextLong ) + val res = myRand & ( ( BigInt(1) << bitWidth ) - 1 ) + res + } + + def toSigned(myNum : BigInt, bitWidth : Int) : BigInt = { + if ( myNum > ( BigInt(1) << ( bitWidth - 1 ) )) + myNum - (BigInt(1) << bitWidth) + else + myNum + } + + class SandUIntIO(bitWidth : Int) extends Bundle { + val x_s = SInt(INPUT, width=bitWidth) + val y_s = SInt(INPUT, width=bitWidth) + val x_u = UInt(INPUT, width=bitWidth) + val y_u = UInt(INPUT, width=bitWidth) + val z_s = SInt(OUTPUT, width=bitWidth) + val z_u = UInt(OUTPUT, width=bitWidth) + } + + @Test def testNot() { + class Not extends Module { + val io = new SandUIntIO(bitWidth) + io.z_s := ~ io.x_s + io.z_u := ~ io.x_u + } + + class NotTests(c : Not) extends Tester(c) { + val x = getBigRandom(rnd, bitWidth) + val z = ~ x + poke(c.io.x_s, x) + poke(c.io.x_u, x) + expect(c.io.z_s, z) + expect(c.io.z_u, z) + } + launchCppTester((c: Not) => new NotTests(c)) + } + + @Test def testAdd() { + class Add extends Module { + val io = new SandUIntIO(bitWidth) + io.z_s := io.x_s + io.y_s + io.z_u := io.x_u + io.y_u + } + + class AddTests(c : Add) extends Tester(c) { + val x = getBigRandom(rnd, bitWidth) + val y = getBigRandom(rnd, bitWidth) + val z_u = x + y + val z_s = toSigned(x, bitWidth) + toSigned(y, bitWidth) + poke(c.io.x_s, x) + poke(c.io.x_u, x) + poke(c.io.y_s, y) + poke(c.io.y_u, y) + expect(c.io.z_s, z_s) + expect(c.io.z_u, z_u) + } + launchCppTester((c: Add) => new AddTests(c)) + } + + @Test def testSub() { + class Sub extends Module { + val io = new SandUIntIO(bitWidth) + io.z_s := io.x_s - io.y_s + io.z_u := io.x_u - io.y_u + } + + class SubTests(c : Sub) extends Tester(c) { + val x = getBigRandom(rnd, bitWidth) + val y = getBigRandom(rnd, bitWidth) + println("x = " + x) + println("y = " + y) + val z_u = x - y + val z_s = toSigned(x, bitWidth) - toSigned(y, bitWidth) + println("x = " + x) + println("y = " + y) + poke(c.io.x_s, x) + poke(c.io.x_u, x) + poke(c.io.y_s, y) + poke(c.io.y_u, y) + expect(c.io.z_s, z_s) + expect(c.io.z_u, z_u) + } + launchCppTester((c: Sub) => new SubTests(c)) + } + + @Test def testMult() { + class Mult extends Module { + val io = new SandUIntIO(bitWidth) + io.z_s := io.x_s * io.y_s + io.z_u := io.x_u * io.y_u + } + + class MultTests(c : Mult) extends Tester(c) { + val x = getBigRandom(rnd, bitWidth) + val y = getBigRandom(rnd, bitWidth) + val z_u = x * y + val z_s = toSigned(x, bitWidth) * toSigned(y, bitWidth) + poke(c.io.x_s, x) + poke(c.io.x_u, x) + poke(c.io.y_s, y) + poke(c.io.y_u, y) + expect(c.io.z_s, z_s) + expect(c.io.z_u, z_u) + } + launchCppTester((c: Mult) => new MultTests(c)) + } + + @Test def testDiv() { + class Div extends Module { + val io = new SandUIntIO(bitWidth) + io.z_s := io.x_s / io.y_s + io.z_u := io.x_u / io.y_u + } + + class DivTests(c : Div) extends Tester(c) { + val x = getBigRandom(rnd, bitWidth) + val y = getBigRandom(rnd, bitWidth/4) + val z_u = x / y + val z_s = toSigned(x, bitWidth) / toSigned(y, bitWidth) + poke(c.io.x_s, x) + poke(c.io.x_u, x) + poke(c.io.y_s, y) + poke(c.io.y_u, y) + expect(c.io.z_s, z_s) + expect(c.io.z_u, z_u) + } + launchCppTester((c: Div) => new DivTests(c)) + } + + @Test def testLsh() { + class Lsh extends Module { + val io = new SandUIntIO(bitWidth) + io.z_s := io.x_s << io.y_u + io.z_u := io.x_u << io.y_u + } + + class LshTests(c : Lsh) extends Tester(c) { + val x = getBigRandom(rnd, bitWidth) + val y = rnd.nextInt(bitWidth) + val z_u = x << y + val z_s = toSigned(x, bitWidth) << y + poke(c.io.x_s, x) + poke(c.io.x_u, x) + poke(c.io.y_s, BigInt(y)) + poke(c.io.y_u, BigInt(y)) + expect(c.io.z_s, z_s) + expect(c.io.z_u, z_u) + } + launchCppTester((c: Lsh) => new LshTests(c)) + } + + @Test def testRsh() { + class Rsh extends Module { + val io = new SandUIntIO(bitWidth) + io.z_s := io.x_s >> io.y_u + io.z_u := io.x_u >> io.y_u + } + + class RshTests(c : Rsh) extends Tester(c) { + val x = getBigRandom(rnd, bitWidth) + val y = rnd.nextInt(bitWidth) + val z_u = x >> y + val z_s = toSigned(x, bitWidth) >> y + poke(c.io.x_s, x) + poke(c.io.x_u, x) + poke(c.io.y_s, BigInt(y)) + poke(c.io.y_u, BigInt(y)) + expect(c.io.z_s, z_s) + expect(c.io.z_u, z_u) + } + launchCppTester((c: Rsh) => new RshTests(c)) + } + + // regression test for github #576 + @Test def testRshA576() { + class RightShift extends Module { + val W = 64 + + val io = new Bundle { + val a = SInt(INPUT, W) + val b = UInt(INPUT, log2Up(W)) + val signed = Bool(INPUT) + val out = SInt(OUTPUT, W) + } + + val toshift = Cat(io.a(W - 1) & io.signed, io.a).toSInt + io.out := toshift >> io.b + } + + class RightShiftTester(c: RightShift) extends Tester(c) { + val test = BigInt("-8000000000000000", 16) + + poke(c.io.a, test) + poke(c.io.signed, 1) + + for (i <- 0 until 8) { + poke(c.io.b, i) + step(1) + expect(c.io.out, test >> i) + } + } + launchCppTester((c:RightShift) => new RightShiftTester(c)) + } + + @Test def testRshExt() { + class Rsh extends Module { + val io = new Bundle { + val x = SInt(INPUT, width=66) + val z = SInt(OUTPUT, width=33) + } + io.z := io.x >> UInt(24, width=33) + } + + class RshTests(c : Rsh) extends Tester(c) { + val x = BigInt(4003500)*BigInt(825802) + val z = x >> 24 + poke(c.io.x, x) + expect(c.io.z, z) + } + launchCppTester((c: Rsh) => new RshTests(c)) + } + + @Test def testCat() { + class Cat extends Module { + val io = new Bundle { + val x_s = SInt(INPUT, width=bitWidth/2) + val y_s = SInt(INPUT, width=bitWidth/2) + val x_u = UInt(INPUT, width=bitWidth/2) + val y_u = UInt(INPUT, width=bitWidth/2) + val z_s = SInt(OUTPUT, width=bitWidth) + val z_u = UInt(OUTPUT, width=bitWidth) + } + io.z_s := io.x_s ## io.y_s + io.z_u := io.x_u ## io.y_u + } + + class CatTests(c : Cat) extends Tester(c) { + val x = getBigRandom(rnd, bitWidth/2) + val y = getBigRandom(rnd, bitWidth/2) + val z = (x << (bitWidth/2)) | y + poke(c.io.x_s, x) + poke(c.io.x_u, x) + poke(c.io.y_s, y) + poke(c.io.y_u, y) + expect(c.io.z_s, z) + expect(c.io.z_u, z) + } + launchCppTester((c: Cat) => new CatTests(c)) + } + + @Test def testXor() { + class Xor extends Module { + val io = new SandUIntIO(bitWidth) + io.z_s := io.x_s ^ io.y_s + io.z_u := io.x_u ^ io.y_u + } + + class XorTests(c : Xor) extends Tester(c) { + val x = getBigRandom(rnd, bitWidth) + val y = getBigRandom(rnd, bitWidth) + val z = x ^ y + poke(c.io.x_s, x) + poke(c.io.x_u, x) + poke(c.io.y_s, y) + poke(c.io.y_u, y) + expect(c.io.z_s, z) + expect(c.io.z_u, z) + } + launchCppTester((c: Xor) => new XorTests(c)) + } + + @Test def testAnd() { + class And extends Module { + val io = new SandUIntIO(bitWidth) + io.z_s := io.x_s & io.y_s + io.z_u := io.x_u & io.y_u + } + + class AndTests(c : And) extends Tester(c) { + val x = getBigRandom(rnd, bitWidth) + val y = getBigRandom(rnd, bitWidth) + val z = x & y + poke(c.io.x_s, x) + poke(c.io.x_u, x) + poke(c.io.y_s, y) + poke(c.io.y_u, y) + expect(c.io.z_s, z) + expect(c.io.z_u, z) + } + launchCppTester((c: And) => new AndTests(c)) + } + + @Test def testOr() { + class Or extends Module { + val io = new SandUIntIO(bitWidth) + io.z_s := io.x_s | io.y_s + io.z_u := io.x_u | io.y_u + } + + class OrTests(c : Or) extends Tester(c) { + val x = getBigRandom(rnd, bitWidth) + val y = getBigRandom(rnd, bitWidth) + val z = x | y + poke(c.io.x_s, x) + poke(c.io.x_u, x) + poke(c.io.y_s, y) + poke(c.io.y_u, y) + expect(c.io.z_s, z) + expect(c.io.z_u, z) + } + launchCppTester((c: Or) => new OrTests(c)) + } + + @Test def testLt() { + class Lt extends Module { + val io = new Bundle { + val x_s = SInt(INPUT, width=bitWidth) + val y_s = SInt(INPUT, width=bitWidth) + val x_u = UInt(INPUT, width=bitWidth) + val y_u = UInt(INPUT, width=bitWidth) + val z_s = Bool(OUTPUT) + val z_u = Bool(OUTPUT) + } + io.z_s := io.x_s < io.y_s + io.z_u := io.x_u < io.y_u + } + + class LtTests(c : Lt) extends Tester(c) { + val x = getBigRandom(rnd, bitWidth) + val y = getBigRandom(rnd, bitWidth) + val z_u = x < y + val z_s = toSigned(x, bitWidth) < toSigned(y, bitWidth) + poke(c.io.x_s, x) + poke(c.io.x_u, x) + poke(c.io.y_s, y) + poke(c.io.y_u, y) + expect(c.io.z_s, Bool(z_s).litValue()) + expect(c.io.z_u, Bool(z_u).litValue()) + } + launchCppTester((c: Lt) => new LtTests(c)) + } + + @Test def testLtEq() { + class LtEq extends Module { + val io = new Bundle { + val x_s = SInt(INPUT, width=bitWidth) + val y_s = SInt(INPUT, width=bitWidth) + val x_u = UInt(INPUT, width=bitWidth) + val y_u = UInt(INPUT, width=bitWidth) + val z_s = Bool(OUTPUT) + val z_u = Bool(OUTPUT) + } + io.z_s := io.x_s <= io.y_s + io.z_u := io.x_u <= io.y_u + } + + class LtEqTests(c : LtEq) extends Tester(c) { + val x = getBigRandom(rnd, bitWidth) + val y = getBigRandom(rnd, bitWidth) + val z_u = x <= y + val z_s = toSigned(x, bitWidth) <= toSigned(y, bitWidth) + poke(c.io.x_s, x) + poke(c.io.x_u, x) + poke(c.io.y_s, y) + poke(c.io.y_u, y) + expect(c.io.z_s, Bool(z_s).litValue()) + expect(c.io.z_u, Bool(z_u).litValue()) + } + launchCppTester((c: LtEq) => new LtEqTests(c)) + } + + @Test def testEq() { + class Eq extends Module { + val io = new Bundle { + val x_s = SInt(INPUT, width=bitWidth) + val y_s = SInt(INPUT, width=bitWidth) + val x_u = UInt(INPUT, width=bitWidth) + val y_u = UInt(INPUT, width=bitWidth) + val z_s = Bool(OUTPUT) + val z_u = Bool(OUTPUT) + } + io.z_s := io.x_s === io.y_s + io.z_u := io.x_u === io.y_u + } + + class EqTests(c : Eq) extends Tester(c) { + val x = getBigRandom(rnd, bitWidth) + val y = getBigRandom(rnd, bitWidth) + val z_u = x == x + val z_s = toSigned(x, bitWidth) == toSigned(y, bitWidth) + poke(c.io.x_s, x) + poke(c.io.x_u, x) + poke(c.io.y_s, y) + poke(c.io.y_u, x) + expect(c.io.z_s, Bool(z_s).litValue()) + expect(c.io.z_u, Bool(z_u).litValue()) + } + launchCppTester((c: Eq) => new EqTests(c)) + } + + @Test def testNeq() { + class Neq extends Module { + val io = new Bundle { + val x_s = SInt(INPUT, width=bitWidth) + val y_s = SInt(INPUT, width=bitWidth) + val x_u = UInt(INPUT, width=bitWidth) + val y_u = UInt(INPUT, width=bitWidth) + val z_s = Bool(OUTPUT) + val z_u = Bool(OUTPUT) + } + io.z_s := ( io.x_s =/= io.y_s ) + io.z_u := ( io.x_u =/= io.y_u ) + } + + class NeqTests(c : Neq) extends Tester(c) { + val x = getBigRandom(rnd, bitWidth) + val y = getBigRandom(rnd, bitWidth) + val z_u = x != x + val z_s = toSigned(x, bitWidth) != toSigned(y, bitWidth) + poke(c.io.x_s, x) + poke(c.io.x_u, x) + poke(c.io.y_s, y) + poke(c.io.y_u, x) + expect(c.io.z_s, Bool(z_s).litValue()) + expect(c.io.z_u, Bool(z_u).litValue()) + } + launchCppTester((c: Neq) => new NeqTests(c)) + } +} diff --git a/src/test/scala/ManyEnums.scala b/src/test/scala/ManyEnums.scala new file mode 100644 index 00000000..9d03d0d6 --- /dev/null +++ b/src/test/scala/ManyEnums.scala @@ -0,0 +1,57 @@ +/* + Copyright (c) 2011 - 2016 The Regents of the University of + California (Regents). All Rights Reserved. Redistribution and use in + source and binary forms, with or without modification, are permitted + provided that the following conditions are met: + + * Redistributions of source code must retain the above + copyright notice, this list of conditions and the following + two paragraphs of disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + two paragraphs of disclaimer in the documentation and/or other materials + provided with the distribution. + * Neither the name of the Regents nor the names of its contributors + may be used to endorse or promote products derived from this + software without specific prior written permission. + + IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, + SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, + ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF + REGENTS HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF + ANY, PROVIDED HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION + TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR + MODIFICATIONS. +*/ + +//package ChiselTests +import org.junit.Assert._ +import org.junit.Test +import org.junit.Ignore + +import Chisel._ + +class ManyEnumsSuite extends TestSuite { + @Test def testManyEnums() { + println("\ntestManyEnums...") + class ManyEnums extends Module { + val io = UInt(OUTPUT, 16) + val states = Enum(UInt(), + List('e_00, 'e_01, 'e_02, 'e_03, 'e_04, 'e_05, 'e_06, 'e_07, + 'e_08, 'e_09, 'e_10, 'e_11, 'e_12, 'e_13, 'e_14, 'e_15, 'e_16, 'e_17, + 'e_18, 'e_19, 'e_20, 'e_21, 'e_22)) + val state = Reg(UInt(), init = states('e_22)) + io := state + } + + class ManyEnumsTester(m: ManyEnums) extends Tester(m) { + expect(m.io, 22) + } + + launchCppTester((c: ManyEnums) => new ManyEnumsTester(c)) + } +} diff --git a/src/test/scala/ModuleTests.scala b/src/test/scala/ModuleTests.scala index 143a2f65..e7451dbc 100644 --- a/src/test/scala/ModuleTests.scala +++ b/src/test/scala/ModuleTests.scala @@ -1,5 +1,5 @@ /* - Copyright (c) 2011, 2012, 2013, 2014 The Regents of the University of + Copyright (c) 2011 - 2016 The Regents of the University of California (Regents). All Rights Reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: @@ -61,7 +61,7 @@ class ModuleTests extends TestSuite { } catch { case e : java.lang.IllegalStateException => {} } - assertTrue(!ChiselError.ChiselErrors.isEmpty); + assertTrue(ChiselError.hasErrors); } } \ No newline at end of file diff --git a/src/test/scala/MultiClockTest.scala b/src/test/scala/MultiClockTest.scala index c1c2aabe..4357f4f2 100644 --- a/src/test/scala/MultiClockTest.scala +++ b/src/test/scala/MultiClockTest.scala @@ -1,5 +1,5 @@ /* - Copyright (c) 2011, 2012, 2013, 2014 The Regents of the University of + Copyright (c) 2011 - 2016 The Regents of the University of California (Regents). All Rights Reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: @@ -69,26 +69,26 @@ class MultiClockSuite extends TestSuite { () => Module(new Comp())) assertFile("MultiClockSuite_Comp_1.v") } - + @Test def testBundleCustomClock() { println("testBundleCustomClock:") class TestMultiClock2 extends Module { class BundleXY extends Bundle{ - override def clone: this.type = (new BundleXY).asInstanceOf[this.type] + override def cloneType: this.type = (new BundleXY).asInstanceOf[this.type] val onSignal = Bool() } - + class TestMultiClock2_subsub(clkB: Clock) extends Module { val io = new Bundle { val in = Bool(INPUT) val out = Bool(OUTPUT) } - val r1 = Reg(outType = new BundleXY, clock = clkB) + val r1 = Reg(outType = new BundleXY, clock = clkB) r1.onSignal := io.in - + io.out := r1.onSignal } - + class TestMultiClock2_sub(clkA: Clock,clkB: Clock) extends Module(clkA) { val io = new Bundle { val in = Bool(INPUT) @@ -97,7 +97,7 @@ class MultiClockSuite extends TestSuite { val sub = Module(new TestMultiClock2_subsub(clkB)) sub.io <> io } - + val io = new Bundle { val in = Bool(INPUT) val out = Bool(OUTPUT) @@ -113,4 +113,23 @@ class MultiClockSuite extends TestSuite { () => Module(new TestMultiClock2())) assertFile("MultiClockSuite_TestMultiClock2_1.v") } + + @Test def testClockWithReset() { + class ClockDec extends Module { + val io = new Bundle { + val in = Bool(INPUT) + val out = Bool(OUTPUT) + } + val myNewReset = addResetPin(Bool()) + myNewReset.setName("myNewReset") + val myClock = new Clock(myNewReset) + val reg = Reg(init=Bool(false), clock=myClock) + reg := io.in + io.out := reg + } + chiselMain(Array[String]("--v", + "--targetDir", dir.getPath.toString()), + () => Module(new ClockDec())) + assertFile("MultiClockSuite_ClockDec_1.v") + } } diff --git a/src/test/scala/NameTest.scala b/src/test/scala/NameTest.scala index bfc77cc1..a72e33a1 100644 --- a/src/test/scala/NameTest.scala +++ b/src/test/scala/NameTest.scala @@ -1,5 +1,5 @@ /* - Copyright (c) 2011, 2012, 2013, 2014 The Regents of the University of + Copyright (c) 2011 - 2016 The Regents of the University of California (Regents). All Rights Reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: @@ -258,7 +258,7 @@ class NameSuite extends TestSuite { val error = Bool() val ppn = UInt(width = 32) - override def clone = new UnamedBundle().asInstanceOf[this.type] + override def cloneType = new UnamedBundle().asInstanceOf[this.type] } class BlockIO extends Bundle { @@ -270,7 +270,7 @@ class NameSuite extends TestSuite { val in = new BlockIO() val out = new BlockIO().flip } - val tag_ram = Vec.fill(2){ Reg(io.in.resp.bits.ppn) } + val tag_ram = Reg(Vec(2, io.in.resp.bits.ppn)) when (io.in.resp.valid) { tag_ram(UInt(0)) := io.in.resp.bits.ppn } @@ -343,7 +343,7 @@ class NameSuite extends TestSuite { class BlockReq extends Bundle { val ready = Bool() - override def clone = new BlockReq().asInstanceOf[this.type] + override def cloneType = new BlockReq().asInstanceOf[this.type] } class BlockIO extends Bundle { @@ -352,7 +352,7 @@ class NameSuite extends TestSuite { class VecSecondComp extends Module { val io = new Bundle { - val requestor = Vec.fill(4) { new BlockIO() }.flip + val requestor = Vec(4, new BlockIO() ).flip val mem = Bool(OUTPUT) } @@ -479,6 +479,7 @@ class NameSuite extends TestSuite { /* XXX test case derived from issue #6 on github. */ @Test def testInputPortNameChange() { + println("testInputPortNameChange:") class InputPortNameComp extends Module { val io = new Bundle { val in = Bits(INPUT, 20) @@ -498,46 +499,128 @@ class NameSuite extends TestSuite { /* XXX test case derived from issue #153 on github. */ @Test def testNameItTooEager153() { + println("testNameItTooEager153:") class MyBundle extends Bundle { val x = Bool() val y = Bool() val z = Bool() } - + class EntryIO(num_ports: Int) extends Bundle { - val vals = Vec.fill(num_ports) { Bool(INPUT) } + val vals = Vec(num_ports, Bool(INPUT) ) val out = Bool(OUTPUT) - } - + } + class Entry(num_ports: Int) extends Module { val io = new EntryIO(num_ports) io.out := io.vals.reduce(_|_) - } - + } + class NameItTooEager153 extends Module { val io = new Bundle { val idx = UInt(INPUT,2) - val vals = Vec.fill(4) { Bool(INPUT) } + val vals = Vec(4, Bool(INPUT) ) val z = Bool(OUTPUT) } - - val entry_io = Vec.fill(4) { Module(new Entry(4)).io } - + + val entry_io = Vec(4, Module(new Entry(4)).io ) + for (i <- 0 until 4) - { + { for (j <- 0 until 4) - { + { entry_io(i).vals(j) := io.vals(j) } } } - + chiselMain(Array[String]("--backend", "v", "--targetDir", dir.getPath.toString()), () => Module(new NameItTooEager153())) - + + } + + class KeywordsModule extends Module { + val io = new Bundle { + val a = UInt(INPUT, 2) + val z = UInt(OUTPUT, 2) + } + val begin = RegNext(io.a) + val time = RegNext(begin) + val end = RegNext(time) + io.z := end + } + + trait KeywordsModuleTestsCommon extends Tests { + val values = Vector(3,2,1) + def init(c: KeywordsModule) { + values foreach { v => + poke(c.io.a, v) + step(1) + } + } + } + + class KeywordsModulePathTests(c: KeywordsModule) extends Tester(c) with KeywordsModuleTestsCommon { + init(c) + expect(peekPath("NameSuite_KeywordsModule.begin_") == 1, "begin -> begin_: ") + expect(peekPath("NameSuite_KeywordsModule.time_") == 2, "time -> time_: ") + expect(peekPath("NameSuite_KeywordsModule.end_") == 3, "end -> end_: ") + } + + class KeywordsModuleNullTests(c: KeywordsModule) extends Tester(c) with KeywordsModuleTestsCommon { + init(c) + expect(c.begin, 1) + expect(c.time, 2) + expect(c.end, 3) + } + + @Test def testKeywordsCpp() { + println("testKeywordsCpp:") + launchCppTester((c: KeywordsModule) => new KeywordsModulePathTests(c)) + } + + @Test def testKeywordsVerilog() { + println("testKeywordsVerilog:") + // We'd like to use something like assume() here, but it generates + // a TestCanceledException. There should be a programmatic way to skip + // tests (without failing) but make a note of the fact. + if (!Driver.isVCSAvailable) { + assert(true, "vcs unavailable - skipping testKeywordsVerilog") + } else { + launchVerilogTester((c: KeywordsModule) => new KeywordsModulePathTests(c)) + } + } + + @Test def testKeywordsNull() { + println("testKeywordsNull:") + // Make sure we actually have a test to execute (the order of test runs is not defined, + // so testKeywordsCpp or testKeywordsVerilog may not have run yet. + chiselMain(Array[String]("--backend", "c", "--genHarness", "--compile", "--targetDir", dir.getPath.toString()), () => Module(new KeywordsModule())) + launchTester("null", (c: KeywordsModule) => new KeywordsModuleNullTests(c), + Some((args: Array[String]) => args ++ Array("--testCommand", dir.getPath.toString() + "/NameSuite_KeywordsModule", "-q"))) + } + + /* Multiple directionless IO's don't throw assertion error - issue #459. + */ + @Test def testMultipleDirectionlessIO459() { + println("testMultipleDirectionlessIO459:") + class MultipleDirectionlessIO459 extends Module { + val io = new Bundle { + val send = Reg(UInt(0, 8)) + val recv = Reg(UInt(0, 8)) + } + } + + // This should fail since we don't assign a directiom to the IO ports. + intercept[IllegalStateException] { + chiselMain(Array[String]("--backend", "v", + "--targetDir", dir.getPath.toString()), + () => Module(new MultipleDirectionlessIO459())) + } + assertTrue(ChiselError.hasErrors) } } diff --git a/src/test/scala/Outer.scala b/src/test/scala/Outer.scala new file mode 100644 index 00000000..fb98810b --- /dev/null +++ b/src/test/scala/Outer.scala @@ -0,0 +1,76 @@ +/* + Copyright (c) 2011 - 2016 The Regents of the University of + California (Regents). All Rights Reserved. Redistribution and use in + source and binary forms, with or without modification, are permitted + provided that the following conditions are met: + + * Redistributions of source code must retain the above + copyright notice, this list of conditions and the following + two paragraphs of disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + two paragraphs of disclaimer in the documentation and/or other materials + provided with the distribution. + * Neither the name of the Regents nor the names of its contributors + may be used to endorse or promote products derived from this + software without specific prior written permission. + + IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, + SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, + ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF + REGENTS HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF + ANY, PROVIDED HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION + TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR + MODIFICATIONS. +*/ + +//package ChiselTests +import org.junit.Assert._ +import org.junit.Test +import org.junit.Ignore + +import Chisel._ + + +class OuterSuite extends TestSuite { + @Test def testOuterSuite() { + println("\ntestOuterSuite...") + + class Inner extends Module { + val io = new Bundle { + val in = Bits(INPUT, 8) + val out = Bits(OUTPUT, 8) + } + io.out := io.in + Bits(1) + } + + class Outer extends Module { + val io = new Bundle { + val in = Bits(INPUT, 8) + val out = Bits(OUTPUT, 8) + } + // val c = Module(new Inner) + val c = Array(Module(new Inner)) + // val w = Wire(Bits(NO_DIR, 8)) + // w := io.in + c(0).io.in := io.in + io.out := (c(0).io.out * Bits(2))(7,0) + } + + class OuterTester(c: Outer) extends Tester(c) { + for (t <- 0 until 16) { + val test_in = rnd.nextInt(256) + poke(c.io.in, test_in) + step(1) + expect(c.io.out, ((test_in + 1) * 2)&255) + } + } + + launchCppTester((c: Outer) => new OuterTester(c)) + } +} + diff --git a/src/test/scala/ROM.scala b/src/test/scala/ROM.scala new file mode 100644 index 00000000..3e45d39e --- /dev/null +++ b/src/test/scala/ROM.scala @@ -0,0 +1,77 @@ +/* + Copyright (c) 2011 - 2016 The Regents of the University of + California (Regents). All Rights Reserved. Redistribution and use in + source and binary forms, with or without modification, are permitted + provided that the following conditions are met: + + * Redistributions of source code must retain the above + copyright notice, this list of conditions and the following + two paragraphs of disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + two paragraphs of disclaimer in the documentation and/or other materials + provided with the distribution. + * Neither the name of the Regents nor the names of its contributors + may be used to endorse or promote products derived from this + software without specific prior written permission. + + IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, + SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, + ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF + REGENTS HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF + ANY, PROVIDED HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION + TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR + MODIFICATIONS. +*/ + +//package ChiselTests +import org.junit.Test + +import Chisel._ + +class ROMSuite extends TestSuite { + // Verify we can initialize a ROM wider then 64 bits. + @Test def testWideROMInit() { + println("\ntestWideROMInit...") + class DUT extends Module { + + val DATAWIDTH = 133 + + val wideROM = { + val inits = (1 to 2).map(i => UInt(i, width = DATAWIDTH)) + ROM(inits) + } + + val io = new Bundle { + val m = UInt(INPUT, width = log2Up(DATAWIDTH)) + val fState = Bits(OUTPUT, width = DATAWIDTH) + } + + val inpBitStrReg = RegInit(Bits(0, width = DATAWIDTH)) + + inpBitStrReg := wideROM.read(io.m) + io.fState := inpBitStrReg + } + + class DUTTester(c: DUT) extends Tester(c) { + poke(c.io.m, 0) + // We expect a one-cycle delay in memory response. + expect(c.io.fState, 0) + step(1) + expect(c.io.fState, 1) + step(1) + poke(c.io.m, 1) + expect(c.io.fState, 1) + step(1) + // We expect a one-cycle delay in memory response. + expect(c.io.fState, 2) + } + val testArgs = chiselEnvironmentArguments() ++ Array("--targetDir", dir.getPath.toString(), + "--backend", "c", "--genHarness", "--compile", "--test", "--debug") + chiselMainTest(testArgs, () => Module(new DUT())){ c => new DUTTester(c) } + } +} diff --git a/src/test/scala/RegVcdTest.scala b/src/test/scala/RegVcdTest.scala new file mode 100644 index 00000000..28cb4aef --- /dev/null +++ b/src/test/scala/RegVcdTest.scala @@ -0,0 +1,122 @@ +/* + Copyright (c) 2011 - 2016 The Regents of the University of + California (Regents). All Rights Reserved. Redistribution and use in + source and binary forms, with or without modification, are permitted + provided that the following conditions are met: + + * Redistributions of source code must retain the above + copyright notice, this list of conditions and the following + two paragraphs of disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + two paragraphs of disclaimer in the documentation and/or other materials + provided with the distribution. + * Neither the name of the Regents nor the names of its contributors + may be used to endorse or promote products derived from this + software without specific prior written permission. + + IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, + SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, + ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF + REGENTS HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF + ANY, PROVIDED HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION + TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR + MODIFICATIONS. +*/ + +import org.junit.Assert._ +import org.junit.Test +import org.junit.Ignore + +import Chisel._ + + +class RegVcdSuite extends TestSuite { + + // We currently ignore this test until assertVCDFile is updated to deal with redundant signal values. + @Test def testRegVcd() { + println("\ntestRegVcd...") + class RegVcdTest(size: Int) extends Module { + val io = new Bundle { + val din = UInt(INPUT, size) + val write = Bool(INPUT) + val read = Bool(INPUT) + val ready = Bool(OUTPUT) + val full = Bool(OUTPUT) + val dout = UInt(OUTPUT, size) + // for debugging + val stateReg = Bool(OUTPUT) + } + + val empty :: full :: Nil = Enum(UInt(), 2) + val stateReg = Reg(init = empty) + val dataReg = Reg(init = Bits(0, size)) + + when (stateReg === empty) { + when (io.write) { + stateReg := full + dataReg := io.din + } + } . elsewhen(stateReg === full) { + when (io.read) { + stateReg := empty + } + } .otherwise { + } + + io.ready := (stateReg === empty) + io.full := (stateReg === full) + io.dout := dataReg + + io.stateReg := stateReg + } + + + /** + * Test the design. + */ + class RegVcdTestTester(dut: RegVcdTest) extends Tester(dut) { + + // some defaults for all signals + poke(dut.io.write, 0) + poke(dut.io.din, 0xab) + poke(dut.io.read, 0) + step(1) + peek(dut.io.ready) + + // write into the buffer + poke(dut.io.din, 0x12) + poke(dut.io.write, 1) + step(1) + peek(dut.io.ready) + + poke(dut.io.din, 0x34) + poke(dut.io.write, 0) + step(1) + peek(dut.io.ready) + + // read out + poke(dut.io.read, 1) + step(1) + poke(dut.io.read, 0) + step(1) + + // write next + poke(dut.io.din, 0x56) + poke(dut.io.write, 1) + step(1) + peek(dut.io.ready) + } + + val testArgs = chiselEnvironmentArguments() ++ Array("--targetDir", dir.getPath.toString(), + "--genHarness", "--test", "--backend", "c", "--compile", "--vcd") + chiselMainTest(testArgs, () => Module(new RegVcdTest(8))) { + f => new RegVcdTestTester(f) + } + assertVCDFile("RegVcdSuite_RegVcdTest_1.vcd") + } +} diff --git a/src/test/scala/RegWithAgregateDefaultSuite.scala b/src/test/scala/RegWithAgregateDefaultSuite.scala new file mode 100644 index 00000000..d671143f --- /dev/null +++ b/src/test/scala/RegWithAgregateDefaultSuite.scala @@ -0,0 +1,111 @@ +/* + Copyright (c) 2011 - 2016 The Regents of the University of + California (Regents). All Rights Reserved. Redistribution and use in + source and binary forms, with or without modification, are permitted + provided that the following conditions are met: + + * Redistributions of source code must retain the above + copyright notice, this list of conditions and the following + two paragraphs of disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + two paragraphs of disclaimer in the documentation and/or other materials + provided with the distribution. + * Neither the name of the Regents nor the names of its contributors + may be used to endorse or promote products derived from this + software without specific prior written permission. + + IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, + SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, + ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF + REGENTS HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF + ANY, PROVIDED HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION + TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR + MODIFICATIONS. +*/ + +import org.junit.Assert._ +import org.junit.Test +import org.junit.Ignore + +import Chisel._ + +class RegWithAgregateDefaultSuite extends TestSuite { + val myWidth = 32 + val intU = 42 + val intB = false + + @Test def testRegWithAgregateDefault() { + println("\ntestRegWithAgregateDefault...") + + class RegWithAgregateDefaultModule extends Module { + val io = new Bundle { + val outU = UInt(OUTPUT, myWidth) + val outB = Bool(OUTPUT) + } + + if (true) { + val v = Reg(init = Vec(12, UInt(intU, width = myWidth))) + io.outU := v(0) + io.outB := Bool(intB) + } else { + val r = Reg(init = new Bundle { + val a = UInt(intU, width = myWidth) + val b = Bool(intB) + override def cloneType: this.type = this + }) + io.outU := r.a + io.outB := r.b + } + } + + class RegWithAgregateDefaultTests(m: RegWithAgregateDefaultModule) extends Tester(m) { + val expectedBool = if (intB) 1 else 0 + expect(m.io.outU, intU) + expect(m.io.outB, expectedBool) + } + launchCppTester((m: RegWithAgregateDefaultModule) => new RegWithAgregateDefaultTests(m)) + } + + /* Verify that we give a reasonable error message when we can't flatten + * a bundle for use as a Reg. + */ + @Test def testRegWithBundleInit() { + println("\ntestRegWithBundleInit...") + + class BundleWithInit extends Bundle { + // This will fail for use as a Reg, mentioning the element "bar". + val bar = UInt(0, width=8).asOutput + override def cloneType: this.type = { + val res = new BundleWithInit() + res.asInstanceOf[this.type] + } + } + + class RegWithBundleInitModule extends Module { + val io = new Bundle { + val outU = UInt(OUTPUT, myWidth) + val outB = Bool(OUTPUT) + } + + // This will fail, generating a message mentioning the element "bar". + val v = Reg(new BundleWithInit()) + io.outU := v.bar + io.outB := Bool(false) + } + + class RegWithBundleInitTests(m: RegWithBundleInitModule) extends Tester(m) { + expect(m.io.outU, 0) + expect(m.io.outB, 0) + } + intercept[java.lang.reflect.InvocationTargetException] { + launchCppTester((m: RegWithBundleInitModule) => new RegWithBundleInitTests(m)) + } + assertTrue(ChiselError.getErrorList.exists(_.msgFun().contains("element \"bar\" has 1 input"))) + } + +} diff --git a/src/test/scala/Risc.scala b/src/test/scala/Risc.scala new file mode 100644 index 00000000..9e36a0ee --- /dev/null +++ b/src/test/scala/Risc.scala @@ -0,0 +1,150 @@ +/* + Copyright (c) 2011 - 2016 The Regents of the University of + California (Regents). All Rights Reserved. Redistribution and use in + source and binary forms, with or without modification, are permitted + provided that the following conditions are met: + + * Redistributions of source code must retain the above + copyright notice, this list of conditions and the following + two paragraphs of disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + two paragraphs of disclaimer in the documentation and/or other materials + provided with the distribution. + * Neither the name of the Regents nor the names of its contributors + may be used to endorse or promote products derived from this + software without specific prior written permission. + + IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, + SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, + ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF + REGENTS HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF + ANY, PROVIDED HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION + TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR + MODIFICATIONS. +*/ + +//package ChiselTests +import org.junit.Assert._ +import org.junit.Test +import org.junit.Ignore + +import Chisel._ + +class RiscSuite extends TestSuite { + + @Test def testRisc() { + println("\ntestRisc...") + class Risc extends Module { + val io = new Bundle { + val isWr = Bool(INPUT) + val wrAddr = UInt(INPUT, 8) + val wrData = Bits(INPUT, 32) + val boot = Bool(INPUT) + val valid = Bool(OUTPUT) + val out = Bits(OUTPUT, 32) + } + val file = Mem(256, Bits(width = 32)) + val code = Mem(256, Bits(width = 32)) + val pc = Reg(init=UInt(0, 8)) + + val add_op :: imm_op :: Nil = Enum(Bits(width = 8), 2) + + val inst = code(pc) + val op = inst(31,24) + val rci = inst(23,16) + val rai = inst(15, 8) + val rbi = inst( 7, 0) + + val ra = Mux(rai === Bits(0), Bits(0), file(rai)) + val rb = Mux(rbi === Bits(0), Bits(0), file(rbi)) + val rc = Bits(width = 32) + + io.valid := Bool(false) + io.out := Bits(0) + rc := Bits(0) + + when (io.isWr) { + code(io.wrAddr) := io.wrData + } .elsewhen (io.boot) { + pc := UInt(0) + } .otherwise { + switch(op) { + is(add_op) { rc := ra + rb } + is(imm_op) { rc := (rai << UInt(8)) | rbi } + } + io.out := rc + when (rci === UInt(255)) { + io.valid := Bool(true) + } .otherwise { + file(rci) := rc + } + pc := pc + UInt(1) + } + } + + class RiscTester(c: Risc) extends Tester(c) { + def wr(addr: BigInt, data: BigInt) = { + poke(c.io.isWr, 1) + poke(c.io.wrAddr, addr) + poke(c.io.wrData, data) + step(1) + } + def boot() = { + poke(c.io.isWr, 0) + poke(c.io.boot, 1) + step(1) + } + def I (op: UInt, rc: Int, ra: Int, rb: Int) = { + // val cr = Cat(op, UInt(rc, 8), UInt(ra, 8), UInt(rb, 8)).litValue() + val cr = op.litValue() << 24 | rc << 16 | ra << 8 | rb + println("I = " + cr) + cr + } + + val app = Array(I(c.imm_op, 1, 0, 1), // r1 <- 1 + I(c.add_op, 1, 1, 1), // r1 <- r1 + r1 + I(c.add_op, 1, 1, 1), // r1 <- r1 + r1 + I(c.add_op, 255, 1, 0)) // rh <- r1 + wr(0, 0) // skip reset + for (addr <- 0 until app.length) + wr(addr, app(addr)) + def dump(k: Int) { + println("K = " + k) + peek(c.ra) + peek(c.rb) + peek(c.rc) + peek(c.io.out) + peek(c.pc) + peek(c.inst) + peek(c.op) + peek(c.rci) + peek(c.rai) + peek(c.rbi) + peekAt(c.file, 1) + } + boot() + dump(0) + poke(c.io.boot, 0) + var k = 0 + do { + val expectedVal = peek(c.rc) + step(1) + k += 1 + dump(k) + expect(peekAt(c.file, 1) == expectedVal, "memory check") + } while (!(peek(c.io.valid) == 1 || k > 10)) + expect(k <= 10, "TIME LIMIT") + expect(c.io.out, 4) + } + + val testArgs = chiselEnvironmentArguments() ++ Array("--targetDir", dir.getPath.toString(), + "--backend", "c", "--genHarness", "--compile", "--test", "--debug") + chiselMainTest(testArgs, () => Module(new Risc())){ c => new RiscTester(c) } + } +} + diff --git a/src/test/scala/SeqMemSuite.scala b/src/test/scala/SeqMemSuite.scala new file mode 100644 index 00000000..fd420666 --- /dev/null +++ b/src/test/scala/SeqMemSuite.scala @@ -0,0 +1,73 @@ +/* + Copyright (c) 2011 - 2016 The Regents of the University of + California (Regents). All Rights Reserved. Redistribution and use in + source and binary forms, with or without modification, are permitted + provided that the following conditions are met: + + * Redistributions of source code must retain the above + copyright notice, this list of conditions and the following + two paragraphs of disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + two paragraphs of disclaimer in the documentation and/or other materials + provided with the distribution. + * Neither the name of the Regents nor the names of its contributors + may be used to endorse or promote products derived from this + software without specific prior written permission. + + IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, + SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, + ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF + REGENTS HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF + ANY, PROVIDED HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION + TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR + MODIFICATIONS. +*/ + +import Chisel._ +import org.junit.Assert._ +import org.junit.Test +import org.junit.Ignore + +class SeqMemSuite extends TestSuite { + // Test out creating a Sequential Memory + @Test def testSeqMemCreate() { + println("\ntestSeqMemCreate ...") + class CreateSeqMem(size: Integer) extends Module { + val io = new Bundle { + val wEnable = Bool(INPUT) + val rEnable = Bool(INPUT) + val addr = UInt(INPUT, log2Ceil(size)) + val value = UInt(INPUT, 32) + val out = UInt(OUTPUT, 32) + } + val mem = SeqMem(size, UInt(width = 32)) + when(io.wEnable) { + mem.write(io.addr, io.value) + } + val rdata = mem.read(io.addr, io.rEnable) + io.out := rdata + } + + class CreateSeqMemTester(c: CreateSeqMem, size: Int) extends Tester(c) { + for (t <- 0 until 4) { + val test_addr = rnd.nextInt(size) + val test_value = rnd.nextInt(log2Ceil(size)) + poke(c.io.addr, test_addr) + poke(c.io.value, test_value) + poke(c.io.wEnable, 1) + poke(c.io.rEnable, 1) + step(2) + expect(c.io.out, test_value) + } + } + val size = 1024 + val testArgs = chiselEnvironmentArguments() ++ Array("--compile", "--genHarness", "--test", "--targetDir", dir.getPath) + chiselMainTest(testArgs, () => Module(new CreateSeqMem(size))){ + c => new CreateSeqMemTester(c, size)} + } +} diff --git a/src/test/scala/StdlibTest.scala b/src/test/scala/StdlibTest.scala index cb59a473..5c413605 100644 --- a/src/test/scala/StdlibTest.scala +++ b/src/test/scala/StdlibTest.scala @@ -1,5 +1,5 @@ /* - Copyright (c) 2011, 2012, 2013, 2014 The Regents of the University of + Copyright (c) 2011 - 2016 The Regents of the University of California (Regents). All Rights Reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: @@ -144,8 +144,8 @@ try { // ===(b: UInt): Bool val v = io.x === io.y - // != (b: UInt): Bool - val w = io.x != io.y + // =/= (b: UInt): Bool + val w = io.x =/= io.y // > (b: UInt): Bool val x = io.x > io.y @@ -269,7 +269,7 @@ try { @Test def testAssignBundle() { println("\ntestAssignBundle ...") class AssignBundle extends Bundle { - val v = Vec.fill(2){UInt(INPUT, 2)} + val v = Vec(2, UInt(INPUT, 2)) } class AssignBundleComp extends Module { val io = new Bundle { @@ -285,7 +285,7 @@ try { } /** Concatenate two nodes X and Y in a node Z such that - Z[0..wx+wy] = X[0..wx] :: Y[0..wy]. */ + Z[0..wx + wy] = X[0..wx] :: Y[0..wy]. */ @Test def testCat() { println("\ntestCat ...") class CatComp extends Module { @@ -396,13 +396,10 @@ try { for (s <- 0 until m.nSections) { accumulatedDelay += s // The expected value is either the delayed poked value, - // or 0 if we haven't done enough poking. - val expected = if (d >= accumulatedDelay) { - pokeVal + accumulatedDelay - } else { - 0 + // initial values are not necessarily 0 + if (d >= accumulatedDelay) { + expect(m.io.stages(s), pokeVal + accumulatedDelay) } - expect(m.io.stages(s), expected) } step(1) } @@ -605,6 +602,55 @@ try { () => Module(new PriorityMuxComp())) } + /** PriorityMux can be used with Bundles. + */ + @Test def testPriorityMuxWithBundles() { + println("\ntestPriorityMuxWithBundles ...") + class BundleStub extends Bundle { + val x = Bool(INPUT) + + override def cloneType: this.type = new BundleStub().asInstanceOf[this.type] + } + class PriorityMuxComp extends Module { + val io = new Bundle { + val sel = UInt(INPUT, width = 2) + val in0 = new BundleStub() + val in1 = new BundleStub() + val out = new BundleStub().flip() + } + io.out := PriorityMux(io.sel, io.in0 :: io.in1 :: Nil) + } + + class PriorityMuxCompTester(m: PriorityMuxComp) extends Tester(m) { + // Put the value 0 in the first bundle, and 1 in the second + // bundle and verify that we get the expected output for sel = + // 0b01, 0b10, and 0b11. + + poke(m.io.in0.x, 0) + poke(m.io.in1.x, 1) + + poke(m.io.sel, 1) + expect(m.io.out.x, 0) + + poke(m.io.sel, 2) + expect(m.io.out.x, 1) + + poke(m.io.sel, 3) + expect(m.io.out.x, 0) + } + + chiselMainTest( + Array[String]( + "--backend", "c", + "--targetDir", dir.getPath.toString(), + "--genHarness", + "--compile", + "--test" + ), + () => Module(new PriorityMuxComp()) + ) {m => new PriorityMuxCompTester(m)} + } + /** Generate a PriorityEncoder */ @Test def testPriorityEncoder() { @@ -726,6 +772,72 @@ try { () => Module(new MuxCaseComp())) } + /** MuxCase can be used with Bundles. + */ + @Test def testMuxCaseWithBundles() { + println("\ntestMuxCaseWithBundles ...") + class BundleStub extends Bundle { + val x = Bool(INPUT) + + override def cloneType: this.type = new BundleStub().asInstanceOf[this.type] + } + + class MuxCaseComp extends Module { + val io = new Bundle { + val sel0 = Bool(INPUT) + val sel1 = Bool(INPUT) + val in0 = new BundleStub() + val in1 = new BundleStub() + val out = new BundleStub().flip() + } + val default = new BundleStub() + default.x := Bool(true) + io.out := MuxCase( + default, + Array( + io.sel0 -> io.in0, + io.sel1 -> io.in1 + ) + ) + } + + class MuxCaseCompTester(m: MuxCaseComp) extends Tester(m) { + // set the contents of the in0 and in1 bundles to 0 and 1 + // respectively and then verify the expected behaviour for all 4 + // combinations of sel0 and sel0. + + poke(m.io.in0.x, 0) + poke(m.io.in1.x, 1) + + poke(m.io.sel0, 0) + poke(m.io.sel1, 0) + expect(m.io.out.x, 1) + + poke(m.io.sel0, 1) + poke(m.io.sel1, 0) + expect(m.io.out.x, 0) + + poke(m.io.sel0, 0) + poke(m.io.sel1, 1) + expect(m.io.out.x, 1) + + poke(m.io.sel0, 1) + poke(m.io.sel1, 1) + expect(m.io.out.x, 0) + } + + chiselMainTest( + Array[String]( + "--backend", "c", + "--targetDir", dir.getPath.toString(), + "--genHarness", + "--compile", + "--test" + ), + () => Module(new MuxCaseComp()) + ) {m => new MuxCaseCompTester(m)} + } + /** Generate a Multiplex */ @Test def testMultiplex() { @@ -776,18 +888,41 @@ try { /** Test width adjustment for Operations on literals. * */ + @Test def testLitAddSubDoesntWiden () { + println("\ntestLitAddSubDoesntWiden ...") + + class LitAddSub extends Module { + val io = new Bundle { + val out1 = UInt(OUTPUT) + } + // The following should generate a warning since we'll assign the + // width of the result as the maximum of the input widths + // which will be too small for the computed result. + val res1 = Reg(init = (UInt(7) + UInt(2))) + debug(res1) + io.out1 := res1 + } + + try { + chiselMain(Array("--backend", "c", + "--targetDir", dir.getPath.toString()), + () => Module(new LitAddSub())) + } catch { + case e : java.lang.IllegalStateException => {} + } + assertTrue(ChiselError.hasErrors); + } + @Test def testLitAddSub () { println("\ntestLitAddSub ...") - + // If we had a "Tester" backend that allowed us to examine // the constructed graph, we wouldn't need this. class LitAddSub extends Module { val io = new Bundle { - val out1 = UInt(OUTPUT) val out2 = SInt(OUTPUT) val out3 = UInt(OUTPUT, width=8) } - val res1 = Reg(init = (UInt(7) + UInt(2))) val res2 = Reg(init = (SInt(2) - SInt(4))) val res3 = Reg(init = (UInt(2) - UInt(4))) // We'd like to just access the 'debug' nodes, @@ -795,29 +930,22 @@ try { // have been cases where unconnected debug node chains // don't have their type nodes removed or their widths // correctly inferred. These shouldn't happen, but ... - debug(res1) debug(res2) debug(res3) - io.out1 := res1 io.out2 := res2 io.out3 := res3 } class LitAddSubTester(m: LitAddSub) extends Tester(m) { // (until "expect" learns to deal with 0x and negative numbers...) // Half of these are redundant. - val res1 = peek(m.res1) val res2 = peek(m.res2) val res3 = peek(m.res3) - assertResult(9) { res1 } assertResult(-2) { res2 } assertResult(6) { res3 } - val out1 = peek(m.io.out1) val out2 = peek(m.io.out2) val out3 = peek(m.io.out3) - assertResult(9) { out1 } assertResult(-2) { out2 } assertResult(6) { out3 } - assertResult(4) {m.res1.getWidth} assertResult(4) {m.res2.getWidth} assertResult(3) {m.res3.getWidth} assertResult(4) {m.io.out2.getWidth} @@ -846,7 +974,7 @@ try { } catch { case e : java.lang.IllegalStateException => {} } - assertTrue(!ChiselError.ChiselErrors.isEmpty); + assertTrue(ChiselError.hasErrors); } /** Test for issue #384 - Data width lost in Vec @@ -876,4 +1004,24 @@ try { () => Module(new VecSIntWidth())) {m => new VecSIntWidthTester(m)} } + /** Test for issue #407 - Don't care in literal ("?") exhibits bizarre behavior + */ + @Test def testLitDontCare () { + println("\ntestLitDontCare ...") + try { + class LitDontCare extends Module { + val io = new Bundle { + val in = UInt(INPUT, 8) + val out = UInt(OUTPUT, 8) + } + io.out := Mux(io.in === (Bits("b?110") | Bits("b1???")), io.in, UInt(0)) + } + + chiselMain(testArgs, + () => Module(new LitDontCare())) + } catch { + case e : java.lang.IllegalStateException => {} + } + assertTrue(ChiselError.hasErrors); + } } diff --git a/src/test/scala/SubwordTests.scala b/src/test/scala/SubwordTests.scala new file mode 100644 index 00000000..a1f7ee38 --- /dev/null +++ b/src/test/scala/SubwordTests.scala @@ -0,0 +1,106 @@ +/* + Copyright (c) 2011 - 2016 The Regents of the University of + California (Regents). All Rights Reserved. Redistribution and use in + source and binary forms, with or without modification, are permitted + provided that the following conditions are met: + + * Redistributions of source code must retain the above + copyright notice, this list of conditions and the following + two paragraphs of disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + two paragraphs of disclaimer in the documentation and/or other materials + provided with the distribution. + * Neither the name of the Regents nor the names of its contributors + may be used to endorse or promote products derived from this + software without specific prior written permission. + + IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, + SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, + ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF + REGENTS HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF + ANY, PROVIDED HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION + TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR + MODIFICATIONS. +*/ + +import Chisel._ +import org.junit.Assert._ +import org.junit.Test +import org.junit.Ignore + +class SubwordSuite extends TestSuite { + class SubwordModule extends Module { + val w = 8 + val io = new Bundle { + val in = UInt(INPUT, w) + val out = UInt(OUTPUT, w) + } + io.out := UInt(0) + for (i <- 0 until w/2) { + io.out(i) := io.in(i) + } + } + + class SubwordTester(c: SubwordModule) extends Tester(c) { + val in = rnd.nextInt(1 << c.w) + poke(c.io.in, in) + expect(c.io.out, in & ((1 << (c.w/2))-1)) + } + + @Test def testSubwordCpp() { + println("\ntestSubwordCpp ...") + launchCppTester((c: SubwordModule) => new SubwordTester(c)) + } + + @Test def testSubwordVerilog() { + println("\ntestSubwordVerilog ...") + if (!Driver.isVCSAvailable) { + assert(true, "vcs unavailable - skipping testSubwordVerilog") + } else { + launchVerilogTester((c: SubwordModule) => new SubwordTester(c)) + } + } + + + class SubwordModule2 extends Module { + val w = 4 + val io = new Bundle { + val out_initial = UInt(INPUT, w) + val in = Bool(INPUT) + val out = UInt(OUTPUT, w) + } + + io.out := io.out_initial + io.out(0) := io.in + } + + class SubwordTester2(c: SubwordModule2) extends Tester(c) { + for ( + in <- Array(0, 1); + out_initial <- 0 until 1 << c.w + ) + { + poke(c.io.in, in) + poke(c.io.out_initial, out_initial) + var expected = out_initial + if (in == 1) { + // Set the least significant bit + expected |= 0x0001 + } else { + // Clear the least significant bit + expected &= 0xFFFE + } + expect(c.io.out, expected) + } + } + + @Test def testSubwordCpp2() { + println("\ntestSubwordCpp2 ...") + launchCppTester((c: SubwordModule2) => new SubwordTester2(c)) + } +} diff --git a/src/test/scala/AddFilter.scala b/src/test/scala/SysCTest/AddFilter.scala similarity index 96% rename from src/test/scala/AddFilter.scala rename to src/test/scala/SysCTest/AddFilter.scala index a062a303..c378ede4 100644 --- a/src/test/scala/AddFilter.scala +++ b/src/test/scala/SysCTest/AddFilter.scala @@ -1,5 +1,5 @@ /* - Copyright (c) 2011, 2012, 2013, 2014 The Regents of the University of + Copyright (c) 2011 - 2016 The Regents of the University of California (Regents). All Rights Reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: @@ -28,6 +28,8 @@ MODIFICATIONS. */ +package SysCTest + import Chisel._ import collection.mutable.ArrayBuffer @@ -75,7 +77,7 @@ object AddFilter { var argsBuild: ArrayBuffer[String] = ArrayBuffer(args : _*) //Pull out design name - var design:String = "" + var design:String = "AddFilter" for(i <- 0 until args.length){ if(args(i).equals("--design")) { design = args(i + 1) diff --git a/src/test/scala/SysCTest/FullAdder.scala b/src/test/scala/SysCTest/FullAdder.scala new file mode 100644 index 00000000..5794eab2 --- /dev/null +++ b/src/test/scala/SysCTest/FullAdder.scala @@ -0,0 +1,105 @@ +package SysCTest + +import Chisel._ + +class FullAdderInput extends Bundle { + val a = Bits(width = 1) + val b = Bits(width = 1) + val cin = Bits(width = 1) +} + +class FullAdderOutput extends Bundle { + val sum = Bits(width = 1) + val cout = Bits(width = 1) +} + +class FullAdder extends Module { + val io = new Bundle { + val in = Decoupled(new FullAdderInput()).flip() + val out = Decoupled(new FullAdderOutput()) + } + + val in_a = Reg(UInt(1)) + val in_b = Reg(UInt(1)) + val in_cin = Reg(UInt(1)) + val out_sum = Reg(init=UInt(0, 1)) + val out_cout = Reg(init=UInt(0, 1)) + + val p = Reg(init=Bool(false)) + val q = Reg(init=Bool(true)) + io.in.ready := !p + io.out.valid := !q + + when (io.in.valid && !p) { + in_a := io.in.bits.a + in_b := io.in.bits.b + in_cin := io.in.bits.cin + io.in.ready := Bool(false) + io.out.valid := Bool(false) + p := Bool(true) + q := Bool(true) + } + + when (io.out.ready && p) { + // Calculate the sum + val a_xor_b = in_a ^ in_b + out_sum := a_xor_b ^ in_cin + // Generate the carry + val a_and_b = io.in.bits.a & io.in.bits.b + val a_and_cin = io.in.bits.a & io.in.bits.cin + val b_and_cin = io.in.bits.b & io.in.bits.cin + out_cout := a_and_b | b_and_cin | a_and_cin + p := Bool(false) + q := Bool(false) + io.out.valid := p + } + io.out.bits.sum := out_sum + io.out.bits.cout := out_cout +} + +class FullAdderTests(c: FullAdder) extends Tester(c) { + var i = 0 + do { + val a = rnd.nextInt(2) + val b = rnd.nextInt(2) + val cin = rnd.nextInt(2) + val res = a + b + cin + val sum = res & 1 + val cout = (res >> 1) & 1 + var transfer = false + poke(c.io.in.valid, 0) + poke(c.io.out.ready, 0) + + do { + transfer = (peek(c.io.in.ready) == 1) + step(1) + } while (t < 50 && !transfer) + + poke(c.io.in.bits.a, a) + poke(c.io.in.bits.b, b) + poke(c.io.in.bits.cin, cin) + poke(c.io.in.valid, 1) + poke(c.io.out.ready, 1) + + do { + transfer = (peek(c.io.out.valid) == 1) + step(1) + } while (t < 50 && !transfer) + + expect(c.io.out.bits.sum, sum) + expect(c.io.out.bits.cout, cout) + i += 1 + printf("* INPUT -> a: %d b: %d cin: %d",a, b, cin) + printf(" - OUTPUT -> sum: %d cout: %d\n", sum, cout) + } while (t < 50 && i < 4) + if (t >= 50) fail +} + +object FullAdder { + def main(mainArgs: scala.Array[String]): Unit = { + val sysCArgs = Array[String]("--backend", "sysc", "--genHarness", "--compile", "--test") + val args = sysCArgs ++ mainArgs + chiselMainTest(args, + () => Module(new FullAdder())){c => new FullAdderTests(c)} + } +} diff --git a/src/test/scala/SystemCSuite.scala b/src/test/scala/SystemCSuite.scala new file mode 100644 index 00000000..042c4c5e --- /dev/null +++ b/src/test/scala/SystemCSuite.scala @@ -0,0 +1,72 @@ +/* + Copyright (c) 2011 - 2016 The Regents of the University of + California (Regents). All Rights Reserved. Redistribution and use in + source and binary forms, with or without modification, are permitted + provided that the following conditions are met: + + * Redistributions of source code must retain the above + copyright notice, this list of conditions and the following + two paragraphs of disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + two paragraphs of disclaimer in the documentation and/or other materials + provided with the distribution. + * Neither the name of the Regents nor the names of its contributors + may be used to endorse or promote products derived from this + software without specific prior written permission. + + IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, + SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, + ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF + REGENTS HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF + ANY, PROVIDED HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION + TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR + MODIFICATIONS. +*/ +import org.junit.Assert._ +import org.junit.Test +import org.junit.Ignore + +//package ChiselTests +import Chisel._ + + +/** This testsuite checks the SystemC backend implementation. +*/ +class SystemCSuite extends TestSuite { + // Test top-level IOs are decoupled. + @Test def testTopLevelIO() { + + class SystemCModuleGood extends Module { + val io = new Bundle { + val a = Decoupled( UInt(width = 16) ).flip() + val b = Decoupled( UInt(width = 16) ) + } + + io.b.bits := io.a.bits + UInt(10) + io.a.ready := io.b.ready + io.b.valid := io.a.valid + } + + class SystemCModuleBad extends Module { + val io = new Bundle { + val a = UInt(INPUT, width = 16) + val b = UInt(OUTPUT, width = 16) + } + + io.b := io.a + UInt(10) + } + + val testArgs = chiselEnvironmentArguments() ++ Array("--targetDir", dir.getPath, "--backend", "sysc") + + chiselMain(testArgs.toArray, () => Module(new SystemCModuleGood())) + assertFalse(ChiselError.hasErrors) + + chiselMain(testArgs.toArray, () => Module(new SystemCModuleBad())) + assertTrue(ChiselError.hasErrors) + } +} diff --git a/src/test/scala/TestHelpers.scala b/src/test/scala/TestHelpers.scala new file mode 100644 index 00000000..3805b231 --- /dev/null +++ b/src/test/scala/TestHelpers.scala @@ -0,0 +1,118 @@ +/* + Copyright (c) 2011 - 2016 The Regents of the University of + California (Regents). All Rights Reserved. Redistribution and use in + source and binary forms, with or without modification, are permitted + provided that the following conditions are met: + + * Redistributions of source code must retain the above + copyright notice, this list of conditions and the following + two paragraphs of disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + two paragraphs of disclaimer in the documentation and/or other materials + provided with the distribution. + * Neither the name of the Regents nor the names of its contributors + may be used to endorse or promote products derived from this + software without specific prior written permission. + + IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, + SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, + ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF + REGENTS HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF + ANY, PROVIDED HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION + TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR + MODIFICATIONS. +*/ + +import org.scalatest.Assertions +import java.io.File + +import Chisel._ +import TestHelpers._ + +object TestHelpers { + + val dir = new File("test-outputs") + val blankLines_re = """(?m)^\s*$[\r\n]+""".r + + // Ensure our output directory exists before we run any tests. + dir.mkdir + Driver.initChisel(Array[String]()) +} + +trait TestHelpers extends Assertions { + + def assertFile( filename: String ) { + val useNewCompare = true + val url = getClass.getResource(filename) + // Did we find the resource? + if (url == null) { + println("assertFile: \"%s\" not found".format(filename)) + // Make sure we don't inadvertently pass this test. + assertResult(filename) { "" } + return + } + val reffile = scala.io.Source.fromURL(url) + val refText = blankLines_re.replaceAllIn(reffile.mkString, "") + reffile.close() + val testfile = scala.io.Source.fromFile( + dir.getPath + "/" + filename, "utf-8") + val testText = blankLines_re.replaceAllIn(testfile.mkString, "") + testfile.close() + if (useNewCompare) { + val comparator = new TextComparator() + val testTextWithSubstitutions = comparator.substituteTextIfPossible(refText, testText) + assertResult(refText) { testTextWithSubstitutions } + } else { + assertResult(refText) { testText } + } + } + + def assertVCDFile( filename: String ) { + val masterPath = getClass.getResource(filename) + // Did we find the resource? + if (masterPath == null) { + println("assertFile: \"%s\" not found".format(filename)) + // Make sure we don't inadvertently pass this test. + assertResult(filename) { "" } + return + } + val reffile = scala.io.Source.fromURL(masterPath) + val refText = reffile.getLines.filter(_ != "").toArray + reffile.close() + val testPath = dir.getPath + "/" + filename + val testfile = scala.io.Source.fromFile(testPath, "utf-8") + val testText = testfile.getLines.filter(_ != "").toArray + testfile.close() + val comparator = new VCDComparator(masterPath.getPath(), testPath) + val result = comparator.compare(refText.toIterator, testText.toIterator) + assert(result == None) + } + + class BoolIO extends Bundle { + val in = Bool(INPUT) + val out = Bool(OUTPUT) + } + + class UIntIO extends Bundle { + val in = UInt(INPUT, 4) + val out = UInt(OUTPUT, 4) + } + + class DecoupledUIntIO extends Bundle { + val in = Decoupled(UInt(width = 4)).flip + val out = Decoupled(UInt(width = 4)) + } + + class EnableIO extends Bundle { + val en = Bool(INPUT) + val in = UInt(INPUT, 4) + val out = UInt(OUTPUT, 4) + } + // Create the singleton object,and as a side-effect, ensure the test output directory exists. + val dir = TestHelpers.dir +} diff --git a/src/test/scala/TestSuite.scala b/src/test/scala/TestSuite.scala index 4edba907..5c3a72af 100644 --- a/src/test/scala/TestSuite.scala +++ b/src/test/scala/TestSuite.scala @@ -1,5 +1,5 @@ /* - Copyright (c) 2011, 2012, 2013, 2014 The Regents of the University of + Copyright (c) 2011 - 2016 The Regents of the University of California (Regents). All Rights Reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: @@ -29,9 +29,9 @@ */ import org.scalatest.junit.JUnitSuite +import org.scalatest._ import org.junit.Before -import java.io.File -import scala.collection.mutable.ArrayBuffer +import org.scalatest._ import scala.reflect.ClassTag import scala.collection.JavaConversions import Chisel._ @@ -41,81 +41,37 @@ object TestSuite { // Should we enable some global settings? val partitionIslandsParameterName = "partitionIslands" - val defaultEnablePartitionIslands = false - val partitionIslandsParameter = System.getProperty(partitionIslandsParameterName) - val partitionIslandsEnable = if (partitionIslandsParameter == null) defaultEnablePartitionIslands else true + val partitionIslandsArguments = chiselEnvironmentArguments(partitionIslandsParameterName) } -abstract class TestSuite extends JUnitSuite { - - val dir = new File("test-outputs") - val blankLines_re = """(?m)^\s*$[\r\n]+""".r +abstract class TestSuite extends JUnitSuite with TestHelpers { + // This functionality has been replaced by the static TestHelper object + // and should be elminated. @Before def initialize() { - dir.mkdir - } - - def assertFile( filename: String ) { - val useNewCompare = true - val url = getClass.getResource(filename) - // Did we find the resource? - if (url == null) { - println("assertFile: \"%s\" not found".format(filename)) - // Make sure we don't inadvertently pass this test. - assertResult(filename) { "" } - return - } - val reffile = scala.io.Source.fromURL(url) - val refText = blankLines_re.replaceAllIn(reffile.mkString, "") - reffile.close() - val testfile = scala.io.Source.fromFile( - dir.getPath + "/" + filename, "utf-8") - val testText = blankLines_re.replaceAllIn(testfile.mkString, "") - testfile.close() - if (useNewCompare) { - val comparator = new TextComparator() - val testTextWithSubstitutions = comparator.substituteTextIfPossible(refText, testText) - assertResult(refText) { testTextWithSubstitutions } - } else { - assertResult(refText) { testText } - } } - - def launchTester[M <: Module : ClassTag, T <: Tester[M]](b: String, t: M => T) { + def launchTester[M <: Module : ClassTag, T <: Tester[M]](b: String, t: M => T, fArg: Option[(Array[String]) => Array[String]] = None) { val ctor = implicitly[ClassTag[M]].runtimeClass.getConstructors.head - val conditionalArgs = ArrayBuffer[String]() - - if (partitionIslandsEnable) { - conditionalArgs += "--partitionIslands" - } - val testArgs = Array[String]("--backend", b, + val baseArgs = chiselEnvironmentArguments() ++ Array[String]("--backend", b, "--targetDir", dir.getPath.toString(), "--genHarness", "--compile", "--test") - chiselMainTest(conditionalArgs.toArray ++ testArgs, + val testArgs = fArg match { + case Some(f) => { + f(baseArgs) + } + case None => { + baseArgs + } + } + chiselMainTest(testArgs, () => Module(ctor.newInstance(this).asInstanceOf[M])) {t} + // If this is a test of the Cpp backend, launch it again with some Cpp specific arguments, + // if "partitionIslands" is defined in the environment and isn't one of the specified test arguments. + if (b == "c" && partitionIslandsArguments.size != 0 && !testArgs.contains("--partitionIslands")) { + chiselMainTest(partitionIslandsArguments ++ testArgs, + () => Module(ctor.newInstance(this).asInstanceOf[M])) {t} + } } - def launchCppTester[M <: Module : ClassTag, T <: Tester[M]](t: M => T) = launchTester("c", t) - def launchVerilogTester[M <: Module : ClassTag, T <: Tester[M]](t: M => T) = launchTester("v", t) - - - class BoolIO extends Bundle { - val in = Bool(INPUT) - val out = Bool(OUTPUT) - } - - class UIntIO extends Bundle { - val in = UInt(INPUT, 4) - val out = UInt(OUTPUT, 4) - } - - class DecoupledUIntIO extends Bundle { - val in = Decoupled(UInt(width = 4)).flip - val out = Decoupled(UInt(width = 4)) - } - - class EnableIO extends Bundle { - val en = Bool(INPUT) - val in = UInt(INPUT, 4) - val out = UInt(OUTPUT, 4) - } + def launchCppTester[M <: Module : ClassTag, T <: Tester[M]](t: M => T, fArg: Option[(Array[String]) => Array[String]] = None) = launchTester("c", t, fArg) + def launchVerilogTester[M <: Module : ClassTag, T <: Tester[M]](t: M => T, fArg: Option[(Array[String]) => Array[String]] = None) = launchTester("v", t, fArg) } diff --git a/src/test/scala/TesterTest.scala b/src/test/scala/TesterTest.scala index ce036670..c9963963 100644 --- a/src/test/scala/TesterTest.scala +++ b/src/test/scala/TesterTest.scala @@ -1,5 +1,5 @@ /* - Copyright (c) 2011, 2012, 2013, 2014 The Regents of the University of + Copyright (c) 2011 - 2016 The Regents of the University of California (Regents). All Rights Reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: @@ -34,6 +34,7 @@ import org.junit.Test import Chisel._ import Chisel.Implicits._ import Chisel.AdvTester._ +import Chisel.testers.TesterDriver /** This testsuite checks the primitives of the standard library that will generate basic common graphs of *Node*. @@ -47,9 +48,8 @@ import Chisel.AdvTester._ // scalastyle:off method.length class TesterTest extends TestSuite { - val testArgs = Array("--backend", "v", - "--targetDir", dir.getPath.toString() - ) + + val backends: List[String] = TesterDriver.backends /** Test poking various numbers. * This is primarily a test of the Tester and its peek/poke/expect interface. @@ -57,7 +57,7 @@ class TesterTest extends TestSuite { */ @Test def testVariousPokes () { println("\ntestVariousPokes ...") - + class IOSelector extends Module { val io = new Bundle { val selectIn = UInt(INPUT, width=4) @@ -88,8 +88,8 @@ class TesterTest extends TestSuite { } } - class VariousPokeTester(m: IOSelector) extends Tester(m) { - case class TestVector(inSelect: Int, inValue: BigInt, expectedValue: BigInt) {} + trait VariousPokeTests extends Tests { + case class TestVector(inSelect: Int, inValue: BigInt, expectedValue: BigInt) val testVectors = Array[TestVector]( TestVector(0, -1, 0x0000000000000000ffL), TestVector(1, -1, 0x00000000000000ffffL), @@ -104,27 +104,35 @@ class TesterTest extends TestSuite { TestVector(8, -1, (BigInt(0x0000ffffffffffffffL) << 16)|0x00ffffL), TestVector(9, (java.lang.Float.floatToIntBits(-1.0f).toLong & 0x00000000ffffffffL), 0x00bf800000L) ) - for (tv <- testVectors) { - tv.inSelect match { - case 0 => poke(m.io.in8, tv.inValue) - case 1 => poke(m.io.in16, tv.inValue) - case 2 => poke(m.io.in24, tv.inValue) - case 3 => poke(m.io.in32, tv.inValue) - case 4 => poke(m.io.in40, tv.inValue) - case 5 => poke(m.io.in48, tv.inValue) - case 6 => poke(m.io.in56, tv.inValue) - case 7 => poke(m.io.in64, tv.inValue) - case 8 => poke(m.io.in72, tv.inValue) - case 9 => poke(m.io.infm1, tv.inValue) + def tests(m: IOSelector) { + for (tv <- testVectors) { + tv.inSelect match { + case 0 => poke(m.io.in8, tv.inValue) + case 1 => poke(m.io.in16, tv.inValue) + case 2 => poke(m.io.in24, tv.inValue) + case 3 => poke(m.io.in32, tv.inValue) + case 4 => poke(m.io.in40, tv.inValue) + case 5 => poke(m.io.in48, tv.inValue) + case 6 => poke(m.io.in56, tv.inValue) + case 7 => poke(m.io.in64, tv.inValue) + case 8 => poke(m.io.in72, tv.inValue) + case 9 => poke(m.io.infm1, tv.inValue) + } + poke(m.io.selectIn, tv.inSelect) + expect(m.io.out, tv.expectedValue) } - poke(m.io.selectIn, tv.inSelect) - expect(m.io.out, tv.expectedValue) } } - chiselMainTest(Array[String]("--backend", "c", - "--targetDir", dir.getPath.toString(), "--genHarness", "--compile", "--test"), - () => Module(new IOSelector())) {m => new VariousPokeTester(m)} + class VariousPokeTester(m: IOSelector) extends Tester(m) with VariousPokeTests { + tests(m) + } + + for (b <- backends) { + chiselMainTest(Array[String]("--backend", b, + "--targetDir", dir.getPath.toString(), "--genHarness", "--compile", "--test"), + () => Module(new IOSelector())) {m => new VariousPokeTester(m)} + } } /** Test poking negative numbers. @@ -133,32 +141,118 @@ class TesterTest extends TestSuite { */ @Test def testPokeNegTests () { println("\ntestPokeNegTests ...") - + class PokeNegModule extends Module { - - val io = new Bundle { + + val io = new Bundle { val i_value = UInt(INPUT, width = 64) val o_value = UInt(OUTPUT, width = 64) } - + io.o_value := io.i_value - } - - class PokeNegTests(c:PokeNegModule) extends AdvTester(c){ - isTrace = true - + } + + class PokeNegTests(c:PokeNegModule) extends AdvTester(c, true){ wire_poke(c.io.i_value, 0x7100a000a000a000L) expect(c.io.o_value, 0x7100a000a000a000L) - + wire_poke(c.io.i_value, 0x8100a000a000a000L) - expect(c.io.o_value, 0x8100a000a000a000L) - + expect(c.io.o_value, 0x8100a000a000a000L) + wire_poke(c.io.i_value, -1L ) expect(c.io.o_value, -1L ) - } - - chiselMainTest(Array[String]("--backend", "c", - "--targetDir", dir.getPath.toString(), "--genHarness", "--compile", "--test"), - () => Module(new PokeNegModule())) {m => new PokeNegTests(m)} + } + + for (b <- backends) { + chiselMainTest(Array[String]("--backend", b, + "--targetDir", dir.getPath.toString(), "--genHarness", "--compile", "--test"), + () => Module(new PokeNegModule())) {m => new PokeNegTests(m)} + } + } + + /** Test poking wide numbers. + * This is primarily a test of the Tester and its peek/poke/expect interface. + * + */ + @Test def testPokeWide () { + println("\ntestPokeWide ...") + + class PokeWideModule extends Module { + + val io = new Bundle { + val i_value = UInt(INPUT, width = 64) + val o_value = UInt(OUTPUT, width = 64) + } + + io.o_value := io.i_value + } + + class PokeWideTests(c:PokeWideModule) extends AdvTester(c, true){ + wire_poke(c.io.i_value, 0x7100a000a000a000L) + expect(c.io.o_value, 0x7100a000a000a000L) + + // We need to construct the next number carefully. + // We don't want it flagged as a negative number, + // so we manually construct it by shifting a positive number. + // (0x8100a000a000a000L is interpreted as a negative 64-bit number. + val notNeg = BigInt(0x8100a000a000a00L) << 4 + wire_poke(c.io.i_value, notNeg) + expect(c.io.o_value, notNeg) + + // "-1" is not a legal poke value for the Verilog tester.. + // All poke values must be hex strings for Verilog. + // See harnessAPIs() in Verilog.scala + //wire_poke(c.io.i_value, -1L ) + //expect(c.io.o_value, -1L ) + } + + for (b <- backends) { + chiselMainTest(Array[String]("--backend", b, + "--targetDir", dir.getPath.toString(), "--genHarness", "--compile", "--test"), + () => Module(new PokeWideModule())) {m => new PokeWideTests(m)} + } + } + + /** Test many IOs - issue #665. + * This is primarily a test of the Tester and its peek/poke/expect interface. + * + */ + @Test def testBigIO () { + println("\ntestBiGIO ...") + + class PokeBigIOModule extends Module { + + val io = new Bundle { + val i_values = Vec(8192, UInt(INPUT, width = 64)) + val o_values = Vec(10000, UInt(OUTPUT, width = 64)) + } + + io.o_values(9000) := io.i_values(8191) + } + + class PokeBigIOTests(c:PokeBigIOModule) extends AdvTester(c, true){ + wire_poke(c.io.i_values(8191), 0x7100a000a000a000L) + expect(c.io.o_values(9000), 0x7100a000a000a000L) + + // We need to construct the next number carefully. + // We don't want it flagged as a negative number, + // so we manually construct it by shifting a positive number. + // (0x8100a000a000a000L is interpreted as a negative 64-bit number. + val notNeg = BigInt(0x8100a000a000a00L) << 4 + wire_poke(c.io.i_values(8191), notNeg) + expect(c.io.o_values(9000), notNeg) + + // "-1" is not a legal poke value for the Verilog tester.. + // All poke values must be hex strings for Verilog. + // See harnessAPIs() in Verilog.scala + //wire_poke(c.io.i_value, -1L ) + //expect(c.io.o_value, -1L ) + } + + for (b <- backends) { + chiselMainTest(Array[String]("--backend", b, + "--targetDir", dir.getPath.toString(), "--genHarness", "--compile", "--test"), + () => Module(new PokeBigIOModule())) {m => new PokeBigIOTests(m)} + } } } diff --git a/src/test/scala/TextComparator.scala b/src/test/scala/TextComparator.scala index 1b98e2c3..ea7026c6 100644 --- a/src/test/scala/TextComparator.scala +++ b/src/test/scala/TextComparator.scala @@ -1,5 +1,5 @@ /* - Copyright (c) 2011, 2012, 2013, 2014 The Regents of the University of + Copyright (c) 2011 - 2016 The Regents of the University of California (Regents). All Rights Reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: diff --git a/src/test/scala/VCDComparator.scala b/src/test/scala/VCDComparator.scala new file mode 100644 index 00000000..28ec798b --- /dev/null +++ b/src/test/scala/VCDComparator.scala @@ -0,0 +1,213 @@ +/* + Copyright (c) 2011 - 2016 The Regents of the University of + California (Regents). All Rights Reserved. Redistribution and use in + source and binary forms, with or without modification, are permitted + provided that the following conditions are met: + + * Redistributions of source code must retain the above + copyright notice, this list of conditions and the following + two paragraphs of disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + two paragraphs of disclaimer in the documentation and/or other materials + provided with the distribution. + * Neither the name of the Regents nor the names of its contributors + may be used to endorse or promote products derived from this + software without specific prior written permission. + + IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, + SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, + ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF + REGENTS HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF + ANY, PROVIDED HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION + TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR + MODIFICATIONS. +*/ + +import scala.collection.mutable.HashMap +import scala.collection.mutable.ArrayBuffer +import scala.util.matching.Regex +import scala.io.Source._ +import java.io._ + +import TextComparator._ +import VCDComparator._ + +object VCDComparator { + val moduleDefRegex = """\$scope module (\S+) \$end""".r + val signalDefRegex = """\$var wire (\d+) (\S+) (\S+) \$end""".r + val signalValRegex = """b(\d+) (\S+)""".r + val VCDSignalValueBase = 2 + + /** Generate a signal name from a module name and a signal name + * @param moduleName The name of the module containing the signal. + * @param internalSignalName The name of the signal internal to the module. + * @return The combined (unique) signal name. + */ + def generateUniqueSignalName(moduleName: String, internalSignalName: String): String = "%s.%s".format(moduleName, internalSignalName) + + /** Return a map of short signal names to long (unique) signal names, and a list of module names. + */ + def buildSignalDefs(si: Iterator[String]): Tuple2[Map[String, String], List[String]] = { + val tSignalMap = scala.collection.mutable.HashMap[String, String]() + val moduleNames = ArrayBuffer[String]() + for (s <- si ) { + s match { + case moduleDefRegex(name) => moduleNames += name + case signalDefRegex(width, rep, name) => tSignalMap.put(rep, generateUniqueSignalName(moduleNames.last, name)) + case _ => {} + } + } + (tSignalMap.toMap, moduleNames.toList) + } + + def compareFiles(masters: Array[String], tests: Array[String]): Option[ComparatorError] = { + var finalResult: Option[ComparatorError] = None + try { + for ((masterFilePath, testFilePath) <- masters zip tests) { + val masterFile = fromFile(masterFilePath) + val masterLines = masterFile.getLines + masterFile.close() + val testFile = fromFile(testFilePath) + val testLines = testFile.getLines + testFile.close() + val comparator = new VCDComparator(masterFilePath, testFilePath) + val result = comparator.compare(masterLines.toIterator, testLines.toIterator) + result match { + case Some(e: ComparatorError) => throw e + case _ => {} + } + } + } catch { + case e: ComparatorError => finalResult = Some(e) + } + finalResult + } +} + +class VCDComparator(masterPath: String, testPath: String) { + type SignalStates = scala.collection.mutable.HashMap[String, Option[String]] + + /** Simulate the state of signals in a VCD file. + * Inspired by Palmer Dabbelt's vcddiff program. + * NOTE: This minimalist implementation is designed to deal with the VCD files generated by Chisel + * and may not work with generic VCD files. + */ + case class VCDStateSim(lines: Iterator[String]) { + // Partition the incoming stream into two sequences - definitions and data. + val (defs, data) = lines.partition(_.startsWith("$")) + // Generate the map from short signal names to long ones from the definition lines. + val (shortToLong: Map[String, String], moduleNames: List[String]) = buildSignalDefs(defs) + // Generate the inverse map. + val longToShort = shortToLong.map(_.swap) + // Create the signal state map, initialized to unknown signal values. + // Use the long (original) signal names as the keys + // Minor changes to the generated code could shuffle the short signal names + // and we want to compare values for the original (long) signals + val signalStates: SignalStates = shortToLong.values.map(k => (k, None))(collection.breakOut) + var clockTick = -1 + // Is there more data to be checked? + def hasNext: Boolean = data.hasNext + + /** Step one cycle. + * Read data lines updating the signal state until we see a clock change. + */ + def step() { + val startingTick = clockTick + // Loop while we have hasNext data and we haven't changed the clock + while (hasNext && clockTick == startingTick) { + val line = data.next() + // Is this a clock tick or a signal change? + line(0) match { + case '#' => { + // Increment the clock. This should terminate the loop. + clockTick += 1 + } + case 'b' => { + // Extract the signal name (short) and new value and update the signal state map for the original (long) named signal. + line match { + case signalValRegex(value, shortName) => signalStates(shortToLong(shortName)) = Some(value) + case _ => throw new ComparatorError("unrecognized line '%s'".format(line)) + } + } + } + } + } + + /** Position the stream to the cycle where the specified signal has the specified value. + * NOTE: This assumes we need to perform at least one step (i.e., the terminating condition is not current). + * @param name The name of the signal. + * @param value The desired signal value. + */ + def seek(longName: String, value: BigInt) { + do { + // If we've hit the end of the stream, indicate failure. + if (!hasNext) { + throw new ComparatorError("can't find %s with value %d.".format(longName, value)) + } + step() + } while (BigInt(signalStates(longName).get, VCDSignalValueBase) != value) + } + + /** Read and update the signal states until we see reset de-asserted. + * + */ + def init() { + step() // Position to the start of the first cycle. + // Find the reset signal + val reset = generateUniqueSignalName(moduleNames.head, "reset") + if (signalStates.contains(reset)) { + seek(reset, 0) + } + } + + /** Do two simulations have the same signal state? + * @param that The other simulation state to compare + * @return True if both simulations have identical signal states. + */ + def sameSignalValues(that: VCDStateSim): Boolean = { + this.signalStates equals that.signalStates + } + } + + /** Compare two VCD file streams. + * @param masterLines An iterator for the master (reference) VCD file. + * @param testLines An iterator for the comparison file. + * @return A ComparatorError if the files differ, otherwise None. + */ + def compare(masterLines: Iterator[String], testLines: Iterator[String]): Option[ComparatorError] = { + var result: Option[ComparatorError] = None + val vcdStates = new HashMap[String, VCDStateSim] + try { + // Initialize and position the two streams + for ( (name, stream) <- List(("master", masterLines), ("test", testLines))) { + val sim = new VCDStateSim(stream) + vcdStates(name) = sim + sim.init() + } + // Verify both define the same set of signals. + val differentSignals = vcdStates("master").signalStates.keySet &~ vcdStates("test").signalStates.keySet + if (!differentSignals.isEmpty) { + throw new ComparatorError("master and test differ on %s".format(differentSignals.mkString(", "))) + } + + // Step through the files ensuring signals are the same at each cycle, stopping when both files contain no hasNext data. + do { + if (!(vcdStates("master") sameSignalValues vcdStates("test"))) { + val clockTick = vcdStates("master").clockTick + val signals = vcdStates("master").signalStates.filter{ case (k, v) => vcdStates("test").signalStates(k) != v }.keys.mkString(", ") + throw new ComparatorError("%s and %s differ for signal %s at clockTick %d".format(masterPath, testPath, signals, clockTick)) + } + vcdStates("master").step() + vcdStates("test").step() + } while (vcdStates("master").hasNext || vcdStates("test").hasNext) + } catch { + case e: ComparatorError => result = Some(e) + } + result + } +} diff --git a/src/test/scala/VCDVerifySuite.scala b/src/test/scala/VCDVerifySuite.scala new file mode 100644 index 00000000..9ccb2458 --- /dev/null +++ b/src/test/scala/VCDVerifySuite.scala @@ -0,0 +1,88 @@ +/* + Copyright (c) 2011 - 2016 The Regents of the University of + California (Regents). All Rights Reserved. Redistribution and use in + source and binary forms, with or without modification, are permitted + provided that the following conditions are met: + + * Redistributions of source code must retain the above + copyright notice, this list of conditions and the following + two paragraphs of disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + two paragraphs of disclaimer in the documentation and/or other materials + provided with the distribution. + * Neither the name of the Regents nor the names of its contributors + may be used to endorse or promote products derived from this + software without specific prior written permission. + + IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, + SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, + ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF + REGENTS HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF + ANY, PROVIDED HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION + TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR + MODIFICATIONS. +*/ + +import org.junit.Assert._ +import org.junit.Test +import org.junit.Ignore +import scala.collection.mutable.HashMap +import scala.sys.process._ + +import Chisel._ + +object VCDVerifySuite { + val backends = List("c") /* ++ + (if (Driver.isVCSAvailable) { + "v" :: Nil + } else { + Nil + } + ) */ +} + +class VCDVerifySuite extends TestSuite { + + // We currently ignore this test until assertVCDFile is updated to deal with redundant signal values. + @Test def verifyVCD1() { + class Hz extends Module { + val io = new Bundle { + val input = Bool(INPUT) + val output = Bool(OUTPUT) + } + val reg = Reg(init = Bool(false)) + when (io.input) { + reg := Bool(true) + } + io.output := reg + } + + class Top extends Module { + val io = new Bundle { + val input = Bool(INPUT) + val output = Bool(OUTPUT) + } + val hz = Module(new Hz) + hz.io <> io + } + + class VCDTester(c: Top) extends Tester(c) { + step(1) + poke(c.io.input, true) + step(5) + } + + for (backend <- VCDVerifySuite.backends) { + chiselMain(Array[String]("--backend", backend, "--compile", "--genHarness", "--test", "--vcd", + "--targetDir", dir.getPath.toString()), + () => Module(new Top()), (c: Top) => new VCDTester(c)) + assertVCDFile("VCDVerifySuite_Top_1.vcd") + } + } +} + diff --git a/src/test/scala/VecApp.scala b/src/test/scala/VecApp.scala new file mode 100644 index 00000000..f714b6e1 --- /dev/null +++ b/src/test/scala/VecApp.scala @@ -0,0 +1,71 @@ +//package ChiselTests +import Chisel._ +import org.junit.Test +import org.junit.Assert._ + +class VecSuite extends TestSuite { + @Test def testMiscVec() { + println("\ntestMiscVec ...") + + class VecApp(n: Int, W: Int) extends Module { + class MyBundle(aWidth: Int) extends Bundle { + val aUInt = UInt(width = aWidth) + } + val io = IO(new Bundle { + val a = UInt(INPUT, n) + val i = Vec(n, Bits(INPUT, W)) + val d = Bits(OUTPUT, W) + }) + io.d := io.i(io.a) + } + + val testArgs = chiselEnvironmentArguments() ++ Array("--targetDir", dir.getPath.toString(), + "--minimumCompatibility", "3.0.0", "--wError", "--backend", "null") + chiselMain(testArgs, () => Module(new VecApp(8, 9))) + assertFalse(ChiselError.hasErrors) + } + + @Test def testEmptyVec() { + println("\ntestEmptyVec ...") + + class EmptyVec(n: Int) extends Module { + class MyBundle(aWidth: Int) extends Bundle { + val aUInt = UInt(width = aWidth) + } + val io = IO(new Bundle { + val empty = Vec(0, new MyBundle(n).asOutput) + }) + } + + val testArgs = chiselEnvironmentArguments() ++ Array("--targetDir", dir.getPath.toString(), + "--minimumCompatibility", "3.0.0", "--wError", "--backend", "null") + intercept[IllegalStateException] { + chiselMain(testArgs, () => Module(new EmptyVec(8))) + } + assertTrue(ChiselError.hasErrors) + } + // Issue #718 - Vec.fill with vec initializer + @Test def testVecFillFromVec() { + println("\ntestVecFillFromVec ...") + + class VecApp(n: Int) extends Module { + val io = IO(new Bundle { + val a = UInt(INPUT, n) + }) + val z = Vec(32, UInt(32, width=16)) + var i = 0 + val x = Vec.fill( 32 ) + { + val y = z(i) + i = i + 1 + y + } + } + + val testArgs = chiselEnvironmentArguments() ++ Array("--targetDir", dir.getPath.toString(), + /* "--minimumCompatibility", "3.0.0", "--wError",*/ "--backend", "null") + chiselMain(testArgs, () => Module(new VecApp(32))) + assertFalse(ChiselError.hasErrors) + + } +} diff --git a/src/test/scala/VerifTest.scala b/src/test/scala/VerifTest.scala index bf45f44d..73c2bf2b 100644 --- a/src/test/scala/VerifTest.scala +++ b/src/test/scala/VerifTest.scala @@ -1,5 +1,5 @@ /* - Copyright (c) 2011, 2012, 2013, 2014 The Regents of the University of + Copyright (c) 2011 - 2016 The Regents of the University of California (Regents). All Rights Reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: @@ -111,7 +111,7 @@ class VerifSuite extends TestSuite { } catch { case _ : Throwable => ; } - assertTrue(!ChiselError.ChiselErrors.isEmpty); + assertTrue(ChiselError.hasErrors); } @Test def testPrintfVerilog() { @@ -151,4 +151,83 @@ class VerifSuite extends TestSuite { () => Module(new VerilogPrintfNULComp())) assertFile("VerifSuite_VerilogPrintfNULComp_1.v") } + + class AssertTestModule extends Module { + val io = new QueueIO(UInt(width=4), 2) + io.deq <> Queue(io.enq, 2) + assert(!(io.deq.ready && !io.deq.valid), "pop from an empty queue") + } + + trait AssertTesterCommon extends Tests { + val values = Vector.fill(2)(rnd.nextInt(1 << 4)) + def queue(c: AssertTestModule) { + for (v <- values) { + poke(c.io.enq.bits, v) + poke(c.io.enq.valid, 1) + step(1) + } + poke(c.io.enq.valid, 0) + expect(c.io.enq.ready, 0) + for (v <- values) { + expect(c.io.deq.bits, v) + expect(c.io.deq.valid, 1) + poke(c.io.deq.ready, 1) + step(1) + } + expect(c.io.deq.valid, 0) + } + } + + class AssertNoFireTester(c: AssertTestModule) extends Tester(c) with AssertTesterCommon { + // Asserts shouldn't fire in this test + queue(c) + } + + class AssertFireTester(c: AssertTestModule) extends Tester(c) with AssertTesterCommon { + queue(c) + // Asserts should fire here + step(1) + } + + @Test def testAssertNoFireCpp { + println("\ntestAssertNoFireCpp ...") + launchCppTester((c: AssertTestModule) => new AssertNoFireTester(c)) + } + + @Test def testAssertNoFireVerilog { + println("\ntestAssertNoFireVerilog ...") + if (!Driver.isVCSAvailable) { + assert(true, "vcs unavailable - skipping testPokeWide") + } else { + launchVerilogTester((c: AssertTestModule) => new AssertNoFireTester(c)) + } + } + + @Test def testAssertFireCpp { + println("\ntestAssertFireCpp ...") + var hasException = false + try { + launchCppTester((c: AssertTestModule) => new AssertFireTester(c)) + } catch { + case e: TestApplicationException => hasException = true + case _: Throwable => + } + assertTrue(hasException) + } + + @Test def testAssertFireVerilog { + println("\ntestAssertFireVerilog ...") + if (!Driver.isVCSAvailable) { + assert(true, "vcs unavailable - skipping testPokeWide") + } else { + var hasException = false + try { + launchVerilogTester((c: AssertTestModule) => new AssertFireTester(c)) + } catch { + case e: TestApplicationException => hasException = true + case _: Throwable => + } + assertTrue(hasException) + } + } } diff --git a/src/test/scala/VerilogMultiModule.scala b/src/test/scala/VerilogMultiModule.scala index a9e43b62..7e5d384f 100644 --- a/src/test/scala/VerilogMultiModule.scala +++ b/src/test/scala/VerilogMultiModule.scala @@ -1,5 +1,5 @@ /* - Copyright (c) 2011, 2012, 2013, 2014 The Regents of the University of + Copyright (c) 2011 - 2016 The Regents of the University of California (Regents). All Rights Reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: @@ -40,13 +40,13 @@ class VerilogMultiModule extends TestSuite { // A class to generate multiple "filter" sections. // The default is two sections. // For any module with more than one section, Queues are used to interconnect sections. - case class MultiMultiFIR (nSections: Int = 2) extends Module { - case class MultiFIR (nSections: Int = 2) extends Module { + class MultiMultiFIR (nSections: Int = 2) extends Module { + class MultiFIR (nSections: Int = 2) extends Module { class FilterSection(coeffs: Array[Flo]) extends Module { val io = new Bundle { val in = Decoupled(Flo(INPUT)).flip val out = Decoupled(Flo(OUTPUT)) - + } // Specify the filter function - multiply by two. io.out.bits := io.in.bits * Flo(2.0) @@ -54,7 +54,7 @@ class VerilogMultiModule extends TestSuite { io.out.valid := io.in.valid io.in.ready := io.out.ready } - + val io = new Bundle { val in = Decoupled(Flo(INPUT)).flip val out = Decoupled(Flo(OUTPUT)) @@ -70,7 +70,7 @@ class VerilogMultiModule extends TestSuite { // Do we have a following section? if (s < nSections) { val q = Module(new Queue(Flo(), 4)) - // q.name = "q" + s.toString + (s+1).toString + // q.name = "q" + s.toString + (s + 1).toString q.io.enq <> f.io.out lastin = q.io.deq } else { @@ -86,7 +86,7 @@ class VerilogMultiModule extends TestSuite { val m2 = Module(new MultiFIR(nSections)) m2.io.in <> m1.io.out } - + chiselMain(Array[String]("--backend", "v", "--targetDir", dir.getPath.toString()), () => Module(new MultiMultiFIR(3))) diff --git a/src/test/scala/VersionSuite.scala b/src/test/scala/VersionSuite.scala new file mode 100644 index 00000000..cc0fb6e5 --- /dev/null +++ b/src/test/scala/VersionSuite.scala @@ -0,0 +1,75 @@ +/* + Copyright (c) 2011 - 2016 The Regents of the University of + California (Regents). All Rights Reserved. Redistribution and use in + source and binary forms, with or without modification, are permitted + provided that the following conditions are met: + + * Redistributions of source code must retain the above + copyright notice, this list of conditions and the following + two paragraphs of disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + two paragraphs of disclaimer in the documentation and/or other materials + provided with the distribution. + * Neither the name of the Regents nor the names of its contributors + may be used to endorse or promote products derived from this + software without specific prior written permission. + + IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, + SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, + ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF + REGENTS HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF + ANY, PROVIDED HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION + TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR + MODIFICATIONS. +*/ + +import scala.collection.mutable.ArrayBuffer +import org.scalatest._ +//import org.junit.Assert._ +import org.junit.Test + +import Chisel._ +class VersionSuite extends TestSuite { + @Test def testValidVersions() { + val versions = Array[(Version, Version, String)]( + ("", "99.99.99", "!="), + ("", "", "=="), + ("3", "2.99.99", "!="), + ("4", "3", "!="), + ("3", "3.99.99", "!="), + ("3.99.99", "3", "!="), + ("3.0", "2.9", "!="), + ("3.9", "3", "!="), + ("3.9", "3.0", "!="), + ("3.9", "3.9.99", "!="), + ("3.2.1", "3.2.1", "==") + + ) + for((v1, v2, eq) <- versions) { + assert(v1 >= v2) + if (eq == "==") { + assert(v1 == v2) + } else { + assert(v1 != v2) + } + } + } + + @Test def testInvalidVersions() { + val versions = Array[String]( + ("foo"), + ("3..5"), + ("3.4.5.6") + ) + for(s <- versions) { + intercept[IllegalArgumentException] { + val v = Version(s) + } + } + } +} \ No newline at end of file diff --git a/src/test/scala/WhenTest.scala b/src/test/scala/WhenTest.scala index 02a2081d..0a6b568c 100644 --- a/src/test/scala/WhenTest.scala +++ b/src/test/scala/WhenTest.scala @@ -1,5 +1,5 @@ /* - Copyright (c) 2011, 2012, 2013, 2014 The Regents of the University of + Copyright (c) 2011 - 2016 The Regents of the University of California (Regents). All Rights Reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: @@ -114,9 +114,9 @@ class WhenSuite extends TestSuite { poke(m.io.en0, int(en0)) poke(m.io.en1, int(en1)) poke(m.io.in0, i) - poke(m.io.in1, i+1) + poke(m.io.in1, i + 1) step(1) - expect(m.io.out, if(en0) i else if(en1) i+1 else 0) + expect(m.io.out, if(en0) i else if(en1) i + 1 else 0) } } @@ -144,10 +144,15 @@ class WhenSuite extends TestSuite { when( io.en ) { val sub = Module(new Submodule) io.out := sub.io.out + // The following generates a warning when it can't find 'en' in sub.io io <> sub.io /* connect only io.in to sub.io.in */ } } + def noWerror(srcArgs: Array[String]): Array[String] = { + srcArgs.filterNot(_ == "--wError") + } + class SubmoduleInWhenBlockTests(m: SubmoduleInWhenBlock) extends Tester(m) { List(false,true,false,true,false,false,false,true).zipWithIndex.map { case (en, i) => @@ -158,7 +163,7 @@ class WhenSuite extends TestSuite { } } - launchCppTester((m: SubmoduleInWhenBlock) => new SubmoduleInWhenBlockTests(m)) + launchCppTester({(m: SubmoduleInWhenBlock) => new SubmoduleInWhenBlockTests(m)}, Some(noWerror _)) } // Unless statement with elsewhen and otherwise clause @@ -232,7 +237,7 @@ class WhenSuite extends TestSuite { io.out := Bool(false) switch(io.in) { is(UInt(0)) { io.out := Bool(true) } - is(Bits("b???1")) { io.out := Bool(true) } + is(BitPat("b???1")) { io.out := Bool(true) } } } diff --git a/src/test/scala/ZeroWidthTest.scala b/src/test/scala/ZeroWidthTest.scala index be7f7ef7..514acd42 100644 --- a/src/test/scala/ZeroWidthTest.scala +++ b/src/test/scala/ZeroWidthTest.scala @@ -1,5 +1,5 @@ /* - Copyright (c) 2011, 2012, 2013, 2014 The Regents of the University of + Copyright (c) 2011 - 2016 The Regents of the University of California (Regents). All Rights Reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: @@ -34,6 +34,8 @@ import org.junit.Before import org.junit.BeforeClass import org.junit.Test import org.junit.Ignore +import scala.collection.immutable.HashMap +import scala.collection.mutable.ArrayBuffer import Chisel._ @@ -60,6 +62,18 @@ class ZeroWidthTest extends TestSuite { "--targetDir", dir.getPath.toString() ) + def filterArgs(args: Array[String], amap: HashMap[String, String]): Array[String] = { + val newArgs = ArrayBuffer[String]() + for (arg <- args) { + if (amap.contains(arg)) { + newArgs += amap(arg) + } else { + newArgs += arg + } + } + newArgs.toArray + } + @Before override def initialize() { super.initialize() // Enable W0W support @@ -68,23 +82,35 @@ class ZeroWidthTest extends TestSuite { /** Generate a zero-width wire (explicitly) */ @Test def testImplicitZeroWidth() { - val res = UInt(0,0) - assertTrue( res.getWidth == 0 ) - assertTrue( res.litOf.value == 0 ) + class Dummy extends Module { + val io = UInt(INPUT, 0) + val res = UInt(0,0) + assertTrue( res.getWidth == 0 ) + assertTrue( res.litValue() == 0 ) + } + val dummyInst = Module(new Dummy) } /** Generate a zero-width wire from a '>>' */ @Test def testRSHZeroWidth() { - val res = UInt(3,2) >> UInt(2) - assertTrue( res.getWidth == 0 ) - assertTrue( res.litOf.value == 0 ) + class Dummy extends Module { + val io = UInt(INPUT, 0) + val res = UInt(3,2) >> UInt(2) + assertTrue( res.getWidth == 0 ) + assertTrue( res.litValue() == 0 ) + } + val dummyInst = Module(new Dummy) } /** Generate a zero-width wire from an extraction. */ @Test def testExtractZeroWidth() { - val res = UInt(3)((0, 1)) - assertTrue( res.getWidth == 0 ) - assertTrue( res.litOf.value == 0 ) + class Dummy extends Module { + val io = UInt(INPUT, 0) + val res = UInt(3)((0, 1)) + assertTrue( res.getWidth == 0 ) + assertTrue( res.litValue() == 0 ) + } + val dummyInst = Module(new Dummy) } @Test def testOperators() { @@ -172,8 +198,8 @@ class ZeroWidthTest extends TestSuite { // ===(b: UInt): Bool val v = io.x === io.y - // != (b: UInt): Bool - val w = io.x != io.y + // =/= (b: UInt): Bool + val w = io.x =/= io.y // > (b: UInt): Bool val x = io.x > io.y @@ -271,7 +297,7 @@ class ZeroWidthTest extends TestSuite { assertFile("ZeroWidthTest_RemUZ_1." + backend) } - /** Multiply an signed zero-width number by an unsigned number */ + /** Multiply a signed zero-width number by an unsigned number */ @Test def testMulZU() { println("\ntestMulZU ...") class MulZU extends Module { @@ -286,6 +312,33 @@ class ZeroWidthTest extends TestSuite { assertFile("ZeroWidthTest_MulZU_1." + backend) } + /** Multiply an unsigned zero-width number by a signed number. */ + @Test def testMulZS() { + println("\ntestMulZS ...") + class MulZS extends Module { + val io = new Bundle { + val x = UInt(INPUT, 0) + val y = SInt(INPUT, 32) + val z = SInt(OUTPUT) + } + io.z := io.x * io.y + } + class MulZSTester(m: MulZS) extends Tester(m) { + poke(m.io.y, 42) + step(1) + expect(m.io.z, 42) + } + // Replace whatever backend we're using with verilog. + if (true) { + chiselMain(testArgs, () => Module(new MulZS())) + assertFile("ZeroWidthTest_MulZS_1." + backend) + } else { + val replaceArgs = HashMap[String, String]((backend, "c")) + val testerArgs = Array("--genHarness", "--compile", "--test") + chiselMainTest(filterArgs(testArgs, replaceArgs) ++ testerArgs, () => Module(new MulZS())) {m => new MulZSTester(m)} + } + } + /** Divide a signed zero-width number by an unsigned number */ @Test def testDivZU() { println("\ntestDivZU ...") @@ -317,7 +370,7 @@ class ZeroWidthTest extends TestSuite { } /** Concatenate two nodes X and Y (zero-width) in a node Z such that - Z[0..wx+wy] = X[0..wx] :: Y[0..wy]. */ + Z[0..wx + wy] = X[0..wx] :: Y[0..wy]. */ @Test def testCatCompW0W() { println("\ntestCat ...") class CatCompW0W extends Module { @@ -438,7 +491,7 @@ class ZeroWidthTest extends TestSuite { chiselMain(testArgs, () => Module(new MuxComp())) } - /** Reverse produced many width warning messages. + /** Reverse produced many width warning messages. */ @Test def testReverseNoisyWidth() { println("\ntesttestReverseNoisyWidth ...") @@ -451,7 +504,7 @@ class ZeroWidthTest extends TestSuite { } chiselMain(testArgs, () => Module(new ReverseNoisyWidth())) - assertTrue(ChiselError.ChiselErrors.isEmpty); + assertTrue(ChiselError.isEmpty); } /** Issue #335 @@ -462,16 +515,43 @@ class ZeroWidthTest extends TestSuite { @Test def testUnRefOutNullPointer() { println("\ntestUnRefOutNullPointer ...") class FloatOutModule extends Module { - + val io = new Bundle { val i_value = UInt(INPUT, width = 64) val i_valid = Bool(INPUT) val o_value = UInt(OUTPUT, width = 64) } - + when ( io.i_valid ) { io.o_value := io.i_value } } } + + /** Issue 439 + * Chisel somehow finds a way to build negative (actually zero) width wires. + */ + @Test def testZeroWidthForceMatching { + println("\ntestZeroWidthForceMatching ...") + class ZeroWidthForceMatching extends Module { + val io = UInt(OUTPUT, 1) + io := UInt(1, 1) + io := UInt(width = 0) + } + + class ZeroWidthForceMatchingTester(c: ZeroWidthForceMatching) extends Tester(c) { + assertTrue(c.io.getWidth == 1) + expect(c.io, 0) + } + if (true) { + // Replace whatever backend we're using with verilog. + val replaceArgs = HashMap[String, String]((backend, "v")) + chiselMain(filterArgs(testArgs, replaceArgs) , () => Module(new ZeroWidthForceMatching())) + assertFile("ZeroWidthTest_ZeroWidthForceMatching_1." + "v") + } else { + val replaceArgs = HashMap[String, String]((backend, "c")) + val testerArgs = Array("--genHarness", "--compile", "--test") + chiselMainTest(filterArgs(testArgs, replaceArgs) ++ testerArgs, () => Module(new ZeroWidthForceMatching())) {m => new ZeroWidthForceMatchingTester(m)} + } + } } diff --git a/www/BSD_licence.html b/www/BSD_licence.html deleted file mode 100644 index bb73490c..00000000 --- a/www/BSD_licence.html +++ /dev/null @@ -1,40 +0,0 @@ - - - Chisel licence terms - - -

- Copyright © 2011, 2012, 2013 The Regents of the University of - California (Regents). All Rights Reserved. Redistribution and use in - source and binary forms, with or without modification, are permitted - provided that the following conditions are met: -

    -
  • Redistributions of source code must retain the above - copyright notice, this list of conditions and the following - two paragraphs of disclaimer. -
  • Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the following - two paragraphs of disclaimer in the documentation and/or other materials provided with the distribution. -
  • Neither the name of the Regents nor the names of its contributors - may be used to endorse or promote products derived from this - software without specific prior written permission. -
-

- -

IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, - SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, - ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF - REGENTS HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -

- -

- REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - A PARTICULAR PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF - ANY, PROVIDED HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION - TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR - MODIFICATIONS. -

- - - diff --git a/www/Makefile b/www/Makefile deleted file mode 100644 index b8e8030c..00000000 --- a/www/Makefile +++ /dev/null @@ -1,14 +0,0 @@ - -host=psi.millennium.berkeley.edu -path=/project/eecs/parlab/www/chisel/data -parlaball_grpid=683 - -install: - rsync -rlvzC --delete-after ./* $(host):$(path)/ - -ssh $(host) chgrp -fR $(parlaball_grpid) $(path)/\* - -ssh $(host) chmod -fR 775 $(path)/\* - -clean: - rm -f documentation.html download.html faq.html index.html - - diff --git a/www/assets/css/bootstrap-responsive.css b/www/assets/css/bootstrap-responsive.css deleted file mode 100755 index 06e55c0b..00000000 --- a/www/assets/css/bootstrap-responsive.css +++ /dev/null @@ -1,815 +0,0 @@ -/*! - * Bootstrap Responsive v2.0.4 - * - * Copyright 2012 Twitter, Inc - * Licensed under the Apache License v2.0 - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Designed and built with all the love in the world @twitter by @mdo and @fat. - */ - -.clearfix { - *zoom: 1; -} - -.clearfix:before, -.clearfix:after { - display: table; - content: ""; -} - -.clearfix:after { - clear: both; -} - -.hide-text { - font: 0/0 a; - color: transparent; - text-shadow: none; - background-color: transparent; - border: 0; -} - -.input-block-level { - display: block; - width: 100%; - min-height: 28px; - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - -ms-box-sizing: border-box; - box-sizing: border-box; -} - -.hidden { - display: none; - visibility: hidden; -} - -.visible-phone { - display: none !important; -} - -.visible-tablet { - display: none !important; -} - -.hidden-desktop { - display: none !important; -} - -@media (max-width: 767px) { - .visible-phone { - display: inherit !important; - } - .hidden-phone { - display: none !important; - } - .hidden-desktop { - display: inherit !important; - } - .visible-desktop { - display: none !important; - } -} - -@media (min-width: 768px) and (max-width: 979px) { - .visible-tablet { - display: inherit !important; - } - .hidden-tablet { - display: none !important; - } - .hidden-desktop { - display: inherit !important; - } - .visible-desktop { - display: none !important ; - } -} - -@media (max-width: 480px) { - .nav-collapse { - -webkit-transform: translate3d(0, 0, 0); - } - .page-header h1 small { - display: block; - line-height: 18px; - } - input[type="checkbox"], - input[type="radio"] { - border: 1px solid #ccc; - } - .form-horizontal .control-group > label { - float: none; - width: auto; - padding-top: 0; - text-align: left; - } - .form-horizontal .controls { - margin-left: 0; - } - .form-horizontal .control-list { - padding-top: 0; - } - .form-horizontal .form-actions { - padding-right: 10px; - padding-left: 10px; - } - .modal { - position: absolute; - top: 10px; - right: 10px; - left: 10px; - width: auto; - margin: 0; - } - .modal.fade.in { - top: auto; - } - .modal-header .close { - padding: 10px; - margin: -10px; - } - .carousel-caption { - position: static; - } -} - -@media (max-width: 767px) { - body { - padding-right: 20px; - padding-left: 20px; - } - .navbar-fixed-top, - .navbar-fixed-bottom { - margin-right: -20px; - margin-left: -20px; - } - .container-fluid { - padding: 0; - } - .dl-horizontal dt { - float: none; - width: auto; - clear: none; - text-align: left; - } - .dl-horizontal dd { - margin-left: 0; - } - .container { - width: auto; - } - .row-fluid { - width: 100%; - } - .row, - .thumbnails { - margin-left: 0; - } - [class*="span"], - .row-fluid [class*="span"] { - display: block; - float: none; - width: auto; - margin-left: 0; - } - .input-large, - .input-xlarge, - .input-xxlarge, - input[class*="span"], - select[class*="span"], - textarea[class*="span"], - .uneditable-input { - display: block; - width: 100%; - min-height: 28px; - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - -ms-box-sizing: border-box; - box-sizing: border-box; - } - .input-prepend input, - .input-append input, - .input-prepend input[class*="span"], - .input-append input[class*="span"] { - display: inline-block; - width: auto; - } -} - -@media (min-width: 768px) and (max-width: 979px) { - .row { - margin-left: -20px; - *zoom: 1; - } - .row:before, - .row:after { - display: table; - content: ""; - } - .row:after { - clear: both; - } - [class*="span"] { - float: left; - margin-left: 20px; - } - .container, - .navbar-fixed-top .container, - .navbar-fixed-bottom .container { - width: 724px; - } - .span12 { - width: 724px; - } - .span11 { - width: 662px; - } - .span10 { - width: 600px; - } - .span9 { - width: 538px; - } - .span8 { - width: 476px; - } - .span7 { - width: 414px; - } - .span6 { - width: 352px; - } - .span5 { - width: 290px; - } - .span4 { - width: 228px; - } - .span3 { - width: 166px; - } - .span2 { - width: 104px; - } - .span1 { - width: 42px; - } - .offset12 { - margin-left: 764px; - } - .offset11 { - margin-left: 702px; - } - .offset10 { - margin-left: 640px; - } - .offset9 { - margin-left: 578px; - } - .offset8 { - margin-left: 516px; - } - .offset7 { - margin-left: 454px; - } - .offset6 { - margin-left: 392px; - } - .offset5 { - margin-left: 330px; - } - .offset4 { - margin-left: 268px; - } - .offset3 { - margin-left: 206px; - } - .offset2 { - margin-left: 144px; - } - .offset1 { - margin-left: 82px; - } - .row-fluid { - width: 100%; - *zoom: 1; - } - .row-fluid:before, - .row-fluid:after { - display: table; - content: ""; - } - .row-fluid:after { - clear: both; - } - .row-fluid [class*="span"] { - display: block; - float: left; - width: 100%; - min-height: 28px; - margin-left: 2.762430939%; - *margin-left: 2.709239449638298%; - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - -ms-box-sizing: border-box; - box-sizing: border-box; - } - .row-fluid [class*="span"]:first-child { - margin-left: 0; - } - .row-fluid .span12 { - width: 99.999999993%; - *width: 99.9468085036383%; - } - .row-fluid .span11 { - width: 91.436464082%; - *width: 91.38327259263829%; - } - .row-fluid .span10 { - width: 82.87292817100001%; - *width: 82.8197366816383%; - } - .row-fluid .span9 { - width: 74.30939226%; - *width: 74.25620077063829%; - } - .row-fluid .span8 { - width: 65.74585634900001%; - *width: 65.6926648596383%; - } - .row-fluid .span7 { - width: 57.182320438000005%; - *width: 57.129128948638304%; - } - .row-fluid .span6 { - width: 48.618784527%; - *width: 48.5655930376383%; - } - .row-fluid .span5 { - width: 40.055248616%; - *width: 40.0020571266383%; - } - .row-fluid .span4 { - width: 31.491712705%; - *width: 31.4385212156383%; - } - .row-fluid .span3 { - width: 22.928176794%; - *width: 22.874985304638297%; - } - .row-fluid .span2 { - width: 14.364640883%; - *width: 14.311449393638298%; - } - .row-fluid .span1 { - width: 5.801104972%; - *width: 5.747913482638298%; - } - input, - textarea, - .uneditable-input { - margin-left: 0; - } - input.span12, - textarea.span12, - .uneditable-input.span12 { - width: 714px; - } - input.span11, - textarea.span11, - .uneditable-input.span11 { - width: 652px; - } - input.span10, - textarea.span10, - .uneditable-input.span10 { - width: 590px; - } - input.span9, - textarea.span9, - .uneditable-input.span9 { - width: 528px; - } - input.span8, - textarea.span8, - .uneditable-input.span8 { - width: 466px; - } - input.span7, - textarea.span7, - .uneditable-input.span7 { - width: 404px; - } - input.span6, - textarea.span6, - .uneditable-input.span6 { - width: 342px; - } - input.span5, - textarea.span5, - .uneditable-input.span5 { - width: 280px; - } - input.span4, - textarea.span4, - .uneditable-input.span4 { - width: 218px; - } - input.span3, - textarea.span3, - .uneditable-input.span3 { - width: 156px; - } - input.span2, - textarea.span2, - .uneditable-input.span2 { - width: 94px; - } - input.span1, - textarea.span1, - .uneditable-input.span1 { - width: 32px; - } -} - -@media (min-width: 1200px) { - .row { - margin-left: -30px; - *zoom: 1; - } - .row:before, - .row:after { - display: table; - content: ""; - } - .row:after { - clear: both; - } - [class*="span"] { - float: left; - margin-left: 30px; - } - .container, - .navbar-fixed-top .container, - .navbar-fixed-bottom .container { - width: 1170px; - } - .span12 { - width: 1170px; - } - .span11 { - width: 1070px; - } - .span10 { - width: 970px; - } - .span9 { - width: 870px; - } - .span8 { - width: 770px; - } - .span7 { - width: 670px; - } - .span6 { - width: 570px; - } - .span5 { - width: 470px; - } - .span4 { - width: 370px; - } - .span3 { - width: 270px; - } - .span2 { - width: 170px; - } - .span1 { - width: 70px; - } - .offset12 { - margin-left: 1230px; - } - .offset11 { - margin-left: 1130px; - } - .offset10 { - margin-left: 1030px; - } - .offset9 { - margin-left: 930px; - } - .offset8 { - margin-left: 830px; - } - .offset7 { - margin-left: 730px; - } - .offset6 { - margin-left: 630px; - } - .offset5 { - margin-left: 530px; - } - .offset4 { - margin-left: 430px; - } - .offset3 { - margin-left: 330px; - } - .offset2 { - margin-left: 230px; - } - .offset1 { - margin-left: 130px; - } - .row-fluid { - width: 100%; - *zoom: 1; - } - .row-fluid:before, - .row-fluid:after { - display: table; - content: ""; - } - .row-fluid:after { - clear: both; - } - .row-fluid [class*="span"] { - display: block; - float: left; - width: 100%; - min-height: 28px; - margin-left: 2.564102564%; - *margin-left: 2.510911074638298%; - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - -ms-box-sizing: border-box; - box-sizing: border-box; - } - .row-fluid [class*="span"]:first-child { - margin-left: 0; - } - .row-fluid .span12 { - width: 100%; - *width: 99.94680851063829%; - } - .row-fluid .span11 { - width: 91.45299145300001%; - *width: 91.3997999636383%; - } - .row-fluid .span10 { - width: 82.905982906%; - *width: 82.8527914166383%; - } - .row-fluid .span9 { - width: 74.358974359%; - *width: 74.30578286963829%; - } - .row-fluid .span8 { - width: 65.81196581200001%; - *width: 65.7587743226383%; - } - .row-fluid .span7 { - width: 57.264957265%; - *width: 57.2117657756383%; - } - .row-fluid .span6 { - width: 48.717948718%; - *width: 48.6647572286383%; - } - .row-fluid .span5 { - width: 40.170940171000005%; - *width: 40.117748681638304%; - } - .row-fluid .span4 { - width: 31.623931624%; - *width: 31.5707401346383%; - } - .row-fluid .span3 { - width: 23.076923077%; - *width: 23.0237315876383%; - } - .row-fluid .span2 { - width: 14.529914530000001%; - *width: 14.4767230406383%; - } - .row-fluid .span1 { - width: 5.982905983%; - *width: 5.929714493638298%; - } - input, - textarea, - .uneditable-input { - margin-left: 0; - } - input.span12, - textarea.span12, - .uneditable-input.span12 { - width: 1160px; - } - input.span11, - textarea.span11, - .uneditable-input.span11 { - width: 1060px; - } - input.span10, - textarea.span10, - .uneditable-input.span10 { - width: 960px; - } - input.span9, - textarea.span9, - .uneditable-input.span9 { - width: 860px; - } - input.span8, - textarea.span8, - .uneditable-input.span8 { - width: 760px; - } - input.span7, - textarea.span7, - .uneditable-input.span7 { - width: 660px; - } - input.span6, - textarea.span6, - .uneditable-input.span6 { - width: 560px; - } - input.span5, - textarea.span5, - .uneditable-input.span5 { - width: 460px; - } - input.span4, - textarea.span4, - .uneditable-input.span4 { - width: 360px; - } - input.span3, - textarea.span3, - .uneditable-input.span3 { - width: 260px; - } - input.span2, - textarea.span2, - .uneditable-input.span2 { - width: 160px; - } - input.span1, - textarea.span1, - .uneditable-input.span1 { - width: 60px; - } - .thumbnails { - margin-left: -30px; - } - .thumbnails > li { - margin-left: 30px; - } - .row-fluid .thumbnails { - margin-left: 0; - } -} - -@media (max-width: 979px) { - body { - padding-top: 0; - } - .navbar-fixed-top, - .navbar-fixed-bottom { - position: static; - } - .navbar-fixed-top { - margin-bottom: 18px; - } - .navbar-fixed-bottom { - margin-top: 18px; - } - .navbar-fixed-top .navbar-inner, - .navbar-fixed-bottom .navbar-inner { - padding: 5px; - } - .navbar .container { - width: auto; - padding: 0; - } - .navbar .brand { - padding-right: 10px; - padding-left: 10px; - margin: 0 0 0 -5px; - } - .nav-collapse { - clear: both; - } - .nav-collapse .nav { - float: none; - margin: 0 0 9px; - } - .nav-collapse .nav > li { - float: none; - } - .nav-collapse .nav > li > a { - margin-bottom: 2px; - } - .nav-collapse .nav > .divider-vertical { - display: none; - } - .nav-collapse .nav .nav-header { - color: #999999; - text-shadow: none; - } - .nav-collapse .nav > li > a, - .nav-collapse .dropdown-menu a { - padding: 6px 15px; - font-weight: bold; - color: #999999; - -webkit-border-radius: 3px; - -moz-border-radius: 3px; - border-radius: 3px; - } - .nav-collapse .btn { - padding: 4px 10px 4px; - font-weight: normal; - -webkit-border-radius: 4px; - -moz-border-radius: 4px; - border-radius: 4px; - } - .nav-collapse .dropdown-menu li + li a { - margin-bottom: 2px; - } - .nav-collapse .nav > li > a:hover, - .nav-collapse .dropdown-menu a:hover { - background-color: #222222; - } - .nav-collapse.in .btn-group { - padding: 0; - margin-top: 5px; - } - .nav-collapse .dropdown-menu { - position: static; - top: auto; - left: auto; - display: block; - float: none; - max-width: none; - padding: 0; - margin: 0 15px; - background-color: transparent; - border: none; - -webkit-border-radius: 0; - -moz-border-radius: 0; - border-radius: 0; - -webkit-box-shadow: none; - -moz-box-shadow: none; - box-shadow: none; - } - .nav-collapse .dropdown-menu:before, - .nav-collapse .dropdown-menu:after { - display: none; - } - .nav-collapse .dropdown-menu .divider { - display: none; - } - .nav-collapse .navbar-form, - .nav-collapse .navbar-search { - float: none; - padding: 9px 15px; - margin: 9px 0; - border-top: 1px solid #222222; - border-bottom: 1px solid #222222; - -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1); - -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1); - box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1); - } - .navbar .nav-collapse .nav.pull-right { - float: none; - margin-left: 0; - } - .nav-collapse, - .nav-collapse.collapse { - height: 0; - overflow: hidden; - } - .navbar .btn-navbar { - display: block; - } - .navbar-static .navbar-inner { - padding-right: 10px; - padding-left: 10px; - } -} - -@media (min-width: 980px) { - .nav-collapse.collapse { - height: auto !important; - overflow: visible !important; - } -} diff --git a/www/assets/css/bootstrap-responsive.min.css b/www/assets/css/bootstrap-responsive.min.css deleted file mode 100755 index 1f55036a..00000000 --- a/www/assets/css/bootstrap-responsive.min.css +++ /dev/null @@ -1,9 +0,0 @@ -/*! - * Bootstrap Responsive v2.0.4 - * - * Copyright 2012 Twitter, Inc - * Licensed under the Apache License v2.0 - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Designed and built with all the love in the world @twitter by @mdo and @fat. - */.clearfix{*zoom:1}.clearfix:before,.clearfix:after{display:table;content:""}.clearfix:after{clear:both}.hide-text{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.input-block-level{display:block;width:100%;min-height:28px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;-ms-box-sizing:border-box;box-sizing:border-box}.hidden{display:none;visibility:hidden}.visible-phone{display:none!important}.visible-tablet{display:none!important}.hidden-desktop{display:none!important}@media(max-width:767px){.visible-phone{display:inherit!important}.hidden-phone{display:none!important}.hidden-desktop{display:inherit!important}.visible-desktop{display:none!important}}@media(min-width:768px) and (max-width:979px){.visible-tablet{display:inherit!important}.hidden-tablet{display:none!important}.hidden-desktop{display:inherit!important}.visible-desktop{display:none!important}}@media(max-width:480px){.nav-collapse{-webkit-transform:translate3d(0,0,0)}.page-header h1 small{display:block;line-height:18px}input[type="checkbox"],input[type="radio"]{border:1px solid #ccc}.form-horizontal .control-group>label{float:none;width:auto;padding-top:0;text-align:left}.form-horizontal .controls{margin-left:0}.form-horizontal .control-list{padding-top:0}.form-horizontal .form-actions{padding-right:10px;padding-left:10px}.modal{position:absolute;top:10px;right:10px;left:10px;width:auto;margin:0}.modal.fade.in{top:auto}.modal-header .close{padding:10px;margin:-10px}.carousel-caption{position:static}}@media(max-width:767px){body{padding-right:20px;padding-left:20px}.navbar-fixed-top,.navbar-fixed-bottom{margin-right:-20px;margin-left:-20px}.container-fluid{padding:0}.dl-horizontal dt{float:none;width:auto;clear:none;text-align:left}.dl-horizontal dd{margin-left:0}.container{width:auto}.row-fluid{width:100%}.row,.thumbnails{margin-left:0}[class*="span"],.row-fluid [class*="span"]{display:block;float:none;width:auto;margin-left:0}.input-large,.input-xlarge,.input-xxlarge,input[class*="span"],select[class*="span"],textarea[class*="span"],.uneditable-input{display:block;width:100%;min-height:28px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;-ms-box-sizing:border-box;box-sizing:border-box}.input-prepend input,.input-append input,.input-prepend input[class*="span"],.input-append input[class*="span"]{display:inline-block;width:auto}}@media(min-width:768px) and (max-width:979px){.row{margin-left:-20px;*zoom:1}.row:before,.row:after{display:table;content:""}.row:after{clear:both}[class*="span"]{float:left;margin-left:20px}.container,.navbar-fixed-top .container,.navbar-fixed-bottom .container{width:724px}.span12{width:724px}.span11{width:662px}.span10{width:600px}.span9{width:538px}.span8{width:476px}.span7{width:414px}.span6{width:352px}.span5{width:290px}.span4{width:228px}.span3{width:166px}.span2{width:104px}.span1{width:42px}.offset12{margin-left:764px}.offset11{margin-left:702px}.offset10{margin-left:640px}.offset9{margin-left:578px}.offset8{margin-left:516px}.offset7{margin-left:454px}.offset6{margin-left:392px}.offset5{margin-left:330px}.offset4{margin-left:268px}.offset3{margin-left:206px}.offset2{margin-left:144px}.offset1{margin-left:82px}.row-fluid{width:100%;*zoom:1}.row-fluid:before,.row-fluid:after{display:table;content:""}.row-fluid:after{clear:both}.row-fluid [class*="span"]{display:block;float:left;width:100%;min-height:28px;margin-left:2.762430939%;*margin-left:2.709239449638298%;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;-ms-box-sizing:border-box;box-sizing:border-box}.row-fluid [class*="span"]:first-child{margin-left:0}.row-fluid .span12{width:99.999999993%;*width:99.9468085036383%}.row-fluid .span11{width:91.436464082%;*width:91.38327259263829%}.row-fluid .span10{width:82.87292817100001%;*width:82.8197366816383%}.row-fluid .span9{width:74.30939226%;*width:74.25620077063829%}.row-fluid .span8{width:65.74585634900001%;*width:65.6926648596383%}.row-fluid .span7{width:57.182320438000005%;*width:57.129128948638304%}.row-fluid .span6{width:48.618784527%;*width:48.5655930376383%}.row-fluid .span5{width:40.055248616%;*width:40.0020571266383%}.row-fluid .span4{width:31.491712705%;*width:31.4385212156383%}.row-fluid .span3{width:22.928176794%;*width:22.874985304638297%}.row-fluid .span2{width:14.364640883%;*width:14.311449393638298%}.row-fluid .span1{width:5.801104972%;*width:5.747913482638298%}input,textarea,.uneditable-input{margin-left:0}input.span12,textarea.span12,.uneditable-input.span12{width:714px}input.span11,textarea.span11,.uneditable-input.span11{width:652px}input.span10,textarea.span10,.uneditable-input.span10{width:590px}input.span9,textarea.span9,.uneditable-input.span9{width:528px}input.span8,textarea.span8,.uneditable-input.span8{width:466px}input.span7,textarea.span7,.uneditable-input.span7{width:404px}input.span6,textarea.span6,.uneditable-input.span6{width:342px}input.span5,textarea.span5,.uneditable-input.span5{width:280px}input.span4,textarea.span4,.uneditable-input.span4{width:218px}input.span3,textarea.span3,.uneditable-input.span3{width:156px}input.span2,textarea.span2,.uneditable-input.span2{width:94px}input.span1,textarea.span1,.uneditable-input.span1{width:32px}}@media(min-width:1200px){.row{margin-left:-30px;*zoom:1}.row:before,.row:after{display:table;content:""}.row:after{clear:both}[class*="span"]{float:left;margin-left:30px}.container,.navbar-fixed-top .container,.navbar-fixed-bottom .container{width:1170px}.span12{width:1170px}.span11{width:1070px}.span10{width:970px}.span9{width:870px}.span8{width:770px}.span7{width:670px}.span6{width:570px}.span5{width:470px}.span4{width:370px}.span3{width:270px}.span2{width:170px}.span1{width:70px}.offset12{margin-left:1230px}.offset11{margin-left:1130px}.offset10{margin-left:1030px}.offset9{margin-left:930px}.offset8{margin-left:830px}.offset7{margin-left:730px}.offset6{margin-left:630px}.offset5{margin-left:530px}.offset4{margin-left:430px}.offset3{margin-left:330px}.offset2{margin-left:230px}.offset1{margin-left:130px}.row-fluid{width:100%;*zoom:1}.row-fluid:before,.row-fluid:after{display:table;content:""}.row-fluid:after{clear:both}.row-fluid [class*="span"]{display:block;float:left;width:100%;min-height:28px;margin-left:2.564102564%;*margin-left:2.510911074638298%;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;-ms-box-sizing:border-box;box-sizing:border-box}.row-fluid [class*="span"]:first-child{margin-left:0}.row-fluid .span12{width:100%;*width:99.94680851063829%}.row-fluid .span11{width:91.45299145300001%;*width:91.3997999636383%}.row-fluid .span10{width:82.905982906%;*width:82.8527914166383%}.row-fluid .span9{width:74.358974359%;*width:74.30578286963829%}.row-fluid .span8{width:65.81196581200001%;*width:65.7587743226383%}.row-fluid .span7{width:57.264957265%;*width:57.2117657756383%}.row-fluid .span6{width:48.717948718%;*width:48.6647572286383%}.row-fluid .span5{width:40.170940171000005%;*width:40.117748681638304%}.row-fluid .span4{width:31.623931624%;*width:31.5707401346383%}.row-fluid .span3{width:23.076923077%;*width:23.0237315876383%}.row-fluid .span2{width:14.529914530000001%;*width:14.4767230406383%}.row-fluid .span1{width:5.982905983%;*width:5.929714493638298%}input,textarea,.uneditable-input{margin-left:0}input.span12,textarea.span12,.uneditable-input.span12{width:1160px}input.span11,textarea.span11,.uneditable-input.span11{width:1060px}input.span10,textarea.span10,.uneditable-input.span10{width:960px}input.span9,textarea.span9,.uneditable-input.span9{width:860px}input.span8,textarea.span8,.uneditable-input.span8{width:760px}input.span7,textarea.span7,.uneditable-input.span7{width:660px}input.span6,textarea.span6,.uneditable-input.span6{width:560px}input.span5,textarea.span5,.uneditable-input.span5{width:460px}input.span4,textarea.span4,.uneditable-input.span4{width:360px}input.span3,textarea.span3,.uneditable-input.span3{width:260px}input.span2,textarea.span2,.uneditable-input.span2{width:160px}input.span1,textarea.span1,.uneditable-input.span1{width:60px}.thumbnails{margin-left:-30px}.thumbnails>li{margin-left:30px}.row-fluid .thumbnails{margin-left:0}}@media(max-width:979px){body{padding-top:0}.navbar-fixed-top,.navbar-fixed-bottom{position:static}.navbar-fixed-top{margin-bottom:18px}.navbar-fixed-bottom{margin-top:18px}.navbar-fixed-top .navbar-inner,.navbar-fixed-bottom .navbar-inner{padding:5px}.navbar .container{width:auto;padding:0}.navbar .brand{padding-right:10px;padding-left:10px;margin:0 0 0 -5px}.nav-collapse{clear:both}.nav-collapse .nav{float:none;margin:0 0 9px}.nav-collapse .nav>li{float:none}.nav-collapse .nav>li>a{margin-bottom:2px}.nav-collapse .nav>.divider-vertical{display:none}.nav-collapse .nav .nav-header{color:#999;text-shadow:none}.nav-collapse .nav>li>a,.nav-collapse .dropdown-menu a{padding:6px 15px;font-weight:bold;color:#999;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px}.nav-collapse .btn{padding:4px 10px 4px;font-weight:normal;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.nav-collapse .dropdown-menu li+li a{margin-bottom:2px}.nav-collapse .nav>li>a:hover,.nav-collapse .dropdown-menu a:hover{background-color:#222}.nav-collapse.in .btn-group{padding:0;margin-top:5px}.nav-collapse .dropdown-menu{position:static;top:auto;left:auto;display:block;float:none;max-width:none;padding:0;margin:0 15px;background-color:transparent;border:0;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none}.nav-collapse .dropdown-menu:before,.nav-collapse .dropdown-menu:after{display:none}.nav-collapse .dropdown-menu .divider{display:none}.nav-collapse .navbar-form,.nav-collapse .navbar-search{float:none;padding:9px 15px;margin:9px 0;border-top:1px solid #222;border-bottom:1px solid #222;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.1);-moz-box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.1);box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.1)}.navbar .nav-collapse .nav.pull-right{float:none;margin-left:0}.nav-collapse,.nav-collapse.collapse{height:0;overflow:hidden}.navbar .btn-navbar{display:block}.navbar-static .navbar-inner{padding-right:10px;padding-left:10px}}@media(min-width:980px){.nav-collapse.collapse{height:auto!important;overflow:visible!important}} diff --git a/www/assets/css/bootstrap.css b/www/assets/css/bootstrap.css deleted file mode 100755 index 7d01b8df..00000000 --- a/www/assets/css/bootstrap.css +++ /dev/null @@ -1,4983 +0,0 @@ -/*! - * Bootstrap v2.0.4 - * - * Copyright 2012 Twitter, Inc - * Licensed under the Apache License v2.0 - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Designed and built with all the love in the world @twitter by @mdo and @fat. - */ - -article, -aside, -details, -figcaption, -figure, -footer, -header, -hgroup, -nav, -section { - display: block; -} - -audio, -canvas, -video { - display: inline-block; - *display: inline; - *zoom: 1; -} - -audio:not([controls]) { - display: none; -} - -html { - font-size: 100%; - -webkit-text-size-adjust: 100%; - -ms-text-size-adjust: 100%; -} - -a:focus { - outline: thin dotted #333; - outline: 5px auto -webkit-focus-ring-color; - outline-offset: -2px; -} - -a:hover, -a:active { - outline: 0; -} - -sub, -sup { - position: relative; - font-size: 75%; - line-height: 0; - vertical-align: baseline; -} - -sup { - top: -0.5em; -} - -sub { - bottom: -0.25em; -} - -img { - max-width: 100%; - vertical-align: middle; - border: 0; - -ms-interpolation-mode: bicubic; -} - -#map_canvas img { - max-width: none; -} - -button, -input, -select, -textarea { - margin: 0; - font-size: 100%; - vertical-align: middle; -} - -button, -input { - *overflow: visible; - line-height: normal; -} - -button::-moz-focus-inner, -input::-moz-focus-inner { - padding: 0; - border: 0; -} - -button, -input[type="button"], -input[type="reset"], -input[type="submit"] { - cursor: pointer; - -webkit-appearance: button; -} - -input[type="search"] { - -webkit-box-sizing: content-box; - -moz-box-sizing: content-box; - box-sizing: content-box; - -webkit-appearance: textfield; -} - -input[type="search"]::-webkit-search-decoration, -input[type="search"]::-webkit-search-cancel-button { - -webkit-appearance: none; -} - -textarea { - overflow: auto; - vertical-align: top; -} - -.clearfix { - *zoom: 1; -} - -.clearfix:before, -.clearfix:after { - display: table; - content: ""; -} - -.clearfix:after { - clear: both; -} - -.hide-text { - font: 0/0 a; - color: transparent; - text-shadow: none; - background-color: transparent; - border: 0; -} - -.input-block-level { - display: block; - width: 100%; - min-height: 28px; - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - -ms-box-sizing: border-box; - box-sizing: border-box; -} - -body { - margin: 0; - font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; - font-size: 16px; - line-height: 18px; - color: #333333; - background-color: #ffffff; -} - -a { - color: #0088cc; - text-decoration: none; -} - -a:hover { - color: #005580; - text-decoration: underline; -} - -.row { - margin-left: -20px; - *zoom: 1; -} - -.row:before, -.row:after { - display: table; - content: ""; -} - -.row:after { - clear: both; -} - -[class*="span"] { - float: left; - margin-left: 20px; -} - -.container, -.navbar-fixed-top .container, -.navbar-fixed-bottom .container { - width: 940px; -} - -.span12 { - width: 940px; -} - -.span11 { - width: 860px; -} - -.span10 { - width: 780px; -} - -.span9 { - width: 700px; -} - -.span8 { - width: 620px; -} - -.span7 { - width: 540px; -} - -.span6 { - width: 460px; -} - -.span5 { - width: 380px; -} - -.span4 { - width: 300px; -} - -.span3 { - width: 220px; -} - -.span2 { - width: 140px; -} - -.span1 { - width: 60px; -} - -.offset12 { - margin-left: 980px; -} - -.offset11 { - margin-left: 900px; -} - -.offset10 { - margin-left: 820px; -} - -.offset9 { - margin-left: 740px; -} - -.offset8 { - margin-left: 660px; -} - -.offset7 { - margin-left: 580px; -} - -.offset6 { - margin-left: 500px; -} - -.offset5 { - margin-left: 420px; -} - -.offset4 { - margin-left: 340px; -} - -.offset3 { - margin-left: 260px; -} - -.offset2 { - margin-left: 180px; -} - -.offset1 { - margin-left: 100px; -} - -.row-fluid { - width: 100%; - *zoom: 1; -} - -.row-fluid:before, -.row-fluid:after { - display: table; - content: ""; -} - -.row-fluid:after { - clear: both; -} - -.row-fluid [class*="span"] { - display: block; - float: left; - width: 100%; - min-height: 28px; - margin-left: 2.127659574%; - *margin-left: 2.0744680846382977%; - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - -ms-box-sizing: border-box; - box-sizing: border-box; -} - -.row-fluid [class*="span"]:first-child { - margin-left: 0; -} - -.row-fluid .span12 { - width: 99.99999998999999%; - *width: 99.94680850063828%; -} - -.row-fluid .span11 { - width: 91.489361693%; - *width: 91.4361702036383%; -} - -.row-fluid .span10 { - width: 82.97872339599999%; - *width: 82.92553190663828%; -} - -.row-fluid .span9 { - width: 74.468085099%; - *width: 74.4148936096383%; -} - -.row-fluid .span8 { - width: 65.95744680199999%; - *width: 65.90425531263828%; -} - -.row-fluid .span7 { - width: 57.446808505%; - *width: 57.3936170156383%; -} - -.row-fluid .span6 { - width: 48.93617020799999%; - *width: 48.88297871863829%; -} - -.row-fluid .span5 { - width: 40.425531911%; - *width: 40.3723404216383%; -} - -.row-fluid .span4 { - width: 31.914893614%; - *width: 31.8617021246383%; -} - -.row-fluid .span3 { - width: 23.404255317%; - *width: 23.3510638276383%; -} - -.row-fluid .span2 { - width: 14.89361702%; - *width: 14.8404255306383%; -} - -.row-fluid .span1 { - width: 6.382978723%; - *width: 6.329787233638298%; -} - -.container { - margin-right: auto; - margin-left: auto; - *zoom: 1; -} - -.container:before, -.container:after { - display: table; - content: ""; -} - -.container:after { - clear: both; -} - -.container-fluid { - padding-right: 20px; - padding-left: 20px; - *zoom: 1; -} - -.container-fluid:before, -.container-fluid:after { - display: table; - content: ""; -} - -.container-fluid:after { - clear: both; -} - -p { - margin: 0 0 9px; -} - -p small { - font-size: 11px; - color: #999999; -} - -.lead { - margin-bottom: 18px; - font-size: 20px; - font-weight: 200; - line-height: 27px; -} - -h1, -h2, -h3, -h4, -h5, -h6 { - margin: 0; - font-family: inherit; - font-weight: bold; - color: inherit; - text-rendering: optimizelegibility; -} - -h1 small, -h2 small, -h3 small, -h4 small, -h5 small, -h6 small { - font-weight: normal; - color: #999999; -} - -h1 { - font-size: 30px; - line-height: 36px; -} - -h1 small { - font-size: 18px; -} - -h2 { - font-size: 24px; - line-height: 36px; -} - -h2 small { - font-size: 18px; -} - -h3 { - font-size: 18px; - line-height: 27px; -} - -h3 small { - font-size: 14px; -} - -h4, -h5, -h6 { - line-height: 18px; -} - -h4 { - font-size: 14px; -} - -h4 small { - font-size: 12px; -} - -h5 { - font-size: 12px; -} - -h6 { - font-size: 11px; - color: #999999; - text-transform: uppercase; -} - -.page-header { - padding-bottom: 4px; - margin: 18px 0; - border-bottom: 2px solid #eeeeee; -} - -.page-header h1 { - line-height: 1; -} - -ul, -ol { - padding: 0; - margin: 0 0 9px 25px; -} - -ul ul, -ul ol, -ol ol, -ol ul { - margin-bottom: 0; -} - -ul { - list-style: disc; -} - -ol { - list-style: decimal; -} - -li { - line-height: 18px; -} - -ul.unstyled, -ol.unstyled { - margin-left: 0; - list-style: none; -} - -dl { - margin-bottom: 18px; -} - -dt, -dd { - line-height: 18px; -} - -dt { - font-weight: bold; - line-height: 17px; -} - -dd { - margin-left: 9px; -} - -.dl-horizontal dt { - float: left; - width: 120px; - overflow: hidden; - clear: left; - text-align: right; - text-overflow: ellipsis; - white-space: nowrap; -} - -.dl-horizontal dd { - margin-left: 130px; -} - -hr { - margin: 18px 0; - border: 0; - border-top: 1px solid #eeeeee; - border-bottom: 1px solid #ffffff; -} - -strong { - font-weight: bold; -} - -em { - font-style: italic; -} - -.muted { - color: #999999; -} - -abbr[title] { - cursor: help; - border-bottom: 1px dotted #999999; -} - -abbr.initialism { - font-size: 90%; - text-transform: uppercase; -} - -blockquote { - padding: 0 0 0 15px; - margin: 0 0 18px; - border-left: 5px solid #eeeeee; -} - -blockquote p { - margin-bottom: 0; - font-size: 16px; - font-weight: 300; - line-height: 22.5px; -} - -blockquote small { - display: block; - line-height: 18px; - color: #999999; -} - -blockquote small:before { - content: '\2014 \00A0'; -} - -blockquote.pull-right { - float: right; - padding-right: 15px; - padding-left: 0; - border-right: 5px solid #eeeeee; - border-left: 0; -} - -blockquote.pull-right p, -blockquote.pull-right small { - text-align: right; -} - -q:before, -q:after, -blockquote:before, -blockquote:after { - content: ""; -} - -address { - display: block; - margin-bottom: 18px; - font-style: normal; - line-height: 18px; -} - -small { - font-size: 100%; -} - -cite { - font-style: normal; -} - -code, -pre { - padding: 0 3px 2px; - font-family: Menlo, Monaco, Consolas, "Courier New", monospace; - font-size: 12px; - color: #333333; - -webkit-border-radius: 3px; - -moz-border-radius: 3px; - border-radius: 3px; -} - -code { - padding: 2px 4px; - color: #d14; - background-color: #f7f7f9; - border: 1px solid #e1e1e8; -} - -pre { - display: block; - padding: 8.5px; - margin: 0 0 9px; - font-size: 12.025px; - line-height: 18px; - word-break: break-all; - word-wrap: break-word; - white-space: pre; - white-space: pre-wrap; - background-color: #f5f5f5; - border: 1px solid #ccc; - border: 1px solid rgba(0, 0, 0, 0.15); - -webkit-border-radius: 4px; - -moz-border-radius: 4px; - border-radius: 4px; -} - -pre.prettyprint { - margin-bottom: 18px; -} - -pre code { - padding: 0; - color: inherit; - background-color: transparent; - border: 0; -} - -.pre-scrollable { - max-height: 340px; - overflow-y: scroll; -} - -form { - margin: 0 0 18px; -} - -fieldset { - padding: 0; - margin: 0; - border: 0; -} - -legend { - display: block; - width: 100%; - padding: 0; - margin-bottom: 27px; - font-size: 19.5px; - line-height: 36px; - color: #333333; - border: 0; - border-bottom: 1px solid #e5e5e5; -} - -legend small { - font-size: 13.5px; - color: #999999; -} - -label, -input, -button, -select, -textarea { - font-size: 13px; - font-weight: normal; - line-height: 18px; -} - -input, -button, -select, -textarea { - font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; -} - -label { - display: block; - margin-bottom: 5px; -} - -select, -textarea, -input[type="text"], -input[type="password"], -input[type="datetime"], -input[type="datetime-local"], -input[type="date"], -input[type="month"], -input[type="time"], -input[type="week"], -input[type="number"], -input[type="email"], -input[type="url"], -input[type="search"], -input[type="tel"], -input[type="color"], -.uneditable-input { - display: inline-block; - height: 18px; - padding: 4px; - margin-bottom: 9px; - font-size: 13px; - line-height: 18px; - color: #555555; -} - -input, -textarea { - width: 210px; -} - -textarea { - height: auto; -} - -textarea, -input[type="text"], -input[type="password"], -input[type="datetime"], -input[type="datetime-local"], -input[type="date"], -input[type="month"], -input[type="time"], -input[type="week"], -input[type="number"], -input[type="email"], -input[type="url"], -input[type="search"], -input[type="tel"], -input[type="color"], -.uneditable-input { - background-color: #ffffff; - border: 1px solid #cccccc; - -webkit-border-radius: 3px; - -moz-border-radius: 3px; - border-radius: 3px; - -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); - -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); - box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); - -webkit-transition: border linear 0.2s, box-shadow linear 0.2s; - -moz-transition: border linear 0.2s, box-shadow linear 0.2s; - -ms-transition: border linear 0.2s, box-shadow linear 0.2s; - -o-transition: border linear 0.2s, box-shadow linear 0.2s; - transition: border linear 0.2s, box-shadow linear 0.2s; -} - -textarea:focus, -input[type="text"]:focus, -input[type="password"]:focus, -input[type="datetime"]:focus, -input[type="datetime-local"]:focus, -input[type="date"]:focus, -input[type="month"]:focus, -input[type="time"]:focus, -input[type="week"]:focus, -input[type="number"]:focus, -input[type="email"]:focus, -input[type="url"]:focus, -input[type="search"]:focus, -input[type="tel"]:focus, -input[type="color"]:focus, -.uneditable-input:focus { - border-color: rgba(82, 168, 236, 0.8); - outline: 0; - outline: thin dotted \9; - /* IE6-9 */ - - -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6); - -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6); - box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6); -} - -input[type="radio"], -input[type="checkbox"] { - margin: 3px 0; - *margin-top: 0; - /* IE7 */ - - line-height: normal; - cursor: pointer; -} - -input[type="submit"], -input[type="reset"], -input[type="button"], -input[type="radio"], -input[type="checkbox"] { - width: auto; -} - -.uneditable-textarea { - width: auto; - height: auto; -} - -select, -input[type="file"] { - height: 28px; - /* In IE7, the height of the select element cannot be changed by height, only font-size */ - - *margin-top: 4px; - /* For IE7, add top margin to align select with labels */ - - line-height: 28px; -} - -select { - width: 220px; - border: 1px solid #bbb; -} - -select[multiple], -select[size] { - height: auto; -} - -select:focus, -input[type="file"]:focus, -input[type="radio"]:focus, -input[type="checkbox"]:focus { - outline: thin dotted #333; - outline: 5px auto -webkit-focus-ring-color; - outline-offset: -2px; -} - -.radio, -.checkbox { - min-height: 18px; - padding-left: 18px; -} - -.radio input[type="radio"], -.checkbox input[type="checkbox"] { - float: left; - margin-left: -18px; -} - -.controls > .radio:first-child, -.controls > .checkbox:first-child { - padding-top: 5px; -} - -.radio.inline, -.checkbox.inline { - display: inline-block; - padding-top: 5px; - margin-bottom: 0; - vertical-align: middle; -} - -.radio.inline + .radio.inline, -.checkbox.inline + .checkbox.inline { - margin-left: 10px; -} - -.input-mini { - width: 60px; -} - -.input-small { - width: 90px; -} - -.input-medium { - width: 150px; -} - -.input-large { - width: 210px; -} - -.input-xlarge { - width: 270px; -} - -.input-xxlarge { - width: 530px; -} - -input[class*="span"], -select[class*="span"], -textarea[class*="span"], -.uneditable-input[class*="span"], -.row-fluid input[class*="span"], -.row-fluid select[class*="span"], -.row-fluid textarea[class*="span"], -.row-fluid .uneditable-input[class*="span"] { - float: none; - margin-left: 0; -} - -.input-append input[class*="span"], -.input-append .uneditable-input[class*="span"], -.input-prepend input[class*="span"], -.input-prepend .uneditable-input[class*="span"], -.row-fluid .input-prepend [class*="span"], -.row-fluid .input-append [class*="span"] { - display: inline-block; -} - -input, -textarea, -.uneditable-input { - margin-left: 0; -} - -input.span12, -textarea.span12, -.uneditable-input.span12 { - width: 930px; -} - -input.span11, -textarea.span11, -.uneditable-input.span11 { - width: 850px; -} - -input.span10, -textarea.span10, -.uneditable-input.span10 { - width: 770px; -} - -input.span9, -textarea.span9, -.uneditable-input.span9 { - width: 690px; -} - -input.span8, -textarea.span8, -.uneditable-input.span8 { - width: 610px; -} - -input.span7, -textarea.span7, -.uneditable-input.span7 { - width: 530px; -} - -input.span6, -textarea.span6, -.uneditable-input.span6 { - width: 450px; -} - -input.span5, -textarea.span5, -.uneditable-input.span5 { - width: 370px; -} - -input.span4, -textarea.span4, -.uneditable-input.span4 { - width: 290px; -} - -input.span3, -textarea.span3, -.uneditable-input.span3 { - width: 210px; -} - -input.span2, -textarea.span2, -.uneditable-input.span2 { - width: 130px; -} - -input.span1, -textarea.span1, -.uneditable-input.span1 { - width: 50px; -} - -input[disabled], -select[disabled], -textarea[disabled], -input[readonly], -select[readonly], -textarea[readonly] { - cursor: not-allowed; - background-color: #eeeeee; - border-color: #ddd; -} - -input[type="radio"][disabled], -input[type="checkbox"][disabled], -input[type="radio"][readonly], -input[type="checkbox"][readonly] { - background-color: transparent; -} - -.control-group.warning > label, -.control-group.warning .help-block, -.control-group.warning .help-inline { - color: #c09853; -} - -.control-group.warning .checkbox, -.control-group.warning .radio, -.control-group.warning input, -.control-group.warning select, -.control-group.warning textarea { - color: #c09853; - border-color: #c09853; -} - -.control-group.warning .checkbox:focus, -.control-group.warning .radio:focus, -.control-group.warning input:focus, -.control-group.warning select:focus, -.control-group.warning textarea:focus { - border-color: #a47e3c; - -webkit-box-shadow: 0 0 6px #dbc59e; - -moz-box-shadow: 0 0 6px #dbc59e; - box-shadow: 0 0 6px #dbc59e; -} - -.control-group.warning .input-prepend .add-on, -.control-group.warning .input-append .add-on { - color: #c09853; - background-color: #fcf8e3; - border-color: #c09853; -} - -.control-group.error > label, -.control-group.error .help-block, -.control-group.error .help-inline { - color: #b94a48; -} - -.control-group.error .checkbox, -.control-group.error .radio, -.control-group.error input, -.control-group.error select, -.control-group.error textarea { - color: #b94a48; - border-color: #b94a48; -} - -.control-group.error .checkbox:focus, -.control-group.error .radio:focus, -.control-group.error input:focus, -.control-group.error select:focus, -.control-group.error textarea:focus { - border-color: #953b39; - -webkit-box-shadow: 0 0 6px #d59392; - -moz-box-shadow: 0 0 6px #d59392; - box-shadow: 0 0 6px #d59392; -} - -.control-group.error .input-prepend .add-on, -.control-group.error .input-append .add-on { - color: #b94a48; - background-color: #f2dede; - border-color: #b94a48; -} - -.control-group.success > label, -.control-group.success .help-block, -.control-group.success .help-inline { - color: #468847; -} - -.control-group.success .checkbox, -.control-group.success .radio, -.control-group.success input, -.control-group.success select, -.control-group.success textarea { - color: #468847; - border-color: #468847; -} - -.control-group.success .checkbox:focus, -.control-group.success .radio:focus, -.control-group.success input:focus, -.control-group.success select:focus, -.control-group.success textarea:focus { - border-color: #356635; - -webkit-box-shadow: 0 0 6px #7aba7b; - -moz-box-shadow: 0 0 6px #7aba7b; - box-shadow: 0 0 6px #7aba7b; -} - -.control-group.success .input-prepend .add-on, -.control-group.success .input-append .add-on { - color: #468847; - background-color: #dff0d8; - border-color: #468847; -} - -input:focus:required:invalid, -textarea:focus:required:invalid, -select:focus:required:invalid { - color: #b94a48; - border-color: #ee5f5b; -} - -input:focus:required:invalid:focus, -textarea:focus:required:invalid:focus, -select:focus:required:invalid:focus { - border-color: #e9322d; - -webkit-box-shadow: 0 0 6px #f8b9b7; - -moz-box-shadow: 0 0 6px #f8b9b7; - box-shadow: 0 0 6px #f8b9b7; -} - -.form-actions { - padding: 17px 20px 18px; - margin-top: 18px; - margin-bottom: 18px; - background-color: #f5f5f5; - border-top: 1px solid #e5e5e5; - *zoom: 1; -} - -.form-actions:before, -.form-actions:after { - display: table; - content: ""; -} - -.form-actions:after { - clear: both; -} - -.uneditable-input { - overflow: hidden; - white-space: nowrap; - cursor: not-allowed; - background-color: #ffffff; - border-color: #eee; - -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025); - -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025); - box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025); -} - -:-moz-placeholder { - color: #999999; -} - -:-ms-input-placeholder { - color: #999999; -} - -::-webkit-input-placeholder { - color: #999999; -} - -.help-block, -.help-inline { - color: #555555; -} - -.help-block { - display: block; - margin-bottom: 9px; -} - -.help-inline { - display: inline-block; - *display: inline; - padding-left: 5px; - vertical-align: middle; - *zoom: 1; -} - -.input-prepend, -.input-append { - margin-bottom: 5px; -} - -.input-prepend input, -.input-append input, -.input-prepend select, -.input-append select, -.input-prepend .uneditable-input, -.input-append .uneditable-input { - position: relative; - margin-bottom: 0; - *margin-left: 0; - vertical-align: middle; - -webkit-border-radius: 0 3px 3px 0; - -moz-border-radius: 0 3px 3px 0; - border-radius: 0 3px 3px 0; -} - -.input-prepend input:focus, -.input-append input:focus, -.input-prepend select:focus, -.input-append select:focus, -.input-prepend .uneditable-input:focus, -.input-append .uneditable-input:focus { - z-index: 2; -} - -.input-prepend .uneditable-input, -.input-append .uneditable-input { - border-left-color: #ccc; -} - -.input-prepend .add-on, -.input-append .add-on { - display: inline-block; - width: auto; - height: 18px; - min-width: 16px; - padding: 4px 5px; - font-weight: normal; - line-height: 18px; - text-align: center; - text-shadow: 0 1px 0 #ffffff; - vertical-align: middle; - background-color: #eeeeee; - border: 1px solid #ccc; -} - -.input-prepend .add-on, -.input-append .add-on, -.input-prepend .btn, -.input-append .btn { - margin-left: -1px; - -webkit-border-radius: 0; - -moz-border-radius: 0; - border-radius: 0; -} - -.input-prepend .active, -.input-append .active { - background-color: #a9dba9; - border-color: #46a546; -} - -.input-prepend .add-on, -.input-prepend .btn { - margin-right: -1px; -} - -.input-prepend .add-on:first-child, -.input-prepend .btn:first-child { - -webkit-border-radius: 3px 0 0 3px; - -moz-border-radius: 3px 0 0 3px; - border-radius: 3px 0 0 3px; -} - -.input-append input, -.input-append select, -.input-append .uneditable-input { - -webkit-border-radius: 3px 0 0 3px; - -moz-border-radius: 3px 0 0 3px; - border-radius: 3px 0 0 3px; -} - -.input-append .uneditable-input { - border-right-color: #ccc; - border-left-color: #eee; -} - -.input-append .add-on:last-child, -.input-append .btn:last-child { - -webkit-border-radius: 0 3px 3px 0; - -moz-border-radius: 0 3px 3px 0; - border-radius: 0 3px 3px 0; -} - -.input-prepend.input-append input, -.input-prepend.input-append select, -.input-prepend.input-append .uneditable-input { - -webkit-border-radius: 0; - -moz-border-radius: 0; - border-radius: 0; -} - -.input-prepend.input-append .add-on:first-child, -.input-prepend.input-append .btn:first-child { - margin-right: -1px; - -webkit-border-radius: 3px 0 0 3px; - -moz-border-radius: 3px 0 0 3px; - border-radius: 3px 0 0 3px; -} - -.input-prepend.input-append .add-on:last-child, -.input-prepend.input-append .btn:last-child { - margin-left: -1px; - -webkit-border-radius: 0 3px 3px 0; - -moz-border-radius: 0 3px 3px 0; - border-radius: 0 3px 3px 0; -} - -.search-query { - padding-right: 14px; - padding-right: 4px \9; - padding-left: 14px; - padding-left: 4px \9; - /* IE7-8 doesn't have border-radius, so don't indent the padding */ - - margin-bottom: 0; - -webkit-border-radius: 14px; - -moz-border-radius: 14px; - border-radius: 14px; -} - -.form-search input, -.form-inline input, -.form-horizontal input, -.form-search textarea, -.form-inline textarea, -.form-horizontal textarea, -.form-search select, -.form-inline select, -.form-horizontal select, -.form-search .help-inline, -.form-inline .help-inline, -.form-horizontal .help-inline, -.form-search .uneditable-input, -.form-inline .uneditable-input, -.form-horizontal .uneditable-input, -.form-search .input-prepend, -.form-inline .input-prepend, -.form-horizontal .input-prepend, -.form-search .input-append, -.form-inline .input-append, -.form-horizontal .input-append { - display: inline-block; - *display: inline; - margin-bottom: 0; - *zoom: 1; -} - -.form-search .hide, -.form-inline .hide, -.form-horizontal .hide { - display: none; -} - -.form-search label, -.form-inline label { - display: inline-block; -} - -.form-search .input-append, -.form-inline .input-append, -.form-search .input-prepend, -.form-inline .input-prepend { - margin-bottom: 0; -} - -.form-search .radio, -.form-search .checkbox, -.form-inline .radio, -.form-inline .checkbox { - padding-left: 0; - margin-bottom: 0; - vertical-align: middle; -} - -.form-search .radio input[type="radio"], -.form-search .checkbox input[type="checkbox"], -.form-inline .radio input[type="radio"], -.form-inline .checkbox input[type="checkbox"] { - float: left; - margin-right: 3px; - margin-left: 0; -} - -.control-group { - margin-bottom: 9px; -} - -legend + .control-group { - margin-top: 18px; - -webkit-margin-top-collapse: separate; -} - -.form-horizontal .control-group { - margin-bottom: 18px; - *zoom: 1; -} - -.form-horizontal .control-group:before, -.form-horizontal .control-group:after { - display: table; - content: ""; -} - -.form-horizontal .control-group:after { - clear: both; -} - -.form-horizontal .control-label { - float: left; - width: 140px; - padding-top: 5px; - text-align: right; -} - -.form-horizontal .controls { - *display: inline-block; - *padding-left: 20px; - margin-left: 160px; - *margin-left: 0; -} - -.form-horizontal .controls:first-child { - *padding-left: 160px; -} - -.form-horizontal .help-block { - margin-top: 9px; - margin-bottom: 0; -} - -.form-horizontal .form-actions { - padding-left: 160px; -} - -table { - max-width: 100%; - background-color: transparent; - border-collapse: collapse; - border-spacing: 0; -} - -.table { - width: 100%; - margin-bottom: 18px; -} - -.table th, -.table td { - padding: 8px; - line-height: 18px; - text-align: left; - vertical-align: top; - border-top: 1px solid #dddddd; -} - -.table th { - font-weight: bold; -} - -.table thead th { - vertical-align: bottom; -} - -.table caption + thead tr:first-child th, -.table caption + thead tr:first-child td, -.table colgroup + thead tr:first-child th, -.table colgroup + thead tr:first-child td, -.table thead:first-child tr:first-child th, -.table thead:first-child tr:first-child td { - border-top: 0; -} - -.table tbody + tbody { - border-top: 2px solid #dddddd; -} - -.table-condensed th, -.table-condensed td { - padding: 4px 5px; -} - -.table-bordered { - border: 1px solid #dddddd; - border-collapse: separate; - *border-collapse: collapsed; - border-left: 0; - -webkit-border-radius: 4px; - -moz-border-radius: 4px; - border-radius: 4px; -} - -.table-bordered th, -.table-bordered td { - border-left: 1px solid #dddddd; -} - -.table-bordered caption + thead tr:first-child th, -.table-bordered caption + tbody tr:first-child th, -.table-bordered caption + tbody tr:first-child td, -.table-bordered colgroup + thead tr:first-child th, -.table-bordered colgroup + tbody tr:first-child th, -.table-bordered colgroup + tbody tr:first-child td, -.table-bordered thead:first-child tr:first-child th, -.table-bordered tbody:first-child tr:first-child th, -.table-bordered tbody:first-child tr:first-child td { - border-top: 0; -} - -.table-bordered thead:first-child tr:first-child th:first-child, -.table-bordered tbody:first-child tr:first-child td:first-child { - -webkit-border-top-left-radius: 4px; - border-top-left-radius: 4px; - -moz-border-radius-topleft: 4px; -} - -.table-bordered thead:first-child tr:first-child th:last-child, -.table-bordered tbody:first-child tr:first-child td:last-child { - -webkit-border-top-right-radius: 4px; - border-top-right-radius: 4px; - -moz-border-radius-topright: 4px; -} - -.table-bordered thead:last-child tr:last-child th:first-child, -.table-bordered tbody:last-child tr:last-child td:first-child { - -webkit-border-radius: 0 0 0 4px; - -moz-border-radius: 0 0 0 4px; - border-radius: 0 0 0 4px; - -webkit-border-bottom-left-radius: 4px; - border-bottom-left-radius: 4px; - -moz-border-radius-bottomleft: 4px; -} - -.table-bordered thead:last-child tr:last-child th:last-child, -.table-bordered tbody:last-child tr:last-child td:last-child { - -webkit-border-bottom-right-radius: 4px; - border-bottom-right-radius: 4px; - -moz-border-radius-bottomright: 4px; -} - -.table-striped tbody tr:nth-child(odd) td, -.table-striped tbody tr:nth-child(odd) th { - background-color: #f9f9f9; -} - -.table tbody tr:hover td, -.table tbody tr:hover th { - background-color: #f5f5f5; -} - -table .span1 { - float: none; - width: 44px; - margin-left: 0; -} - -table .span2 { - float: none; - width: 124px; - margin-left: 0; -} - -table .span3 { - float: none; - width: 204px; - margin-left: 0; -} - -table .span4 { - float: none; - width: 284px; - margin-left: 0; -} - -table .span5 { - float: none; - width: 364px; - margin-left: 0; -} - -table .span6 { - float: none; - width: 444px; - margin-left: 0; -} - -table .span7 { - float: none; - width: 524px; - margin-left: 0; -} - -table .span8 { - float: none; - width: 604px; - margin-left: 0; -} - -table .span9 { - float: none; - width: 684px; - margin-left: 0; -} - -table .span10 { - float: none; - width: 764px; - margin-left: 0; -} - -table .span11 { - float: none; - width: 844px; - margin-left: 0; -} - -table .span12 { - float: none; - width: 924px; - margin-left: 0; -} - -table .span13 { - float: none; - width: 1004px; - margin-left: 0; -} - -table .span14 { - float: none; - width: 1084px; - margin-left: 0; -} - -table .span15 { - float: none; - width: 1164px; - margin-left: 0; -} - -table .span16 { - float: none; - width: 1244px; - margin-left: 0; -} - -table .span17 { - float: none; - width: 1324px; - margin-left: 0; -} - -table .span18 { - float: none; - width: 1404px; - margin-left: 0; -} - -table .span19 { - float: none; - width: 1484px; - margin-left: 0; -} - -table .span20 { - float: none; - width: 1564px; - margin-left: 0; -} - -table .span21 { - float: none; - width: 1644px; - margin-left: 0; -} - -table .span22 { - float: none; - width: 1724px; - margin-left: 0; -} - -table .span23 { - float: none; - width: 1804px; - margin-left: 0; -} - -table .span24 { - float: none; - width: 1884px; - margin-left: 0; -} - -[class^="icon-"], -[class*=" icon-"] { - display: inline-block; - width: 14px; - height: 14px; - *margin-right: .3em; - line-height: 14px; - vertical-align: text-top; - background-image: url("../img/glyphicons-halflings.png"); - background-position: 14px 14px; - background-repeat: no-repeat; -} - -[class^="icon-"]:last-child, -[class*=" icon-"]:last-child { - *margin-left: 0; -} - -.icon-white { - background-image: url("../img/glyphicons-halflings-white.png"); -} - -.icon-glass { - background-position: 0 0; -} - -.icon-music { - background-position: -24px 0; -} - -.icon-search { - background-position: -48px 0; -} - -.icon-envelope { - background-position: -72px 0; -} - -.icon-heart { - background-position: -96px 0; -} - -.icon-star { - background-position: -120px 0; -} - -.icon-star-empty { - background-position: -144px 0; -} - -.icon-user { - background-position: -168px 0; -} - -.icon-film { - background-position: -192px 0; -} - -.icon-th-large { - background-position: -216px 0; -} - -.icon-th { - background-position: -240px 0; -} - -.icon-th-list { - background-position: -264px 0; -} - -.icon-ok { - background-position: -288px 0; -} - -.icon-remove { - background-position: -312px 0; -} - -.icon-zoom-in { - background-position: -336px 0; -} - -.icon-zoom-out { - background-position: -360px 0; -} - -.icon-off { - background-position: -384px 0; -} - -.icon-signal { - background-position: -408px 0; -} - -.icon-cog { - background-position: -432px 0; -} - -.icon-trash { - background-position: -456px 0; -} - -.icon-home { - background-position: 0 -24px; -} - -.icon-file { - background-position: -24px -24px; -} - -.icon-time { - background-position: -48px -24px; -} - -.icon-road { - background-position: -72px -24px; -} - -.icon-download-alt { - background-position: -96px -24px; -} - -.icon-download { - background-position: -120px -24px; -} - -.icon-upload { - background-position: -144px -24px; -} - -.icon-inbox { - background-position: -168px -24px; -} - -.icon-play-circle { - background-position: -192px -24px; -} - -.icon-repeat { - background-position: -216px -24px; -} - -.icon-refresh { - background-position: -240px -24px; -} - -.icon-list-alt { - background-position: -264px -24px; -} - -.icon-lock { - background-position: -287px -24px; -} - -.icon-flag { - background-position: -312px -24px; -} - -.icon-headphones { - background-position: -336px -24px; -} - -.icon-volume-off { - background-position: -360px -24px; -} - -.icon-volume-down { - background-position: -384px -24px; -} - -.icon-volume-up { - background-position: -408px -24px; -} - -.icon-qrcode { - background-position: -432px -24px; -} - -.icon-barcode { - background-position: -456px -24px; -} - -.icon-tag { - background-position: 0 -48px; -} - -.icon-tags { - background-position: -25px -48px; -} - -.icon-book { - background-position: -48px -48px; -} - -.icon-bookmark { - background-position: -72px -48px; -} - -.icon-print { - background-position: -96px -48px; -} - -.icon-camera { - background-position: -120px -48px; -} - -.icon-font { - background-position: -144px -48px; -} - -.icon-bold { - background-position: -167px -48px; -} - -.icon-italic { - background-position: -192px -48px; -} - -.icon-text-height { - background-position: -216px -48px; -} - -.icon-text-width { - background-position: -240px -48px; -} - -.icon-align-left { - background-position: -264px -48px; -} - -.icon-align-center { - background-position: -288px -48px; -} - -.icon-align-right { - background-position: -312px -48px; -} - -.icon-align-justify { - background-position: -336px -48px; -} - -.icon-list { - background-position: -360px -48px; -} - -.icon-indent-left { - background-position: -384px -48px; -} - -.icon-indent-right { - background-position: -408px -48px; -} - -.icon-facetime-video { - background-position: -432px -48px; -} - -.icon-picture { - background-position: -456px -48px; -} - -.icon-pencil { - background-position: 0 -72px; -} - -.icon-map-marker { - background-position: -24px -72px; -} - -.icon-adjust { - background-position: -48px -72px; -} - -.icon-tint { - background-position: -72px -72px; -} - -.icon-edit { - background-position: -96px -72px; -} - -.icon-share { - background-position: -120px -72px; -} - -.icon-check { - background-position: -144px -72px; -} - -.icon-move { - background-position: -168px -72px; -} - -.icon-step-backward { - background-position: -192px -72px; -} - -.icon-fast-backward { - background-position: -216px -72px; -} - -.icon-backward { - background-position: -240px -72px; -} - -.icon-play { - background-position: -264px -72px; -} - -.icon-pause { - background-position: -288px -72px; -} - -.icon-stop { - background-position: -312px -72px; -} - -.icon-forward { - background-position: -336px -72px; -} - -.icon-fast-forward { - background-position: -360px -72px; -} - -.icon-step-forward { - background-position: -384px -72px; -} - -.icon-eject { - background-position: -408px -72px; -} - -.icon-chevron-left { - background-position: -432px -72px; -} - -.icon-chevron-right { - background-position: -456px -72px; -} - -.icon-plus-sign { - background-position: 0 -96px; -} - -.icon-minus-sign { - background-position: -24px -96px; -} - -.icon-remove-sign { - background-position: -48px -96px; -} - -.icon-ok-sign { - background-position: -72px -96px; -} - -.icon-question-sign { - background-position: -96px -96px; -} - -.icon-info-sign { - background-position: -120px -96px; -} - -.icon-screenshot { - background-position: -144px -96px; -} - -.icon-remove-circle { - background-position: -168px -96px; -} - -.icon-ok-circle { - background-position: -192px -96px; -} - -.icon-ban-circle { - background-position: -216px -96px; -} - -.icon-arrow-left { - background-position: -240px -96px; -} - -.icon-arrow-right { - background-position: -264px -96px; -} - -.icon-arrow-up { - background-position: -289px -96px; -} - -.icon-arrow-down { - background-position: -312px -96px; -} - -.icon-share-alt { - background-position: -336px -96px; -} - -.icon-resize-full { - background-position: -360px -96px; -} - -.icon-resize-small { - background-position: -384px -96px; -} - -.icon-plus { - background-position: -408px -96px; -} - -.icon-minus { - background-position: -433px -96px; -} - -.icon-asterisk { - background-position: -456px -96px; -} - -.icon-exclamation-sign { - background-position: 0 -120px; -} - -.icon-gift { - background-position: -24px -120px; -} - -.icon-leaf { - background-position: -48px -120px; -} - -.icon-fire { - background-position: -72px -120px; -} - -.icon-eye-open { - background-position: -96px -120px; -} - -.icon-eye-close { - background-position: -120px -120px; -} - -.icon-warning-sign { - background-position: -144px -120px; -} - -.icon-plane { - background-position: -168px -120px; -} - -.icon-calendar { - background-position: -192px -120px; -} - -.icon-random { - background-position: -216px -120px; -} - -.icon-comment { - background-position: -240px -120px; -} - -.icon-magnet { - background-position: -264px -120px; -} - -.icon-chevron-up { - background-position: -288px -120px; -} - -.icon-chevron-down { - background-position: -313px -119px; -} - -.icon-retweet { - background-position: -336px -120px; -} - -.icon-shopping-cart { - background-position: -360px -120px; -} - -.icon-folder-close { - background-position: -384px -120px; -} - -.icon-folder-open { - background-position: -408px -120px; -} - -.icon-resize-vertical { - background-position: -432px -119px; -} - -.icon-resize-horizontal { - background-position: -456px -118px; -} - -.icon-hdd { - background-position: 0 -144px; -} - -.icon-bullhorn { - background-position: -24px -144px; -} - -.icon-bell { - background-position: -48px -144px; -} - -.icon-certificate { - background-position: -72px -144px; -} - -.icon-thumbs-up { - background-position: -96px -144px; -} - -.icon-thumbs-down { - background-position: -120px -144px; -} - -.icon-hand-right { - background-position: -144px -144px; -} - -.icon-hand-left { - background-position: -168px -144px; -} - -.icon-hand-up { - background-position: -192px -144px; -} - -.icon-hand-down { - background-position: -216px -144px; -} - -.icon-circle-arrow-right { - background-position: -240px -144px; -} - -.icon-circle-arrow-left { - background-position: -264px -144px; -} - -.icon-circle-arrow-up { - background-position: -288px -144px; -} - -.icon-circle-arrow-down { - background-position: -312px -144px; -} - -.icon-globe { - background-position: -336px -144px; -} - -.icon-wrench { - background-position: -360px -144px; -} - -.icon-tasks { - background-position: -384px -144px; -} - -.icon-filter { - background-position: -408px -144px; -} - -.icon-briefcase { - background-position: -432px -144px; -} - -.icon-fullscreen { - background-position: -456px -144px; -} - -.dropup, -.dropdown { - position: relative; -} - -.dropdown-toggle { - *margin-bottom: -3px; -} - -.dropdown-toggle:active, -.open .dropdown-toggle { - outline: 0; -} - -.caret { - display: inline-block; - width: 0; - height: 0; - vertical-align: top; - border-top: 4px solid #000000; - border-right: 4px solid transparent; - border-left: 4px solid transparent; - content: ""; - opacity: 0.3; - filter: alpha(opacity=30); -} - -.dropdown .caret { - margin-top: 8px; - margin-left: 2px; -} - -.dropdown:hover .caret, -.open .caret { - opacity: 1; - filter: alpha(opacity=100); -} - -.dropdown-menu { - position: absolute; - top: 100%; - left: 0; - z-index: 1000; - display: none; - float: left; - min-width: 160px; - padding: 4px 0; - margin: 1px 0 0; - list-style: none; - background-color: #ffffff; - border: 1px solid #ccc; - border: 1px solid rgba(0, 0, 0, 0.2); - *border-right-width: 2px; - *border-bottom-width: 2px; - -webkit-border-radius: 5px; - -moz-border-radius: 5px; - border-radius: 5px; - -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); - -moz-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); - box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); - -webkit-background-clip: padding-box; - -moz-background-clip: padding; - background-clip: padding-box; -} - -.dropdown-menu.pull-right { - right: 0; - left: auto; -} - -.dropdown-menu .divider { - *width: 100%; - height: 1px; - margin: 8px 1px; - *margin: -5px 0 5px; - overflow: hidden; - background-color: #e5e5e5; - border-bottom: 1px solid #ffffff; -} - -.dropdown-menu a { - display: block; - padding: 3px 15px; - clear: both; - font-weight: normal; - line-height: 18px; - color: #333333; - white-space: nowrap; -} - -.dropdown-menu li > a:hover, -.dropdown-menu .active > a, -.dropdown-menu .active > a:hover { - color: #ffffff; - text-decoration: none; - background-color: #0088cc; -} - -.open { - *z-index: 1000; -} - -.open > .dropdown-menu { - display: block; -} - -.pull-right > .dropdown-menu { - right: 0; - left: auto; -} - -.dropup .caret, -.navbar-fixed-bottom .dropdown .caret { - border-top: 0; - border-bottom: 4px solid #000000; - content: "\2191"; -} - -.dropup .dropdown-menu, -.navbar-fixed-bottom .dropdown .dropdown-menu { - top: auto; - bottom: 100%; - margin-bottom: 1px; -} - -.typeahead { - margin-top: 2px; - -webkit-border-radius: 4px; - -moz-border-radius: 4px; - border-radius: 4px; -} - -.well { - min-height: 20px; - padding: 19px; - margin-bottom: 20px; - background-color: #f5f5f5; - border: 1px solid #eee; - border: 1px solid rgba(0, 0, 0, 0.05); - -webkit-border-radius: 4px; - -moz-border-radius: 4px; - border-radius: 4px; - -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05); - -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05); - box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05); -} - -.well blockquote { - border-color: #ddd; - border-color: rgba(0, 0, 0, 0.15); -} - -.well-large { - padding: 24px; - -webkit-border-radius: 6px; - -moz-border-radius: 6px; - border-radius: 6px; -} - -.well-small { - padding: 9px; - -webkit-border-radius: 3px; - -moz-border-radius: 3px; - border-radius: 3px; -} - -.fade { - opacity: 0; - -webkit-transition: opacity 0.15s linear; - -moz-transition: opacity 0.15s linear; - -ms-transition: opacity 0.15s linear; - -o-transition: opacity 0.15s linear; - transition: opacity 0.15s linear; -} - -.fade.in { - opacity: 1; -} - -.collapse { - position: relative; - height: 0; - overflow: hidden; - -webkit-transition: height 0.35s ease; - -moz-transition: height 0.35s ease; - -ms-transition: height 0.35s ease; - -o-transition: height 0.35s ease; - transition: height 0.35s ease; -} - -.collapse.in { - height: auto; -} - -.close { - float: right; - font-size: 20px; - font-weight: bold; - line-height: 18px; - color: #000000; - text-shadow: 0 1px 0 #ffffff; - opacity: 0.2; - filter: alpha(opacity=20); -} - -.close:hover { - color: #000000; - text-decoration: none; - cursor: pointer; - opacity: 0.4; - filter: alpha(opacity=40); -} - -button.close { - padding: 0; - cursor: pointer; - background: transparent; - border: 0; - -webkit-appearance: none; -} - -.btn { - display: inline-block; - *display: inline; - padding: 4px 10px 4px; - margin-bottom: 0; - *margin-left: .3em; - font-size: 13px; - line-height: 18px; - *line-height: 20px; - color: #333333; - text-align: center; - text-shadow: 0 1px 1px rgba(255, 255, 255, 0.75); - vertical-align: middle; - cursor: pointer; - background-color: #f5f5f5; - *background-color: #e6e6e6; - background-image: -ms-linear-gradient(top, #ffffff, #e6e6e6); - background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#e6e6e6)); - background-image: -webkit-linear-gradient(top, #ffffff, #e6e6e6); - background-image: -o-linear-gradient(top, #ffffff, #e6e6e6); - background-image: linear-gradient(top, #ffffff, #e6e6e6); - background-image: -moz-linear-gradient(top, #ffffff, #e6e6e6); - background-repeat: repeat-x; - border: 1px solid #cccccc; - *border: 0; - border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); - border-color: #e6e6e6 #e6e6e6 #bfbfbf; - border-bottom-color: #b3b3b3; - -webkit-border-radius: 4px; - -moz-border-radius: 4px; - border-radius: 4px; - filter: progid:dximagetransform.microsoft.gradient(startColorstr='#ffffff', endColorstr='#e6e6e6', GradientType=0); - filter: progid:dximagetransform.microsoft.gradient(enabled=false); - *zoom: 1; - -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); - -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); - box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); -} - -.btn:hover, -.btn:active, -.btn.active, -.btn.disabled, -.btn[disabled] { - background-color: #e6e6e6; - *background-color: #d9d9d9; -} - -.btn:active, -.btn.active { - background-color: #cccccc \9; -} - -.btn:first-child { - *margin-left: 0; -} - -.btn:hover { - color: #333333; - text-decoration: none; - background-color: #e6e6e6; - *background-color: #d9d9d9; - /* Buttons in IE7 don't get borders, so darken on hover */ - - background-position: 0 -15px; - -webkit-transition: background-position 0.1s linear; - -moz-transition: background-position 0.1s linear; - -ms-transition: background-position 0.1s linear; - -o-transition: background-position 0.1s linear; - transition: background-position 0.1s linear; -} - -.btn:focus { - outline: thin dotted #333; - outline: 5px auto -webkit-focus-ring-color; - outline-offset: -2px; -} - -.btn.active, -.btn:active { - background-color: #e6e6e6; - background-color: #d9d9d9 \9; - background-image: none; - outline: 0; - -webkit-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05); - -moz-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05); - box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05); -} - -.btn.disabled, -.btn[disabled] { - cursor: default; - background-color: #e6e6e6; - background-image: none; - opacity: 0.65; - filter: alpha(opacity=65); - -webkit-box-shadow: none; - -moz-box-shadow: none; - box-shadow: none; -} - -.btn-large { - padding: 9px 14px; - font-size: 15px; - line-height: normal; - -webkit-border-radius: 5px; - -moz-border-radius: 5px; - border-radius: 5px; -} - -.btn-large [class^="icon-"] { - margin-top: 1px; -} - -.btn-small { - padding: 5px 9px; - font-size: 11px; - line-height: 16px; -} - -.btn-small [class^="icon-"] { - margin-top: -1px; -} - -.btn-mini { - padding: 2px 6px; - font-size: 11px; - line-height: 14px; -} - -.btn-primary, -.btn-primary:hover, -.btn-warning, -.btn-warning:hover, -.btn-danger, -.btn-danger:hover, -.btn-success, -.btn-success:hover, -.btn-info, -.btn-info:hover, -.btn-inverse, -.btn-inverse:hover { - color: #ffffff; - text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); -} - -.btn-primary.active, -.btn-warning.active, -.btn-danger.active, -.btn-success.active, -.btn-info.active, -.btn-inverse.active { - color: rgba(255, 255, 255, 0.75); -} - -.btn { - border-color: #ccc; - border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); -} - -.btn-primary { - background-color: #0074cc; - *background-color: #0055cc; - background-image: -ms-linear-gradient(top, #0088cc, #0055cc); - background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0055cc)); - background-image: -webkit-linear-gradient(top, #0088cc, #0055cc); - background-image: -o-linear-gradient(top, #0088cc, #0055cc); - background-image: -moz-linear-gradient(top, #0088cc, #0055cc); - background-image: linear-gradient(top, #0088cc, #0055cc); - background-repeat: repeat-x; - border-color: #0055cc #0055cc #003580; - border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); - filter: progid:dximagetransform.microsoft.gradient(startColorstr='#0088cc', endColorstr='#0055cc', GradientType=0); - filter: progid:dximagetransform.microsoft.gradient(enabled=false); -} - -.btn-primary:hover, -.btn-primary:active, -.btn-primary.active, -.btn-primary.disabled, -.btn-primary[disabled] { - background-color: #0055cc; - *background-color: #004ab3; -} - -.btn-primary:active, -.btn-primary.active { - background-color: #004099 \9; -} - -.btn-warning { - background-color: #faa732; - *background-color: #f89406; - background-image: -ms-linear-gradient(top, #fbb450, #f89406); - background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fbb450), to(#f89406)); - background-image: -webkit-linear-gradient(top, #fbb450, #f89406); - background-image: -o-linear-gradient(top, #fbb450, #f89406); - background-image: -moz-linear-gradient(top, #fbb450, #f89406); - background-image: linear-gradient(top, #fbb450, #f89406); - background-repeat: repeat-x; - border-color: #f89406 #f89406 #ad6704; - border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); - filter: progid:dximagetransform.microsoft.gradient(startColorstr='#fbb450', endColorstr='#f89406', GradientType=0); - filter: progid:dximagetransform.microsoft.gradient(enabled=false); -} - -.btn-warning:hover, -.btn-warning:active, -.btn-warning.active, -.btn-warning.disabled, -.btn-warning[disabled] { - background-color: #f89406; - *background-color: #df8505; -} - -.btn-warning:active, -.btn-warning.active { - background-color: #c67605 \9; -} - -.btn-danger { - background-color: #da4f49; - *background-color: #bd362f; - background-image: -ms-linear-gradient(top, #ee5f5b, #bd362f); - background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ee5f5b), to(#bd362f)); - background-image: -webkit-linear-gradient(top, #ee5f5b, #bd362f); - background-image: -o-linear-gradient(top, #ee5f5b, #bd362f); - background-image: -moz-linear-gradient(top, #ee5f5b, #bd362f); - background-image: linear-gradient(top, #ee5f5b, #bd362f); - background-repeat: repeat-x; - border-color: #bd362f #bd362f #802420; - border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); - filter: progid:dximagetransform.microsoft.gradient(startColorstr='#ee5f5b', endColorstr='#bd362f', GradientType=0); - filter: progid:dximagetransform.microsoft.gradient(enabled=false); -} - -.btn-danger:hover, -.btn-danger:active, -.btn-danger.active, -.btn-danger.disabled, -.btn-danger[disabled] { - background-color: #bd362f; - *background-color: #a9302a; -} - -.btn-danger:active, -.btn-danger.active { - background-color: #942a25 \9; -} - -.btn-success { - background-color: #5bb75b; - *background-color: #51a351; - background-image: -ms-linear-gradient(top, #62c462, #51a351); - background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#62c462), to(#51a351)); - background-image: -webkit-linear-gradient(top, #62c462, #51a351); - background-image: -o-linear-gradient(top, #62c462, #51a351); - background-image: -moz-linear-gradient(top, #62c462, #51a351); - background-image: linear-gradient(top, #62c462, #51a351); - background-repeat: repeat-x; - border-color: #51a351 #51a351 #387038; - border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); - filter: progid:dximagetransform.microsoft.gradient(startColorstr='#62c462', endColorstr='#51a351', GradientType=0); - filter: progid:dximagetransform.microsoft.gradient(enabled=false); -} - -.btn-success:hover, -.btn-success:active, -.btn-success.active, -.btn-success.disabled, -.btn-success[disabled] { - background-color: #51a351; - *background-color: #499249; -} - -.btn-success:active, -.btn-success.active { - background-color: #408140 \9; -} - -.btn-info { - background-color: #49afcd; - *background-color: #2f96b4; - background-image: -ms-linear-gradient(top, #5bc0de, #2f96b4); - background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#5bc0de), to(#2f96b4)); - background-image: -webkit-linear-gradient(top, #5bc0de, #2f96b4); - background-image: -o-linear-gradient(top, #5bc0de, #2f96b4); - background-image: -moz-linear-gradient(top, #5bc0de, #2f96b4); - background-image: linear-gradient(top, #5bc0de, #2f96b4); - background-repeat: repeat-x; - border-color: #2f96b4 #2f96b4 #1f6377; - border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); - filter: progid:dximagetransform.microsoft.gradient(startColorstr='#5bc0de', endColorstr='#2f96b4', GradientType=0); - filter: progid:dximagetransform.microsoft.gradient(enabled=false); -} - -.btn-info:hover, -.btn-info:active, -.btn-info.active, -.btn-info.disabled, -.btn-info[disabled] { - background-color: #2f96b4; - *background-color: #2a85a0; -} - -.btn-info:active, -.btn-info.active { - background-color: #24748c \9; -} - -.btn-inverse { - background-color: #414141; - *background-color: #222222; - background-image: -ms-linear-gradient(top, #555555, #222222); - background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#555555), to(#222222)); - background-image: -webkit-linear-gradient(top, #555555, #222222); - background-image: -o-linear-gradient(top, #555555, #222222); - background-image: -moz-linear-gradient(top, #555555, #222222); - background-image: linear-gradient(top, #555555, #222222); - background-repeat: repeat-x; - border-color: #222222 #222222 #000000; - border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); - filter: progid:dximagetransform.microsoft.gradient(startColorstr='#555555', endColorstr='#222222', GradientType=0); - filter: progid:dximagetransform.microsoft.gradient(enabled=false); -} - -.btn-inverse:hover, -.btn-inverse:active, -.btn-inverse.active, -.btn-inverse.disabled, -.btn-inverse[disabled] { - background-color: #222222; - *background-color: #151515; -} - -.btn-inverse:active, -.btn-inverse.active { - background-color: #080808 \9; -} - -button.btn, -input[type="submit"].btn { - *padding-top: 2px; - *padding-bottom: 2px; -} - -button.btn::-moz-focus-inner, -input[type="submit"].btn::-moz-focus-inner { - padding: 0; - border: 0; -} - -button.btn.btn-large, -input[type="submit"].btn.btn-large { - *padding-top: 7px; - *padding-bottom: 7px; -} - -button.btn.btn-small, -input[type="submit"].btn.btn-small { - *padding-top: 3px; - *padding-bottom: 3px; -} - -button.btn.btn-mini, -input[type="submit"].btn.btn-mini { - *padding-top: 1px; - *padding-bottom: 1px; -} - -.btn-group { - position: relative; - *margin-left: .3em; - *zoom: 1; -} - -.btn-group:before, -.btn-group:after { - display: table; - content: ""; -} - -.btn-group:after { - clear: both; -} - -.btn-group:first-child { - *margin-left: 0; -} - -.btn-group + .btn-group { - margin-left: 5px; -} - -.btn-toolbar { - margin-top: 9px; - margin-bottom: 9px; -} - -.btn-toolbar .btn-group { - display: inline-block; - *display: inline; - /* IE7 inline-block hack */ - - *zoom: 1; -} - -.btn-group > .btn { - position: relative; - float: left; - margin-left: -1px; - -webkit-border-radius: 0; - -moz-border-radius: 0; - border-radius: 0; -} - -.btn-group > .btn:first-child { - margin-left: 0; - -webkit-border-bottom-left-radius: 4px; - border-bottom-left-radius: 4px; - -webkit-border-top-left-radius: 4px; - border-top-left-radius: 4px; - -moz-border-radius-bottomleft: 4px; - -moz-border-radius-topleft: 4px; -} - -.btn-group > .btn:last-child, -.btn-group > .dropdown-toggle { - -webkit-border-top-right-radius: 4px; - border-top-right-radius: 4px; - -webkit-border-bottom-right-radius: 4px; - border-bottom-right-radius: 4px; - -moz-border-radius-topright: 4px; - -moz-border-radius-bottomright: 4px; -} - -.btn-group > .btn.large:first-child { - margin-left: 0; - -webkit-border-bottom-left-radius: 6px; - border-bottom-left-radius: 6px; - -webkit-border-top-left-radius: 6px; - border-top-left-radius: 6px; - -moz-border-radius-bottomleft: 6px; - -moz-border-radius-topleft: 6px; -} - -.btn-group > .btn.large:last-child, -.btn-group > .large.dropdown-toggle { - -webkit-border-top-right-radius: 6px; - border-top-right-radius: 6px; - -webkit-border-bottom-right-radius: 6px; - border-bottom-right-radius: 6px; - -moz-border-radius-topright: 6px; - -moz-border-radius-bottomright: 6px; -} - -.btn-group > .btn:hover, -.btn-group > .btn:focus, -.btn-group > .btn:active, -.btn-group > .btn.active { - z-index: 2; -} - -.btn-group .dropdown-toggle:active, -.btn-group.open .dropdown-toggle { - outline: 0; -} - -.btn-group > .dropdown-toggle { - *padding-top: 4px; - padding-right: 8px; - *padding-bottom: 4px; - padding-left: 8px; - -webkit-box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); - -moz-box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); - box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); -} - -.btn-group > .btn-mini.dropdown-toggle { - padding-right: 5px; - padding-left: 5px; -} - -.btn-group > .btn-small.dropdown-toggle { - *padding-top: 4px; - *padding-bottom: 4px; -} - -.btn-group > .btn-large.dropdown-toggle { - padding-right: 12px; - padding-left: 12px; -} - -.btn-group.open .dropdown-toggle { - background-image: none; - -webkit-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05); - -moz-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05); - box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05); -} - -.btn-group.open .btn.dropdown-toggle { - background-color: #e6e6e6; -} - -.btn-group.open .btn-primary.dropdown-toggle { - background-color: #0055cc; -} - -.btn-group.open .btn-warning.dropdown-toggle { - background-color: #f89406; -} - -.btn-group.open .btn-danger.dropdown-toggle { - background-color: #bd362f; -} - -.btn-group.open .btn-success.dropdown-toggle { - background-color: #51a351; -} - -.btn-group.open .btn-info.dropdown-toggle { - background-color: #2f96b4; -} - -.btn-group.open .btn-inverse.dropdown-toggle { - background-color: #222222; -} - -.btn .caret { - margin-top: 7px; - margin-left: 0; -} - -.btn:hover .caret, -.open.btn-group .caret { - opacity: 1; - filter: alpha(opacity=100); -} - -.btn-mini .caret { - margin-top: 5px; -} - -.btn-small .caret { - margin-top: 6px; -} - -.btn-large .caret { - margin-top: 6px; - border-top-width: 5px; - border-right-width: 5px; - border-left-width: 5px; -} - -.dropup .btn-large .caret { - border-top: 0; - border-bottom: 5px solid #000000; -} - -.btn-primary .caret, -.btn-warning .caret, -.btn-danger .caret, -.btn-info .caret, -.btn-success .caret, -.btn-inverse .caret { - border-top-color: #ffffff; - border-bottom-color: #ffffff; - opacity: 0.75; - filter: alpha(opacity=75); -} - -.alert { - padding: 8px 35px 8px 14px; - margin-bottom: 18px; - color: #c09853; - text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5); - background-color: #fcf8e3; - border: 1px solid #fbeed5; - -webkit-border-radius: 4px; - -moz-border-radius: 4px; - border-radius: 4px; -} - -.alert-heading { - color: inherit; -} - -.alert .close { - position: relative; - top: -2px; - right: -21px; - line-height: 18px; -} - -.alert-success { - color: #468847; - background-color: #dff0d8; - border-color: #d6e9c6; -} - -.alert-danger, -.alert-error { - color: #b94a48; - background-color: #f2dede; - border-color: #eed3d7; -} - -.alert-info { - color: #3a87ad; - background-color: #d9edf7; - border-color: #bce8f1; -} - -.alert-block { - padding-top: 14px; - padding-bottom: 14px; -} - -.alert-block > p, -.alert-block > ul { - margin-bottom: 0; -} - -.alert-block p + p { - margin-top: 5px; -} - -.nav { - margin-bottom: 18px; - margin-left: 0; - list-style: none; -} - -.nav > li > a { - display: block; -} - -.nav > li > a:hover { - text-decoration: none; - background-color: #eeeeee; -} - -.nav > .pull-right { - float: right; -} - -.nav .nav-header { - display: block; - padding: 3px 15px; - font-size: 11px; - font-weight: bold; - line-height: 18px; - color: #999999; - text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5); - text-transform: uppercase; -} - -.nav li + .nav-header { - margin-top: 9px; -} - -.nav-list { - padding-right: 15px; - padding-left: 15px; - margin-bottom: 0; -} - -.nav-list > li > a, -.nav-list .nav-header { - margin-right: -15px; - margin-left: -15px; - text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5); -} - -.nav-list > li > a { - padding: 3px 15px; -} - -.nav-list > .active > a, -.nav-list > .active > a:hover { - color: #ffffff; - text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.2); - background-color: #0088cc; -} - -.nav-list [class^="icon-"] { - margin-right: 2px; -} - -.nav-list .divider { - *width: 100%; - height: 1px; - margin: 8px 1px; - *margin: -5px 0 5px; - overflow: hidden; - background-color: #e5e5e5; - border-bottom: 1px solid #ffffff; -} - -.nav-tabs, -.nav-pills { - *zoom: 1; -} - -.nav-tabs:before, -.nav-pills:before, -.nav-tabs:after, -.nav-pills:after { - display: table; - content: ""; -} - -.nav-tabs:after, -.nav-pills:after { - clear: both; -} - -.nav-tabs > li, -.nav-pills > li { - float: left; -} - -.nav-tabs > li > a, -.nav-pills > li > a { - padding-right: 12px; - padding-left: 12px; - margin-right: 2px; - line-height: 14px; -} - -.nav-tabs { - border-bottom: 1px solid #ddd; -} - -.nav-tabs > li { - margin-bottom: -1px; -} - -.nav-tabs > li > a { - padding-top: 8px; - padding-bottom: 8px; - line-height: 18px; - border: 1px solid transparent; - -webkit-border-radius: 4px 4px 0 0; - -moz-border-radius: 4px 4px 0 0; - border-radius: 4px 4px 0 0; -} - -.nav-tabs > li > a:hover { - border-color: #eeeeee #eeeeee #dddddd; -} - -.nav-tabs > .active > a, -.nav-tabs > .active > a:hover { - color: #555555; - cursor: default; - background-color: #ffffff; - border: 1px solid #ddd; - border-bottom-color: transparent; -} - -.nav-pills > li > a { - padding-top: 8px; - padding-bottom: 8px; - margin-top: 2px; - margin-bottom: 2px; - -webkit-border-radius: 5px; - -moz-border-radius: 5px; - border-radius: 5px; -} - -.nav-pills > .active > a, -.nav-pills > .active > a:hover { - color: #ffffff; - background-color: #0088cc; -} - -.nav-stacked > li { - float: none; -} - -.nav-stacked > li > a { - margin-right: 0; -} - -.nav-tabs.nav-stacked { - border-bottom: 0; -} - -.nav-tabs.nav-stacked > li > a { - border: 1px solid #ddd; - -webkit-border-radius: 0; - -moz-border-radius: 0; - border-radius: 0; -} - -.nav-tabs.nav-stacked > li:first-child > a { - -webkit-border-radius: 4px 4px 0 0; - -moz-border-radius: 4px 4px 0 0; - border-radius: 4px 4px 0 0; -} - -.nav-tabs.nav-stacked > li:last-child > a { - -webkit-border-radius: 0 0 4px 4px; - -moz-border-radius: 0 0 4px 4px; - border-radius: 0 0 4px 4px; -} - -.nav-tabs.nav-stacked > li > a:hover { - z-index: 2; - border-color: #ddd; -} - -.nav-pills.nav-stacked > li > a { - margin-bottom: 3px; -} - -.nav-pills.nav-stacked > li:last-child > a { - margin-bottom: 1px; -} - -.nav-tabs .dropdown-menu { - -webkit-border-radius: 0 0 5px 5px; - -moz-border-radius: 0 0 5px 5px; - border-radius: 0 0 5px 5px; -} - -.nav-pills .dropdown-menu { - -webkit-border-radius: 4px; - -moz-border-radius: 4px; - border-radius: 4px; -} - -.nav-tabs .dropdown-toggle .caret, -.nav-pills .dropdown-toggle .caret { - margin-top: 6px; - border-top-color: #0088cc; - border-bottom-color: #0088cc; -} - -.nav-tabs .dropdown-toggle:hover .caret, -.nav-pills .dropdown-toggle:hover .caret { - border-top-color: #005580; - border-bottom-color: #005580; -} - -.nav-tabs .active .dropdown-toggle .caret, -.nav-pills .active .dropdown-toggle .caret { - border-top-color: #333333; - border-bottom-color: #333333; -} - -.nav > .dropdown.active > a:hover { - color: #000000; - cursor: pointer; -} - -.nav-tabs .open .dropdown-toggle, -.nav-pills .open .dropdown-toggle, -.nav > li.dropdown.open.active > a:hover { - color: #ffffff; - background-color: #999999; - border-color: #999999; -} - -.nav li.dropdown.open .caret, -.nav li.dropdown.open.active .caret, -.nav li.dropdown.open a:hover .caret { - border-top-color: #ffffff; - border-bottom-color: #ffffff; - opacity: 1; - filter: alpha(opacity=100); -} - -.tabs-stacked .open > a:hover { - border-color: #999999; -} - -.tabbable { - *zoom: 1; -} - -.tabbable:before, -.tabbable:after { - display: table; - content: ""; -} - -.tabbable:after { - clear: both; -} - -.tab-content { - overflow: auto; -} - -.tabs-below > .nav-tabs, -.tabs-right > .nav-tabs, -.tabs-left > .nav-tabs { - border-bottom: 0; -} - -.tab-content > .tab-pane, -.pill-content > .pill-pane { - display: none; -} - -.tab-content > .active, -.pill-content > .active { - display: block; -} - -.tabs-below > .nav-tabs { - border-top: 1px solid #ddd; -} - -.tabs-below > .nav-tabs > li { - margin-top: -1px; - margin-bottom: 0; -} - -.tabs-below > .nav-tabs > li > a { - -webkit-border-radius: 0 0 4px 4px; - -moz-border-radius: 0 0 4px 4px; - border-radius: 0 0 4px 4px; -} - -.tabs-below > .nav-tabs > li > a:hover { - border-top-color: #ddd; - border-bottom-color: transparent; -} - -.tabs-below > .nav-tabs > .active > a, -.tabs-below > .nav-tabs > .active > a:hover { - border-color: transparent #ddd #ddd #ddd; -} - -.tabs-left > .nav-tabs > li, -.tabs-right > .nav-tabs > li { - float: none; -} - -.tabs-left > .nav-tabs > li > a, -.tabs-right > .nav-tabs > li > a { - min-width: 74px; - margin-right: 0; - margin-bottom: 3px; -} - -.tabs-left > .nav-tabs { - float: left; - margin-right: 19px; - border-right: 1px solid #ddd; -} - -.tabs-left > .nav-tabs > li > a { - margin-right: -1px; - -webkit-border-radius: 4px 0 0 4px; - -moz-border-radius: 4px 0 0 4px; - border-radius: 4px 0 0 4px; -} - -.tabs-left > .nav-tabs > li > a:hover { - border-color: #eeeeee #dddddd #eeeeee #eeeeee; -} - -.tabs-left > .nav-tabs .active > a, -.tabs-left > .nav-tabs .active > a:hover { - border-color: #ddd transparent #ddd #ddd; - *border-right-color: #ffffff; -} - -.tabs-right > .nav-tabs { - float: right; - margin-left: 19px; - border-left: 1px solid #ddd; -} - -.tabs-right > .nav-tabs > li > a { - margin-left: -1px; - -webkit-border-radius: 0 4px 4px 0; - -moz-border-radius: 0 4px 4px 0; - border-radius: 0 4px 4px 0; -} - -.tabs-right > .nav-tabs > li > a:hover { - border-color: #eeeeee #eeeeee #eeeeee #dddddd; -} - -.tabs-right > .nav-tabs .active > a, -.tabs-right > .nav-tabs .active > a:hover { - border-color: #ddd #ddd #ddd transparent; - *border-left-color: #ffffff; -} - -.navbar { - *position: relative; - *z-index: 2; - margin-bottom: 18px; - overflow: visible; -} - -.navbar-inner { - min-height: 40px; - padding-right: 20px; - padding-left: 20px; - background-color: #2c2c2c; - background-image: -moz-linear-gradient(top, #333333, #222222); - background-image: -ms-linear-gradient(top, #333333, #222222); - background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#333333), to(#222222)); - background-image: -webkit-linear-gradient(top, #333333, #222222); - background-image: -o-linear-gradient(top, #333333, #222222); - background-image: linear-gradient(top, #333333, #222222); - background-repeat: repeat-x; - -webkit-border-radius: 4px; - -moz-border-radius: 4px; - border-radius: 4px; - filter: progid:dximagetransform.microsoft.gradient(startColorstr='#333333', endColorstr='#222222', GradientType=0); - -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.25), inset 0 -1px 0 rgba(0, 0, 0, 0.1); - -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.25), inset 0 -1px 0 rgba(0, 0, 0, 0.1); - box-shadow: 0 1px 3px rgba(0, 0, 0, 0.25), inset 0 -1px 0 rgba(0, 0, 0, 0.1); -} - -.navbar .container { - width: auto; -} - -.nav-collapse.collapse { - height: auto; -} - -.navbar { - color: #999999; -} - -.navbar .brand:hover { - text-decoration: none; -} - -.navbar .brand { - display: block; - float: left; - padding: 8px 20px 12px; - margin-left: -20px; - font-size: 20px; - font-weight: 200; - line-height: 1; - color: #999999; -} - -.navbar .navbar-text { - margin-bottom: 0; - line-height: 40px; -} - -.navbar .navbar-link { - color: #999999; -} - -.navbar .navbar-link:hover { - color: #ffffff; -} - -.navbar .btn, -.navbar .btn-group { - margin-top: 5px; -} - -.navbar .btn-group .btn { - margin: 0; -} - -.navbar-form { - margin-bottom: 0; - *zoom: 1; -} - -.navbar-form:before, -.navbar-form:after { - display: table; - content: ""; -} - -.navbar-form:after { - clear: both; -} - -.navbar-form input, -.navbar-form select, -.navbar-form .radio, -.navbar-form .checkbox { - margin-top: 5px; -} - -.navbar-form input, -.navbar-form select { - display: inline-block; - margin-bottom: 0; -} - -.navbar-form input[type="image"], -.navbar-form input[type="checkbox"], -.navbar-form input[type="radio"] { - margin-top: 3px; -} - -.navbar-form .input-append, -.navbar-form .input-prepend { - margin-top: 6px; - white-space: nowrap; -} - -.navbar-form .input-append input, -.navbar-form .input-prepend input { - margin-top: 0; -} - -.navbar-search { - position: relative; - float: left; - margin-top: 6px; - margin-bottom: 0; -} - -.navbar-search .search-query { - padding: 4px 9px; - font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; - font-size: 13px; - font-weight: normal; - line-height: 1; - color: #ffffff; - background-color: #626262; - border: 1px solid #151515; - -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15); - -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15); - box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15); - -webkit-transition: none; - -moz-transition: none; - -ms-transition: none; - -o-transition: none; - transition: none; -} - -.navbar-search .search-query:-moz-placeholder { - color: #cccccc; -} - -.navbar-search .search-query:-ms-input-placeholder { - color: #cccccc; -} - -.navbar-search .search-query::-webkit-input-placeholder { - color: #cccccc; -} - -.navbar-search .search-query:focus, -.navbar-search .search-query.focused { - padding: 5px 10px; - color: #333333; - text-shadow: 0 1px 0 #ffffff; - background-color: #ffffff; - border: 0; - outline: 0; - -webkit-box-shadow: 0 0 3px rgba(0, 0, 0, 0.15); - -moz-box-shadow: 0 0 3px rgba(0, 0, 0, 0.15); - box-shadow: 0 0 3px rgba(0, 0, 0, 0.15); -} - -.navbar-fixed-top, -.navbar-fixed-bottom { - position: fixed; - right: 0; - left: 0; - z-index: 1030; - margin-bottom: 0; -} - -.navbar-fixed-top .navbar-inner, -.navbar-fixed-bottom .navbar-inner { - padding-right: 0; - padding-left: 0; - -webkit-border-radius: 0; - -moz-border-radius: 0; - border-radius: 0; -} - -.navbar-fixed-top .container, -.navbar-fixed-bottom .container { - width: 940px; -} - -.navbar-fixed-top { - top: 0; -} - -.navbar-fixed-bottom { - bottom: 0; -} - -.navbar .nav { - position: relative; - left: 0; - display: block; - float: left; - margin: 0 10px 0 0; -} - -.navbar .nav.pull-right { - float: right; -} - -.navbar .nav > li { - display: block; - float: left; -} - -.navbar .nav > li > a { - float: none; - padding: 9px 10px 11px; - line-height: 19px; - color: #999999; - text-decoration: none; - text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); -} - -.navbar .btn { - display: inline-block; - padding: 4px 10px 4px; - margin: 5px 5px 6px; - line-height: 18px; -} - -.navbar .btn-group { - padding: 5px 5px 6px; - margin: 0; -} - -.navbar .nav > li > a:hover { - color: #ffffff; - text-decoration: none; - background-color: transparent; -} - -.navbar .nav .active > a, -.navbar .nav .active > a:hover { - color: #ffffff; - text-decoration: none; - background-color: #222222; -} - -.navbar .divider-vertical { - width: 1px; - height: 40px; - margin: 0 9px; - overflow: hidden; - background-color: #222222; - border-right: 1px solid #333333; -} - -.navbar .nav.pull-right { - margin-right: 0; - margin-left: 10px; -} - -.navbar .btn-navbar { - display: none; - float: right; - padding: 7px 10px; - margin-right: 5px; - margin-left: 5px; - background-color: #2c2c2c; - *background-color: #222222; - background-image: -ms-linear-gradient(top, #333333, #222222); - background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#333333), to(#222222)); - background-image: -webkit-linear-gradient(top, #333333, #222222); - background-image: -o-linear-gradient(top, #333333, #222222); - background-image: linear-gradient(top, #333333, #222222); - background-image: -moz-linear-gradient(top, #333333, #222222); - background-repeat: repeat-x; - border-color: #222222 #222222 #000000; - border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); - filter: progid:dximagetransform.microsoft.gradient(startColorstr='#333333', endColorstr='#222222', GradientType=0); - filter: progid:dximagetransform.microsoft.gradient(enabled=false); - -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075); - -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075); - box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075); -} - -.navbar .btn-navbar:hover, -.navbar .btn-navbar:active, -.navbar .btn-navbar.active, -.navbar .btn-navbar.disabled, -.navbar .btn-navbar[disabled] { - background-color: #222222; - *background-color: #151515; -} - -.navbar .btn-navbar:active, -.navbar .btn-navbar.active { - background-color: #080808 \9; -} - -.navbar .btn-navbar .icon-bar { - display: block; - width: 18px; - height: 2px; - background-color: #f5f5f5; - -webkit-border-radius: 1px; - -moz-border-radius: 1px; - border-radius: 1px; - -webkit-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25); - -moz-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25); - box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25); -} - -.btn-navbar .icon-bar + .icon-bar { - margin-top: 3px; -} - -.navbar .dropdown-menu:before { - position: absolute; - top: -7px; - left: 9px; - display: inline-block; - border-right: 7px solid transparent; - border-bottom: 7px solid #ccc; - border-left: 7px solid transparent; - border-bottom-color: rgba(0, 0, 0, 0.2); - content: ''; -} - -.navbar .dropdown-menu:after { - position: absolute; - top: -6px; - left: 10px; - display: inline-block; - border-right: 6px solid transparent; - border-bottom: 6px solid #ffffff; - border-left: 6px solid transparent; - content: ''; -} - -.navbar-fixed-bottom .dropdown-menu:before { - top: auto; - bottom: -7px; - border-top: 7px solid #ccc; - border-bottom: 0; - border-top-color: rgba(0, 0, 0, 0.2); -} - -.navbar-fixed-bottom .dropdown-menu:after { - top: auto; - bottom: -6px; - border-top: 6px solid #ffffff; - border-bottom: 0; -} - -.navbar .nav li.dropdown .dropdown-toggle .caret, -.navbar .nav li.dropdown.open .caret { - border-top-color: #ffffff; - border-bottom-color: #ffffff; -} - -.navbar .nav li.dropdown.active .caret { - opacity: 1; - filter: alpha(opacity=100); -} - -.navbar .nav li.dropdown.open > .dropdown-toggle, -.navbar .nav li.dropdown.active > .dropdown-toggle, -.navbar .nav li.dropdown.open.active > .dropdown-toggle { - background-color: transparent; -} - -.navbar .nav li.dropdown.active > .dropdown-toggle:hover { - color: #ffffff; -} - -.navbar .pull-right .dropdown-menu, -.navbar .dropdown-menu.pull-right { - right: 0; - left: auto; -} - -.navbar .pull-right .dropdown-menu:before, -.navbar .dropdown-menu.pull-right:before { - right: 12px; - left: auto; -} - -.navbar .pull-right .dropdown-menu:after, -.navbar .dropdown-menu.pull-right:after { - right: 13px; - left: auto; -} - -.breadcrumb { - padding: 7px 14px; - margin: 0 0 18px; - list-style: none; - background-color: #fbfbfb; - background-image: -moz-linear-gradient(top, #ffffff, #f5f5f5); - background-image: -ms-linear-gradient(top, #ffffff, #f5f5f5); - background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#f5f5f5)); - background-image: -webkit-linear-gradient(top, #ffffff, #f5f5f5); - background-image: -o-linear-gradient(top, #ffffff, #f5f5f5); - background-image: linear-gradient(top, #ffffff, #f5f5f5); - background-repeat: repeat-x; - border: 1px solid #ddd; - -webkit-border-radius: 3px; - -moz-border-radius: 3px; - border-radius: 3px; - filter: progid:dximagetransform.microsoft.gradient(startColorstr='#ffffff', endColorstr='#f5f5f5', GradientType=0); - -webkit-box-shadow: inset 0 1px 0 #ffffff; - -moz-box-shadow: inset 0 1px 0 #ffffff; - box-shadow: inset 0 1px 0 #ffffff; -} - -.breadcrumb li { - display: inline-block; - *display: inline; - text-shadow: 0 1px 0 #ffffff; - *zoom: 1; -} - -.breadcrumb .divider { - padding: 0 5px; - color: #999999; -} - -.breadcrumb .active a { - color: #333333; -} - -.pagination { - height: 36px; - margin: 18px 0; -} - -.pagination ul { - display: inline-block; - *display: inline; - margin-bottom: 0; - margin-left: 0; - -webkit-border-radius: 3px; - -moz-border-radius: 3px; - border-radius: 3px; - *zoom: 1; - -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05); - -moz-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05); - box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05); -} - -.pagination li { - display: inline; -} - -.pagination a { - float: left; - padding: 0 14px; - line-height: 34px; - text-decoration: none; - border: 1px solid #ddd; - border-left-width: 0; -} - -.pagination a:hover, -.pagination .active a { - background-color: #f5f5f5; -} - -.pagination .active a { - color: #999999; - cursor: default; -} - -.pagination .disabled span, -.pagination .disabled a, -.pagination .disabled a:hover { - color: #999999; - cursor: default; - background-color: transparent; -} - -.pagination li:first-child a { - border-left-width: 1px; - -webkit-border-radius: 3px 0 0 3px; - -moz-border-radius: 3px 0 0 3px; - border-radius: 3px 0 0 3px; -} - -.pagination li:last-child a { - -webkit-border-radius: 0 3px 3px 0; - -moz-border-radius: 0 3px 3px 0; - border-radius: 0 3px 3px 0; -} - -.pagination-centered { - text-align: center; -} - -.pagination-right { - text-align: right; -} - -.pager { - margin-bottom: 18px; - margin-left: 0; - text-align: center; - list-style: none; - *zoom: 1; -} - -.pager:before, -.pager:after { - display: table; - content: ""; -} - -.pager:after { - clear: both; -} - -.pager li { - display: inline; -} - -.pager a { - display: inline-block; - padding: 5px 14px; - background-color: #fff; - border: 1px solid #ddd; - -webkit-border-radius: 15px; - -moz-border-radius: 15px; - border-radius: 15px; -} - -.pager a:hover { - text-decoration: none; - background-color: #f5f5f5; -} - -.pager .next a { - float: right; -} - -.pager .previous a { - float: left; -} - -.pager .disabled a, -.pager .disabled a:hover { - color: #999999; - cursor: default; - background-color: #fff; -} - -.modal-open .dropdown-menu { - z-index: 2050; -} - -.modal-open .dropdown.open { - *z-index: 2050; -} - -.modal-open .popover { - z-index: 2060; -} - -.modal-open .tooltip { - z-index: 2070; -} - -.modal-backdrop { - position: fixed; - top: 0; - right: 0; - bottom: 0; - left: 0; - z-index: 1040; - background-color: #000000; -} - -.modal-backdrop.fade { - opacity: 0; -} - -.modal-backdrop, -.modal-backdrop.fade.in { - opacity: 0.8; - filter: alpha(opacity=80); -} - -.modal { - position: fixed; - top: 50%; - left: 50%; - z-index: 1050; - width: 560px; - margin: -250px 0 0 -280px; - overflow: auto; - background-color: #ffffff; - border: 1px solid #999; - border: 1px solid rgba(0, 0, 0, 0.3); - *border: 1px solid #999; - -webkit-border-radius: 6px; - -moz-border-radius: 6px; - border-radius: 6px; - -webkit-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3); - -moz-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3); - box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3); - -webkit-background-clip: padding-box; - -moz-background-clip: padding-box; - background-clip: padding-box; -} - -.modal.fade { - top: -25%; - -webkit-transition: opacity 0.3s linear, top 0.3s ease-out; - -moz-transition: opacity 0.3s linear, top 0.3s ease-out; - -ms-transition: opacity 0.3s linear, top 0.3s ease-out; - -o-transition: opacity 0.3s linear, top 0.3s ease-out; - transition: opacity 0.3s linear, top 0.3s ease-out; -} - -.modal.fade.in { - top: 50%; -} - -.modal-header { - padding: 9px 15px; - border-bottom: 1px solid #eee; -} - -.modal-header .close { - margin-top: 2px; -} - -.modal-body { - max-height: 400px; - padding: 15px; - overflow-y: auto; -} - -.modal-form { - margin-bottom: 0; -} - -.modal-footer { - padding: 14px 15px 15px; - margin-bottom: 0; - text-align: right; - background-color: #f5f5f5; - border-top: 1px solid #ddd; - -webkit-border-radius: 0 0 6px 6px; - -moz-border-radius: 0 0 6px 6px; - border-radius: 0 0 6px 6px; - *zoom: 1; - -webkit-box-shadow: inset 0 1px 0 #ffffff; - -moz-box-shadow: inset 0 1px 0 #ffffff; - box-shadow: inset 0 1px 0 #ffffff; -} - -.modal-footer:before, -.modal-footer:after { - display: table; - content: ""; -} - -.modal-footer:after { - clear: both; -} - -.modal-footer .btn + .btn { - margin-bottom: 0; - margin-left: 5px; -} - -.modal-footer .btn-group .btn + .btn { - margin-left: -1px; -} - -.tooltip { - position: absolute; - z-index: 1020; - display: block; - padding: 5px; - font-size: 11px; - opacity: 0; - filter: alpha(opacity=0); - visibility: visible; -} - -.tooltip.in { - opacity: 0.8; - filter: alpha(opacity=80); -} - -.tooltip.top { - margin-top: -2px; -} - -.tooltip.right { - margin-left: 2px; -} - -.tooltip.bottom { - margin-top: 2px; -} - -.tooltip.left { - margin-left: -2px; -} - -.tooltip.top .tooltip-arrow { - bottom: 0; - left: 50%; - margin-left: -5px; - border-top: 5px solid #000000; - border-right: 5px solid transparent; - border-left: 5px solid transparent; -} - -.tooltip.left .tooltip-arrow { - top: 50%; - right: 0; - margin-top: -5px; - border-top: 5px solid transparent; - border-bottom: 5px solid transparent; - border-left: 5px solid #000000; -} - -.tooltip.bottom .tooltip-arrow { - top: 0; - left: 50%; - margin-left: -5px; - border-right: 5px solid transparent; - border-bottom: 5px solid #000000; - border-left: 5px solid transparent; -} - -.tooltip.right .tooltip-arrow { - top: 50%; - left: 0; - margin-top: -5px; - border-top: 5px solid transparent; - border-right: 5px solid #000000; - border-bottom: 5px solid transparent; -} - -.tooltip-inner { - max-width: 200px; - padding: 3px 8px; - color: #ffffff; - text-align: center; - text-decoration: none; - background-color: #000000; - -webkit-border-radius: 4px; - -moz-border-radius: 4px; - border-radius: 4px; -} - -.tooltip-arrow { - position: absolute; - width: 0; - height: 0; -} - -.popover { - position: absolute; - top: 0; - left: 0; - z-index: 1010; - display: none; - padding: 5px; -} - -.popover.top { - margin-top: -5px; -} - -.popover.right { - margin-left: 5px; -} - -.popover.bottom { - margin-top: 5px; -} - -.popover.left { - margin-left: -5px; -} - -.popover.top .arrow { - bottom: 0; - left: 50%; - margin-left: -5px; - border-top: 5px solid #000000; - border-right: 5px solid transparent; - border-left: 5px solid transparent; -} - -.popover.right .arrow { - top: 50%; - left: 0; - margin-top: -5px; - border-top: 5px solid transparent; - border-right: 5px solid #000000; - border-bottom: 5px solid transparent; -} - -.popover.bottom .arrow { - top: 0; - left: 50%; - margin-left: -5px; - border-right: 5px solid transparent; - border-bottom: 5px solid #000000; - border-left: 5px solid transparent; -} - -.popover.left .arrow { - top: 50%; - right: 0; - margin-top: -5px; - border-top: 5px solid transparent; - border-bottom: 5px solid transparent; - border-left: 5px solid #000000; -} - -.popover .arrow { - position: absolute; - width: 0; - height: 0; -} - -.popover-inner { - width: 280px; - padding: 3px; - overflow: hidden; - background: #000000; - background: rgba(0, 0, 0, 0.8); - -webkit-border-radius: 6px; - -moz-border-radius: 6px; - border-radius: 6px; - -webkit-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3); - -moz-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3); - box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3); -} - -.popover-title { - padding: 9px 15px; - line-height: 1; - background-color: #f5f5f5; - border-bottom: 1px solid #eee; - -webkit-border-radius: 3px 3px 0 0; - -moz-border-radius: 3px 3px 0 0; - border-radius: 3px 3px 0 0; -} - -.popover-content { - padding: 14px; - background-color: #ffffff; - -webkit-border-radius: 0 0 3px 3px; - -moz-border-radius: 0 0 3px 3px; - border-radius: 0 0 3px 3px; - -webkit-background-clip: padding-box; - -moz-background-clip: padding-box; - background-clip: padding-box; -} - -.popover-content p, -.popover-content ul, -.popover-content ol { - margin-bottom: 0; -} - -.thumbnails { - margin-left: -20px; - list-style: none; - *zoom: 1; -} - -.thumbnails:before, -.thumbnails:after { - display: table; - content: ""; -} - -.thumbnails:after { - clear: both; -} - -.row-fluid .thumbnails { - margin-left: 0; -} - -.thumbnails > li { - float: left; - margin-bottom: 18px; - margin-left: 20px; -} - -.thumbnail { - display: block; - padding: 4px; - line-height: 1; - border: 1px solid #ddd; - -webkit-border-radius: 4px; - -moz-border-radius: 4px; - border-radius: 4px; - -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, 0.075); - -moz-box-shadow: 0 1px 1px rgba(0, 0, 0, 0.075); - box-shadow: 0 1px 1px rgba(0, 0, 0, 0.075); -} - -a.thumbnail:hover { - border-color: #0088cc; - -webkit-box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25); - -moz-box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25); - box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25); -} - -.thumbnail > img { - display: block; - max-width: 100%; - margin-right: auto; - margin-left: auto; -} - -.thumbnail .caption { - padding: 9px; -} - -.label, -.badge { - font-size: 10.998px; - font-weight: bold; - line-height: 14px; - color: #ffffff; - text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); - white-space: nowrap; - vertical-align: baseline; - background-color: #999999; -} - -.label { - padding: 1px 4px 2px; - -webkit-border-radius: 3px; - -moz-border-radius: 3px; - border-radius: 3px; -} - -.badge { - padding: 1px 9px 2px; - -webkit-border-radius: 9px; - -moz-border-radius: 9px; - border-radius: 9px; -} - -a.label:hover, -a.badge:hover { - color: #ffffff; - text-decoration: none; - cursor: pointer; -} - -.label-important, -.badge-important { - background-color: #b94a48; -} - -.label-important[href], -.badge-important[href] { - background-color: #953b39; -} - -.label-warning, -.badge-warning { - background-color: #f89406; -} - -.label-warning[href], -.badge-warning[href] { - background-color: #c67605; -} - -.label-success, -.badge-success { - background-color: #468847; -} - -.label-success[href], -.badge-success[href] { - background-color: #356635; -} - -.label-info, -.badge-info { - background-color: #3a87ad; -} - -.label-info[href], -.badge-info[href] { - background-color: #2d6987; -} - -.label-inverse, -.badge-inverse { - background-color: #333333; -} - -.label-inverse[href], -.badge-inverse[href] { - background-color: #1a1a1a; -} - -@-webkit-keyframes progress-bar-stripes { - from { - background-position: 40px 0; - } - to { - background-position: 0 0; - } -} - -@-moz-keyframes progress-bar-stripes { - from { - background-position: 40px 0; - } - to { - background-position: 0 0; - } -} - -@-ms-keyframes progress-bar-stripes { - from { - background-position: 40px 0; - } - to { - background-position: 0 0; - } -} - -@-o-keyframes progress-bar-stripes { - from { - background-position: 0 0; - } - to { - background-position: 40px 0; - } -} - -@keyframes progress-bar-stripes { - from { - background-position: 40px 0; - } - to { - background-position: 0 0; - } -} - -.progress { - height: 18px; - margin-bottom: 18px; - overflow: hidden; - background-color: #f7f7f7; - background-image: -moz-linear-gradient(top, #f5f5f5, #f9f9f9); - background-image: -ms-linear-gradient(top, #f5f5f5, #f9f9f9); - background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f5f5f5), to(#f9f9f9)); - background-image: -webkit-linear-gradient(top, #f5f5f5, #f9f9f9); - background-image: -o-linear-gradient(top, #f5f5f5, #f9f9f9); - background-image: linear-gradient(top, #f5f5f5, #f9f9f9); - background-repeat: repeat-x; - -webkit-border-radius: 4px; - -moz-border-radius: 4px; - border-radius: 4px; - filter: progid:dximagetransform.microsoft.gradient(startColorstr='#f5f5f5', endColorstr='#f9f9f9', GradientType=0); - -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1); - -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1); - box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1); -} - -.progress .bar { - width: 0; - height: 18px; - font-size: 12px; - color: #ffffff; - text-align: center; - text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); - background-color: #0e90d2; - background-image: -moz-linear-gradient(top, #149bdf, #0480be); - background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#149bdf), to(#0480be)); - background-image: -webkit-linear-gradient(top, #149bdf, #0480be); - background-image: -o-linear-gradient(top, #149bdf, #0480be); - background-image: linear-gradient(top, #149bdf, #0480be); - background-image: -ms-linear-gradient(top, #149bdf, #0480be); - background-repeat: repeat-x; - filter: progid:dximagetransform.microsoft.gradient(startColorstr='#149bdf', endColorstr='#0480be', GradientType=0); - -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15); - -moz-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15); - box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15); - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - -ms-box-sizing: border-box; - box-sizing: border-box; - -webkit-transition: width 0.6s ease; - -moz-transition: width 0.6s ease; - -ms-transition: width 0.6s ease; - -o-transition: width 0.6s ease; - transition: width 0.6s ease; -} - -.progress-striped .bar { - background-color: #149bdf; - background-image: -o-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - background-image: -webkit-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - background-image: -moz-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - background-image: -ms-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent)); - background-image: linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - -webkit-background-size: 40px 40px; - -moz-background-size: 40px 40px; - -o-background-size: 40px 40px; - background-size: 40px 40px; -} - -.progress.active .bar { - -webkit-animation: progress-bar-stripes 2s linear infinite; - -moz-animation: progress-bar-stripes 2s linear infinite; - -ms-animation: progress-bar-stripes 2s linear infinite; - -o-animation: progress-bar-stripes 2s linear infinite; - animation: progress-bar-stripes 2s linear infinite; -} - -.progress-danger .bar { - background-color: #dd514c; - background-image: -moz-linear-gradient(top, #ee5f5b, #c43c35); - background-image: -ms-linear-gradient(top, #ee5f5b, #c43c35); - background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ee5f5b), to(#c43c35)); - background-image: -webkit-linear-gradient(top, #ee5f5b, #c43c35); - background-image: -o-linear-gradient(top, #ee5f5b, #c43c35); - background-image: linear-gradient(top, #ee5f5b, #c43c35); - background-repeat: repeat-x; - filter: progid:dximagetransform.microsoft.gradient(startColorstr='#ee5f5b', endColorstr='#c43c35', GradientType=0); -} - -.progress-danger.progress-striped .bar { - background-color: #ee5f5b; - background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent)); - background-image: -webkit-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - background-image: -moz-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - background-image: -ms-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - background-image: -o-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - background-image: linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); -} - -.progress-success .bar { - background-color: #5eb95e; - background-image: -moz-linear-gradient(top, #62c462, #57a957); - background-image: -ms-linear-gradient(top, #62c462, #57a957); - background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#62c462), to(#57a957)); - background-image: -webkit-linear-gradient(top, #62c462, #57a957); - background-image: -o-linear-gradient(top, #62c462, #57a957); - background-image: linear-gradient(top, #62c462, #57a957); - background-repeat: repeat-x; - filter: progid:dximagetransform.microsoft.gradient(startColorstr='#62c462', endColorstr='#57a957', GradientType=0); -} - -.progress-success.progress-striped .bar { - background-color: #62c462; - background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent)); - background-image: -webkit-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - background-image: -moz-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - background-image: -ms-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - background-image: -o-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - background-image: linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); -} - -.progress-info .bar { - background-color: #4bb1cf; - background-image: -moz-linear-gradient(top, #5bc0de, #339bb9); - background-image: -ms-linear-gradient(top, #5bc0de, #339bb9); - background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#5bc0de), to(#339bb9)); - background-image: -webkit-linear-gradient(top, #5bc0de, #339bb9); - background-image: -o-linear-gradient(top, #5bc0de, #339bb9); - background-image: linear-gradient(top, #5bc0de, #339bb9); - background-repeat: repeat-x; - filter: progid:dximagetransform.microsoft.gradient(startColorstr='#5bc0de', endColorstr='#339bb9', GradientType=0); -} - -.progress-info.progress-striped .bar { - background-color: #5bc0de; - background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent)); - background-image: -webkit-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - background-image: -moz-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - background-image: -ms-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - background-image: -o-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - background-image: linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); -} - -.progress-warning .bar { - background-color: #faa732; - background-image: -moz-linear-gradient(top, #fbb450, #f89406); - background-image: -ms-linear-gradient(top, #fbb450, #f89406); - background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fbb450), to(#f89406)); - background-image: -webkit-linear-gradient(top, #fbb450, #f89406); - background-image: -o-linear-gradient(top, #fbb450, #f89406); - background-image: linear-gradient(top, #fbb450, #f89406); - background-repeat: repeat-x; - filter: progid:dximagetransform.microsoft.gradient(startColorstr='#fbb450', endColorstr='#f89406', GradientType=0); -} - -.progress-warning.progress-striped .bar { - background-color: #fbb450; - background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent)); - background-image: -webkit-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - background-image: -moz-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - background-image: -ms-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - background-image: -o-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - background-image: linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); -} - -.accordion { - margin-bottom: 18px; -} - -.accordion-group { - margin-bottom: 2px; - border: 1px solid #e5e5e5; - -webkit-border-radius: 4px; - -moz-border-radius: 4px; - border-radius: 4px; -} - -.accordion-heading { - border-bottom: 0; -} - -.accordion-heading .accordion-toggle { - display: block; - padding: 8px 15px; -} - -.accordion-toggle { - cursor: pointer; -} - -.accordion-inner { - padding: 9px 15px; - border-top: 1px solid #e5e5e5; -} - -.carousel { - position: relative; - margin-bottom: 18px; - line-height: 1; -} - -.carousel-inner { - position: relative; - width: 100%; - overflow: hidden; -} - -.carousel .item { - position: relative; - display: none; - -webkit-transition: 0.6s ease-in-out left; - -moz-transition: 0.6s ease-in-out left; - -ms-transition: 0.6s ease-in-out left; - -o-transition: 0.6s ease-in-out left; - transition: 0.6s ease-in-out left; -} - -.carousel .item > img { - display: block; - line-height: 1; -} - -.carousel .active, -.carousel .next, -.carousel .prev { - display: block; -} - -.carousel .active { - left: 0; -} - -.carousel .next, -.carousel .prev { - position: absolute; - top: 0; - width: 100%; -} - -.carousel .next { - left: 100%; -} - -.carousel .prev { - left: -100%; -} - -.carousel .next.left, -.carousel .prev.right { - left: 0; -} - -.carousel .active.left { - left: -100%; -} - -.carousel .active.right { - left: 100%; -} - -.carousel-control { - position: absolute; - top: 40%; - left: 15px; - width: 40px; - height: 40px; - margin-top: -20px; - font-size: 60px; - font-weight: 100; - line-height: 30px; - color: #ffffff; - text-align: center; - background: #222222; - border: 3px solid #ffffff; - -webkit-border-radius: 23px; - -moz-border-radius: 23px; - border-radius: 23px; - opacity: 0.5; - filter: alpha(opacity=50); -} - -.carousel-control.right { - right: 15px; - left: auto; -} - -.carousel-control:hover { - color: #ffffff; - text-decoration: none; - opacity: 0.9; - filter: alpha(opacity=90); -} - -.carousel-caption { - position: absolute; - right: 0; - bottom: 0; - left: 0; - padding: 10px 15px 5px; - background: #333333; - background: rgba(0, 0, 0, 0.75); -} - -.carousel-caption h4, -.carousel-caption p { - color: #ffffff; -} - -.hero-unit { - padding: 30px; - margin-bottom: 30px; - background-color: #eeeeee; - -webkit-border-radius: 6px; - -moz-border-radius: 6px; - border-radius: 6px; -} - -.hero-unit h1 { - margin-bottom: 0; - font-size: 60px; - line-height: 1; - letter-spacing: -1px; - color: inherit; -} - -.hero-unit p { - font-size: 18px; - font-weight: 200; - line-height: 27px; - color: inherit; -} - -.pull-right { - float: right; -} - -.pull-left { - float: left; -} - -.hide { - display: none; -} - -.show { - display: block; -} - -.invisible { - visibility: hidden; -} diff --git a/www/assets/css/bootstrap.min.css b/www/assets/css/bootstrap.min.css deleted file mode 100755 index b74b4546..00000000 --- a/www/assets/css/bootstrap.min.css +++ /dev/null @@ -1,9 +0,0 @@ -/*! - * Bootstrap v2.0.4 - * - * Copyright 2012 Twitter, Inc - * Licensed under the Apache License v2.0 - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Designed and built with all the love in the world @twitter by @mdo and @fat. - */article,aside,details,figcaption,figure,footer,header,hgroup,nav,section{display:block}audio,canvas,video{display:inline-block;*display:inline;*zoom:1}audio:not([controls]){display:none}html{font-size:100%;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%}a:focus{outline:thin dotted #333;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}a:hover,a:active{outline:0}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sup{top:-0.5em}sub{bottom:-0.25em}img{max-width:100%;vertical-align:middle;border:0;-ms-interpolation-mode:bicubic}#map_canvas img{max-width:none}button,input,select,textarea{margin:0;font-size:100%;vertical-align:middle}button,input{*overflow:visible;line-height:normal}button::-moz-focus-inner,input::-moz-focus-inner{padding:0;border:0}button,input[type="button"],input[type="reset"],input[type="submit"]{cursor:pointer;-webkit-appearance:button}input[type="search"]{-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;-webkit-appearance:textfield}input[type="search"]::-webkit-search-decoration,input[type="search"]::-webkit-search-cancel-button{-webkit-appearance:none}textarea{overflow:auto;vertical-align:top}.clearfix{*zoom:1}.clearfix:before,.clearfix:after{display:table;content:""}.clearfix:after{clear:both}.hide-text{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.input-block-level{display:block;width:100%;min-height:28px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;-ms-box-sizing:border-box;box-sizing:border-box}body{margin:0;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:13px;line-height:18px;color:#333;background-color:#fff}a{color:#08c;text-decoration:none}a:hover{color:#005580;text-decoration:underline}.row{margin-left:-20px;*zoom:1}.row:before,.row:after{display:table;content:""}.row:after{clear:both}[class*="span"]{float:left;margin-left:20px}.container,.navbar-fixed-top .container,.navbar-fixed-bottom .container{width:940px}.span12{width:940px}.span11{width:860px}.span10{width:780px}.span9{width:700px}.span8{width:620px}.span7{width:540px}.span6{width:460px}.span5{width:380px}.span4{width:300px}.span3{width:220px}.span2{width:140px}.span1{width:60px}.offset12{margin-left:980px}.offset11{margin-left:900px}.offset10{margin-left:820px}.offset9{margin-left:740px}.offset8{margin-left:660px}.offset7{margin-left:580px}.offset6{margin-left:500px}.offset5{margin-left:420px}.offset4{margin-left:340px}.offset3{margin-left:260px}.offset2{margin-left:180px}.offset1{margin-left:100px}.row-fluid{width:100%;*zoom:1}.row-fluid:before,.row-fluid:after{display:table;content:""}.row-fluid:after{clear:both}.row-fluid [class*="span"]{display:block;float:left;width:100%;min-height:28px;margin-left:2.127659574%;*margin-left:2.0744680846382977%;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;-ms-box-sizing:border-box;box-sizing:border-box}.row-fluid [class*="span"]:first-child{margin-left:0}.row-fluid .span12{width:99.99999998999999%;*width:99.94680850063828%}.row-fluid .span11{width:91.489361693%;*width:91.4361702036383%}.row-fluid .span10{width:82.97872339599999%;*width:82.92553190663828%}.row-fluid .span9{width:74.468085099%;*width:74.4148936096383%}.row-fluid .span8{width:65.95744680199999%;*width:65.90425531263828%}.row-fluid .span7{width:57.446808505%;*width:57.3936170156383%}.row-fluid .span6{width:48.93617020799999%;*width:48.88297871863829%}.row-fluid .span5{width:40.425531911%;*width:40.3723404216383%}.row-fluid .span4{width:31.914893614%;*width:31.8617021246383%}.row-fluid .span3{width:23.404255317%;*width:23.3510638276383%}.row-fluid .span2{width:14.89361702%;*width:14.8404255306383%}.row-fluid .span1{width:6.382978723%;*width:6.329787233638298%}.container{margin-right:auto;margin-left:auto;*zoom:1}.container:before,.container:after{display:table;content:""}.container:after{clear:both}.container-fluid{padding-right:20px;padding-left:20px;*zoom:1}.container-fluid:before,.container-fluid:after{display:table;content:""}.container-fluid:after{clear:both}p{margin:0 0 9px}p small{font-size:11px;color:#999}.lead{margin-bottom:18px;font-size:20px;font-weight:200;line-height:27px}h1,h2,h3,h4,h5,h6{margin:0;font-family:inherit;font-weight:bold;color:inherit;text-rendering:optimizelegibility}h1 small,h2 small,h3 small,h4 small,h5 small,h6 small{font-weight:normal;color:#999}h1{font-size:30px;line-height:36px}h1 small{font-size:18px}h2{font-size:24px;line-height:36px}h2 small{font-size:18px}h3{font-size:18px;line-height:27px}h3 small{font-size:14px}h4,h5,h6{line-height:18px}h4{font-size:14px}h4 small{font-size:12px}h5{font-size:12px}h6{font-size:11px;color:#999;text-transform:uppercase}.page-header{padding-bottom:17px;margin:18px 0;border-bottom:1px solid #eee}.page-header h1{line-height:1}ul,ol{padding:0;margin:0 0 9px 25px}ul ul,ul ol,ol ol,ol ul{margin-bottom:0}ul{list-style:disc}ol{list-style:decimal}li{line-height:18px}ul.unstyled,ol.unstyled{margin-left:0;list-style:none}dl{margin-bottom:18px}dt,dd{line-height:18px}dt{font-weight:bold;line-height:17px}dd{margin-left:9px}.dl-horizontal dt{float:left;width:120px;overflow:hidden;clear:left;text-align:right;text-overflow:ellipsis;white-space:nowrap}.dl-horizontal dd{margin-left:130px}hr{margin:18px 0;border:0;border-top:1px solid #eee;border-bottom:1px solid #fff}strong{font-weight:bold}em{font-style:italic}.muted{color:#999}abbr[title]{cursor:help;border-bottom:1px dotted #999}abbr.initialism{font-size:90%;text-transform:uppercase}blockquote{padding:0 0 0 15px;margin:0 0 18px;border-left:5px solid #eee}blockquote p{margin-bottom:0;font-size:16px;font-weight:300;line-height:22.5px}blockquote small{display:block;line-height:18px;color:#999}blockquote small:before{content:'\2014 \00A0'}blockquote.pull-right{float:right;padding-right:15px;padding-left:0;border-right:5px solid #eee;border-left:0}blockquote.pull-right p,blockquote.pull-right small{text-align:right}q:before,q:after,blockquote:before,blockquote:after{content:""}address{display:block;margin-bottom:18px;font-style:normal;line-height:18px}small{font-size:100%}cite{font-style:normal}code,pre{padding:0 3px 2px;font-family:Menlo,Monaco,Consolas,"Courier New",monospace;font-size:12px;color:#333;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px}code{padding:2px 4px;color:#d14;background-color:#f7f7f9;border:1px solid #e1e1e8}pre{display:block;padding:8.5px;margin:0 0 9px;font-size:12.025px;line-height:18px;word-break:break-all;word-wrap:break-word;white-space:pre;white-space:pre-wrap;background-color:#f5f5f5;border:1px solid #ccc;border:1px solid rgba(0,0,0,0.15);-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}pre.prettyprint{margin-bottom:18px}pre code{padding:0;color:inherit;background-color:transparent;border:0}.pre-scrollable{max-height:340px;overflow-y:scroll}form{margin:0 0 18px}fieldset{padding:0;margin:0;border:0}legend{display:block;width:100%;padding:0;margin-bottom:27px;font-size:19.5px;line-height:36px;color:#333;border:0;border-bottom:1px solid #e5e5e5}legend small{font-size:13.5px;color:#999}label,input,button,select,textarea{font-size:13px;font-weight:normal;line-height:18px}input,button,select,textarea{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif}label{display:block;margin-bottom:5px}select,textarea,input[type="text"],input[type="password"],input[type="datetime"],input[type="datetime-local"],input[type="date"],input[type="month"],input[type="time"],input[type="week"],input[type="number"],input[type="email"],input[type="url"],input[type="search"],input[type="tel"],input[type="color"],.uneditable-input{display:inline-block;height:18px;padding:4px;margin-bottom:9px;font-size:13px;line-height:18px;color:#555}input,textarea{width:210px}textarea{height:auto}textarea,input[type="text"],input[type="password"],input[type="datetime"],input[type="datetime-local"],input[type="date"],input[type="month"],input[type="time"],input[type="week"],input[type="number"],input[type="email"],input[type="url"],input[type="search"],input[type="tel"],input[type="color"],.uneditable-input{background-color:#fff;border:1px solid #ccc;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);-webkit-transition:border linear .2s,box-shadow linear .2s;-moz-transition:border linear .2s,box-shadow linear .2s;-ms-transition:border linear .2s,box-shadow linear .2s;-o-transition:border linear .2s,box-shadow linear .2s;transition:border linear .2s,box-shadow linear .2s}textarea:focus,input[type="text"]:focus,input[type="password"]:focus,input[type="datetime"]:focus,input[type="datetime-local"]:focus,input[type="date"]:focus,input[type="month"]:focus,input[type="time"]:focus,input[type="week"]:focus,input[type="number"]:focus,input[type="email"]:focus,input[type="url"]:focus,input[type="search"]:focus,input[type="tel"]:focus,input[type="color"]:focus,.uneditable-input:focus{border-color:rgba(82,168,236,0.8);outline:0;outline:thin dotted \9;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 8px rgba(82,168,236,0.6);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 8px rgba(82,168,236,0.6);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 8px rgba(82,168,236,0.6)}input[type="radio"],input[type="checkbox"]{margin:3px 0;*margin-top:0;line-height:normal;cursor:pointer}input[type="submit"],input[type="reset"],input[type="button"],input[type="radio"],input[type="checkbox"]{width:auto}.uneditable-textarea{width:auto;height:auto}select,input[type="file"]{height:28px;*margin-top:4px;line-height:28px}select{width:220px;border:1px solid #bbb}select[multiple],select[size]{height:auto}select:focus,input[type="file"]:focus,input[type="radio"]:focus,input[type="checkbox"]:focus{outline:thin dotted #333;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}.radio,.checkbox{min-height:18px;padding-left:18px}.radio input[type="radio"],.checkbox input[type="checkbox"]{float:left;margin-left:-18px}.controls>.radio:first-child,.controls>.checkbox:first-child{padding-top:5px}.radio.inline,.checkbox.inline{display:inline-block;padding-top:5px;margin-bottom:0;vertical-align:middle}.radio.inline+.radio.inline,.checkbox.inline+.checkbox.inline{margin-left:10px}.input-mini{width:60px}.input-small{width:90px}.input-medium{width:150px}.input-large{width:210px}.input-xlarge{width:270px}.input-xxlarge{width:530px}input[class*="span"],select[class*="span"],textarea[class*="span"],.uneditable-input[class*="span"],.row-fluid input[class*="span"],.row-fluid select[class*="span"],.row-fluid textarea[class*="span"],.row-fluid .uneditable-input[class*="span"]{float:none;margin-left:0}.input-append input[class*="span"],.input-append .uneditable-input[class*="span"],.input-prepend input[class*="span"],.input-prepend .uneditable-input[class*="span"],.row-fluid .input-prepend [class*="span"],.row-fluid .input-append [class*="span"]{display:inline-block}input,textarea,.uneditable-input{margin-left:0}input.span12,textarea.span12,.uneditable-input.span12{width:930px}input.span11,textarea.span11,.uneditable-input.span11{width:850px}input.span10,textarea.span10,.uneditable-input.span10{width:770px}input.span9,textarea.span9,.uneditable-input.span9{width:690px}input.span8,textarea.span8,.uneditable-input.span8{width:610px}input.span7,textarea.span7,.uneditable-input.span7{width:530px}input.span6,textarea.span6,.uneditable-input.span6{width:450px}input.span5,textarea.span5,.uneditable-input.span5{width:370px}input.span4,textarea.span4,.uneditable-input.span4{width:290px}input.span3,textarea.span3,.uneditable-input.span3{width:210px}input.span2,textarea.span2,.uneditable-input.span2{width:130px}input.span1,textarea.span1,.uneditable-input.span1{width:50px}input[disabled],select[disabled],textarea[disabled],input[readonly],select[readonly],textarea[readonly]{cursor:not-allowed;background-color:#eee;border-color:#ddd}input[type="radio"][disabled],input[type="checkbox"][disabled],input[type="radio"][readonly],input[type="checkbox"][readonly]{background-color:transparent}.control-group.warning>label,.control-group.warning .help-block,.control-group.warning .help-inline{color:#c09853}.control-group.warning .checkbox,.control-group.warning .radio,.control-group.warning input,.control-group.warning select,.control-group.warning textarea{color:#c09853;border-color:#c09853}.control-group.warning .checkbox:focus,.control-group.warning .radio:focus,.control-group.warning input:focus,.control-group.warning select:focus,.control-group.warning textarea:focus{border-color:#a47e3c;-webkit-box-shadow:0 0 6px #dbc59e;-moz-box-shadow:0 0 6px #dbc59e;box-shadow:0 0 6px #dbc59e}.control-group.warning .input-prepend .add-on,.control-group.warning .input-append .add-on{color:#c09853;background-color:#fcf8e3;border-color:#c09853}.control-group.error>label,.control-group.error .help-block,.control-group.error .help-inline{color:#b94a48}.control-group.error .checkbox,.control-group.error .radio,.control-group.error input,.control-group.error select,.control-group.error textarea{color:#b94a48;border-color:#b94a48}.control-group.error .checkbox:focus,.control-group.error .radio:focus,.control-group.error input:focus,.control-group.error select:focus,.control-group.error textarea:focus{border-color:#953b39;-webkit-box-shadow:0 0 6px #d59392;-moz-box-shadow:0 0 6px #d59392;box-shadow:0 0 6px #d59392}.control-group.error .input-prepend .add-on,.control-group.error .input-append .add-on{color:#b94a48;background-color:#f2dede;border-color:#b94a48}.control-group.success>label,.control-group.success .help-block,.control-group.success .help-inline{color:#468847}.control-group.success .checkbox,.control-group.success .radio,.control-group.success input,.control-group.success select,.control-group.success textarea{color:#468847;border-color:#468847}.control-group.success .checkbox:focus,.control-group.success .radio:focus,.control-group.success input:focus,.control-group.success select:focus,.control-group.success textarea:focus{border-color:#356635;-webkit-box-shadow:0 0 6px #7aba7b;-moz-box-shadow:0 0 6px #7aba7b;box-shadow:0 0 6px #7aba7b}.control-group.success .input-prepend .add-on,.control-group.success .input-append .add-on{color:#468847;background-color:#dff0d8;border-color:#468847}input:focus:required:invalid,textarea:focus:required:invalid,select:focus:required:invalid{color:#b94a48;border-color:#ee5f5b}input:focus:required:invalid:focus,textarea:focus:required:invalid:focus,select:focus:required:invalid:focus{border-color:#e9322d;-webkit-box-shadow:0 0 6px #f8b9b7;-moz-box-shadow:0 0 6px #f8b9b7;box-shadow:0 0 6px #f8b9b7}.form-actions{padding:17px 20px 18px;margin-top:18px;margin-bottom:18px;background-color:#f5f5f5;border-top:1px solid #e5e5e5;*zoom:1}.form-actions:before,.form-actions:after{display:table;content:""}.form-actions:after{clear:both}.uneditable-input{overflow:hidden;white-space:nowrap;cursor:not-allowed;background-color:#fff;border-color:#eee;-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,0.025);-moz-box-shadow:inset 0 1px 2px rgba(0,0,0,0.025);box-shadow:inset 0 1px 2px rgba(0,0,0,0.025)}:-moz-placeholder{color:#999}:-ms-input-placeholder{color:#999}::-webkit-input-placeholder{color:#999}.help-block,.help-inline{color:#555}.help-block{display:block;margin-bottom:9px}.help-inline{display:inline-block;*display:inline;padding-left:5px;vertical-align:middle;*zoom:1}.input-prepend,.input-append{margin-bottom:5px}.input-prepend input,.input-append input,.input-prepend select,.input-append select,.input-prepend .uneditable-input,.input-append .uneditable-input{position:relative;margin-bottom:0;*margin-left:0;vertical-align:middle;-webkit-border-radius:0 3px 3px 0;-moz-border-radius:0 3px 3px 0;border-radius:0 3px 3px 0}.input-prepend input:focus,.input-append input:focus,.input-prepend select:focus,.input-append select:focus,.input-prepend .uneditable-input:focus,.input-append .uneditable-input:focus{z-index:2}.input-prepend .uneditable-input,.input-append .uneditable-input{border-left-color:#ccc}.input-prepend .add-on,.input-append .add-on{display:inline-block;width:auto;height:18px;min-width:16px;padding:4px 5px;font-weight:normal;line-height:18px;text-align:center;text-shadow:0 1px 0 #fff;vertical-align:middle;background-color:#eee;border:1px solid #ccc}.input-prepend .add-on,.input-append .add-on,.input-prepend .btn,.input-append .btn{margin-left:-1px;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.input-prepend .active,.input-append .active{background-color:#a9dba9;border-color:#46a546}.input-prepend .add-on,.input-prepend .btn{margin-right:-1px}.input-prepend .add-on:first-child,.input-prepend .btn:first-child{-webkit-border-radius:3px 0 0 3px;-moz-border-radius:3px 0 0 3px;border-radius:3px 0 0 3px}.input-append input,.input-append select,.input-append .uneditable-input{-webkit-border-radius:3px 0 0 3px;-moz-border-radius:3px 0 0 3px;border-radius:3px 0 0 3px}.input-append .uneditable-input{border-right-color:#ccc;border-left-color:#eee}.input-append .add-on:last-child,.input-append .btn:last-child{-webkit-border-radius:0 3px 3px 0;-moz-border-radius:0 3px 3px 0;border-radius:0 3px 3px 0}.input-prepend.input-append input,.input-prepend.input-append select,.input-prepend.input-append .uneditable-input{-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.input-prepend.input-append .add-on:first-child,.input-prepend.input-append .btn:first-child{margin-right:-1px;-webkit-border-radius:3px 0 0 3px;-moz-border-radius:3px 0 0 3px;border-radius:3px 0 0 3px}.input-prepend.input-append .add-on:last-child,.input-prepend.input-append .btn:last-child{margin-left:-1px;-webkit-border-radius:0 3px 3px 0;-moz-border-radius:0 3px 3px 0;border-radius:0 3px 3px 0}.search-query{padding-right:14px;padding-right:4px \9;padding-left:14px;padding-left:4px \9;margin-bottom:0;-webkit-border-radius:14px;-moz-border-radius:14px;border-radius:14px}.form-search input,.form-inline input,.form-horizontal input,.form-search textarea,.form-inline textarea,.form-horizontal textarea,.form-search select,.form-inline select,.form-horizontal select,.form-search .help-inline,.form-inline .help-inline,.form-horizontal .help-inline,.form-search .uneditable-input,.form-inline .uneditable-input,.form-horizontal .uneditable-input,.form-search .input-prepend,.form-inline .input-prepend,.form-horizontal .input-prepend,.form-search .input-append,.form-inline .input-append,.form-horizontal .input-append{display:inline-block;*display:inline;margin-bottom:0;*zoom:1}.form-search .hide,.form-inline .hide,.form-horizontal .hide{display:none}.form-search label,.form-inline label{display:inline-block}.form-search .input-append,.form-inline .input-append,.form-search .input-prepend,.form-inline .input-prepend{margin-bottom:0}.form-search .radio,.form-search .checkbox,.form-inline .radio,.form-inline .checkbox{padding-left:0;margin-bottom:0;vertical-align:middle}.form-search .radio input[type="radio"],.form-search .checkbox input[type="checkbox"],.form-inline .radio input[type="radio"],.form-inline .checkbox input[type="checkbox"]{float:left;margin-right:3px;margin-left:0}.control-group{margin-bottom:9px}legend+.control-group{margin-top:18px;-webkit-margin-top-collapse:separate}.form-horizontal .control-group{margin-bottom:18px;*zoom:1}.form-horizontal .control-group:before,.form-horizontal .control-group:after{display:table;content:""}.form-horizontal .control-group:after{clear:both}.form-horizontal .control-label{float:left;width:140px;padding-top:5px;text-align:right}.form-horizontal .controls{*display:inline-block;*padding-left:20px;margin-left:160px;*margin-left:0}.form-horizontal .controls:first-child{*padding-left:160px}.form-horizontal .help-block{margin-top:9px;margin-bottom:0}.form-horizontal .form-actions{padding-left:160px}table{max-width:100%;background-color:transparent;border-collapse:collapse;border-spacing:0}.table{width:100%;margin-bottom:18px}.table th,.table td{padding:8px;line-height:18px;text-align:left;vertical-align:top;border-top:1px solid #ddd}.table th{font-weight:bold}.table thead th{vertical-align:bottom}.table caption+thead tr:first-child th,.table caption+thead tr:first-child td,.table colgroup+thead tr:first-child th,.table colgroup+thead tr:first-child td,.table thead:first-child tr:first-child th,.table thead:first-child tr:first-child td{border-top:0}.table tbody+tbody{border-top:2px solid #ddd}.table-condensed th,.table-condensed td{padding:4px 5px}.table-bordered{border:1px solid #ddd;border-collapse:separate;*border-collapse:collapsed;border-left:0;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.table-bordered th,.table-bordered td{border-left:1px solid #ddd}.table-bordered caption+thead tr:first-child th,.table-bordered caption+tbody tr:first-child th,.table-bordered caption+tbody tr:first-child td,.table-bordered colgroup+thead tr:first-child th,.table-bordered colgroup+tbody tr:first-child th,.table-bordered colgroup+tbody tr:first-child td,.table-bordered thead:first-child tr:first-child th,.table-bordered tbody:first-child tr:first-child th,.table-bordered tbody:first-child tr:first-child td{border-top:0}.table-bordered thead:first-child tr:first-child th:first-child,.table-bordered tbody:first-child tr:first-child td:first-child{-webkit-border-top-left-radius:4px;border-top-left-radius:4px;-moz-border-radius-topleft:4px}.table-bordered thead:first-child tr:first-child th:last-child,.table-bordered tbody:first-child tr:first-child td:last-child{-webkit-border-top-right-radius:4px;border-top-right-radius:4px;-moz-border-radius-topright:4px}.table-bordered thead:last-child tr:last-child th:first-child,.table-bordered tbody:last-child tr:last-child td:first-child{-webkit-border-radius:0 0 0 4px;-moz-border-radius:0 0 0 4px;border-radius:0 0 0 4px;-webkit-border-bottom-left-radius:4px;border-bottom-left-radius:4px;-moz-border-radius-bottomleft:4px}.table-bordered thead:last-child tr:last-child th:last-child,.table-bordered tbody:last-child tr:last-child td:last-child{-webkit-border-bottom-right-radius:4px;border-bottom-right-radius:4px;-moz-border-radius-bottomright:4px}.table-striped tbody tr:nth-child(odd) td,.table-striped tbody tr:nth-child(odd) th{background-color:#f9f9f9}.table tbody tr:hover td,.table tbody tr:hover th{background-color:#f5f5f5}table .span1{float:none;width:44px;margin-left:0}table .span2{float:none;width:124px;margin-left:0}table .span3{float:none;width:204px;margin-left:0}table .span4{float:none;width:284px;margin-left:0}table .span5{float:none;width:364px;margin-left:0}table .span6{float:none;width:444px;margin-left:0}table .span7{float:none;width:524px;margin-left:0}table .span8{float:none;width:604px;margin-left:0}table .span9{float:none;width:684px;margin-left:0}table .span10{float:none;width:764px;margin-left:0}table .span11{float:none;width:844px;margin-left:0}table .span12{float:none;width:924px;margin-left:0}table .span13{float:none;width:1004px;margin-left:0}table .span14{float:none;width:1084px;margin-left:0}table .span15{float:none;width:1164px;margin-left:0}table .span16{float:none;width:1244px;margin-left:0}table .span17{float:none;width:1324px;margin-left:0}table .span18{float:none;width:1404px;margin-left:0}table .span19{float:none;width:1484px;margin-left:0}table .span20{float:none;width:1564px;margin-left:0}table .span21{float:none;width:1644px;margin-left:0}table .span22{float:none;width:1724px;margin-left:0}table .span23{float:none;width:1804px;margin-left:0}table .span24{float:none;width:1884px;margin-left:0}[class^="icon-"],[class*=" icon-"]{display:inline-block;width:14px;height:14px;*margin-right:.3em;line-height:14px;vertical-align:text-top;background-image:url("../img/glyphicons-halflings.png");background-position:14px 14px;background-repeat:no-repeat}[class^="icon-"]:last-child,[class*=" icon-"]:last-child{*margin-left:0}.icon-white{background-image:url("../img/glyphicons-halflings-white.png")}.icon-glass{background-position:0 0}.icon-music{background-position:-24px 0}.icon-search{background-position:-48px 0}.icon-envelope{background-position:-72px 0}.icon-heart{background-position:-96px 0}.icon-star{background-position:-120px 0}.icon-star-empty{background-position:-144px 0}.icon-user{background-position:-168px 0}.icon-film{background-position:-192px 0}.icon-th-large{background-position:-216px 0}.icon-th{background-position:-240px 0}.icon-th-list{background-position:-264px 0}.icon-ok{background-position:-288px 0}.icon-remove{background-position:-312px 0}.icon-zoom-in{background-position:-336px 0}.icon-zoom-out{background-position:-360px 0}.icon-off{background-position:-384px 0}.icon-signal{background-position:-408px 0}.icon-cog{background-position:-432px 0}.icon-trash{background-position:-456px 0}.icon-home{background-position:0 -24px}.icon-file{background-position:-24px -24px}.icon-time{background-position:-48px -24px}.icon-road{background-position:-72px -24px}.icon-download-alt{background-position:-96px -24px}.icon-download{background-position:-120px -24px}.icon-upload{background-position:-144px -24px}.icon-inbox{background-position:-168px -24px}.icon-play-circle{background-position:-192px -24px}.icon-repeat{background-position:-216px -24px}.icon-refresh{background-position:-240px -24px}.icon-list-alt{background-position:-264px -24px}.icon-lock{background-position:-287px -24px}.icon-flag{background-position:-312px -24px}.icon-headphones{background-position:-336px -24px}.icon-volume-off{background-position:-360px -24px}.icon-volume-down{background-position:-384px -24px}.icon-volume-up{background-position:-408px -24px}.icon-qrcode{background-position:-432px -24px}.icon-barcode{background-position:-456px -24px}.icon-tag{background-position:0 -48px}.icon-tags{background-position:-25px -48px}.icon-book{background-position:-48px -48px}.icon-bookmark{background-position:-72px -48px}.icon-print{background-position:-96px -48px}.icon-camera{background-position:-120px -48px}.icon-font{background-position:-144px -48px}.icon-bold{background-position:-167px -48px}.icon-italic{background-position:-192px -48px}.icon-text-height{background-position:-216px -48px}.icon-text-width{background-position:-240px -48px}.icon-align-left{background-position:-264px -48px}.icon-align-center{background-position:-288px -48px}.icon-align-right{background-position:-312px -48px}.icon-align-justify{background-position:-336px -48px}.icon-list{background-position:-360px -48px}.icon-indent-left{background-position:-384px -48px}.icon-indent-right{background-position:-408px -48px}.icon-facetime-video{background-position:-432px -48px}.icon-picture{background-position:-456px -48px}.icon-pencil{background-position:0 -72px}.icon-map-marker{background-position:-24px -72px}.icon-adjust{background-position:-48px -72px}.icon-tint{background-position:-72px -72px}.icon-edit{background-position:-96px -72px}.icon-share{background-position:-120px -72px}.icon-check{background-position:-144px -72px}.icon-move{background-position:-168px -72px}.icon-step-backward{background-position:-192px -72px}.icon-fast-backward{background-position:-216px -72px}.icon-backward{background-position:-240px -72px}.icon-play{background-position:-264px -72px}.icon-pause{background-position:-288px -72px}.icon-stop{background-position:-312px -72px}.icon-forward{background-position:-336px -72px}.icon-fast-forward{background-position:-360px -72px}.icon-step-forward{background-position:-384px -72px}.icon-eject{background-position:-408px -72px}.icon-chevron-left{background-position:-432px -72px}.icon-chevron-right{background-position:-456px -72px}.icon-plus-sign{background-position:0 -96px}.icon-minus-sign{background-position:-24px -96px}.icon-remove-sign{background-position:-48px -96px}.icon-ok-sign{background-position:-72px -96px}.icon-question-sign{background-position:-96px -96px}.icon-info-sign{background-position:-120px -96px}.icon-screenshot{background-position:-144px -96px}.icon-remove-circle{background-position:-168px -96px}.icon-ok-circle{background-position:-192px -96px}.icon-ban-circle{background-position:-216px -96px}.icon-arrow-left{background-position:-240px -96px}.icon-arrow-right{background-position:-264px -96px}.icon-arrow-up{background-position:-289px -96px}.icon-arrow-down{background-position:-312px -96px}.icon-share-alt{background-position:-336px -96px}.icon-resize-full{background-position:-360px -96px}.icon-resize-small{background-position:-384px -96px}.icon-plus{background-position:-408px -96px}.icon-minus{background-position:-433px -96px}.icon-asterisk{background-position:-456px -96px}.icon-exclamation-sign{background-position:0 -120px}.icon-gift{background-position:-24px -120px}.icon-leaf{background-position:-48px -120px}.icon-fire{background-position:-72px -120px}.icon-eye-open{background-position:-96px -120px}.icon-eye-close{background-position:-120px -120px}.icon-warning-sign{background-position:-144px -120px}.icon-plane{background-position:-168px -120px}.icon-calendar{background-position:-192px -120px}.icon-random{background-position:-216px -120px}.icon-comment{background-position:-240px -120px}.icon-magnet{background-position:-264px -120px}.icon-chevron-up{background-position:-288px -120px}.icon-chevron-down{background-position:-313px -119px}.icon-retweet{background-position:-336px -120px}.icon-shopping-cart{background-position:-360px -120px}.icon-folder-close{background-position:-384px -120px}.icon-folder-open{background-position:-408px -120px}.icon-resize-vertical{background-position:-432px -119px}.icon-resize-horizontal{background-position:-456px -118px}.icon-hdd{background-position:0 -144px}.icon-bullhorn{background-position:-24px -144px}.icon-bell{background-position:-48px -144px}.icon-certificate{background-position:-72px -144px}.icon-thumbs-up{background-position:-96px -144px}.icon-thumbs-down{background-position:-120px -144px}.icon-hand-right{background-position:-144px -144px}.icon-hand-left{background-position:-168px -144px}.icon-hand-up{background-position:-192px -144px}.icon-hand-down{background-position:-216px -144px}.icon-circle-arrow-right{background-position:-240px -144px}.icon-circle-arrow-left{background-position:-264px -144px}.icon-circle-arrow-up{background-position:-288px -144px}.icon-circle-arrow-down{background-position:-312px -144px}.icon-globe{background-position:-336px -144px}.icon-wrench{background-position:-360px -144px}.icon-tasks{background-position:-384px -144px}.icon-filter{background-position:-408px -144px}.icon-briefcase{background-position:-432px -144px}.icon-fullscreen{background-position:-456px -144px}.dropup,.dropdown{position:relative}.dropdown-toggle{*margin-bottom:-3px}.dropdown-toggle:active,.open .dropdown-toggle{outline:0}.caret{display:inline-block;width:0;height:0;vertical-align:top;border-top:4px solid #000;border-right:4px solid transparent;border-left:4px solid transparent;content:"";opacity:.3;filter:alpha(opacity=30)}.dropdown .caret{margin-top:8px;margin-left:2px}.dropdown:hover .caret,.open .caret{opacity:1;filter:alpha(opacity=100)}.dropdown-menu{position:absolute;top:100%;left:0;z-index:1000;display:none;float:left;min-width:160px;padding:4px 0;margin:1px 0 0;list-style:none;background-color:#fff;border:1px solid #ccc;border:1px solid rgba(0,0,0,0.2);*border-right-width:2px;*border-bottom-width:2px;-webkit-border-radius:5px;-moz-border-radius:5px;border-radius:5px;-webkit-box-shadow:0 5px 10px rgba(0,0,0,0.2);-moz-box-shadow:0 5px 10px rgba(0,0,0,0.2);box-shadow:0 5px 10px rgba(0,0,0,0.2);-webkit-background-clip:padding-box;-moz-background-clip:padding;background-clip:padding-box}.dropdown-menu.pull-right{right:0;left:auto}.dropdown-menu .divider{*width:100%;height:1px;margin:8px 1px;*margin:-5px 0 5px;overflow:hidden;background-color:#e5e5e5;border-bottom:1px solid #fff}.dropdown-menu a{display:block;padding:3px 15px;clear:both;font-weight:normal;line-height:18px;color:#333;white-space:nowrap}.dropdown-menu li>a:hover,.dropdown-menu .active>a,.dropdown-menu .active>a:hover{color:#fff;text-decoration:none;background-color:#08c}.open{*z-index:1000}.open>.dropdown-menu{display:block}.pull-right>.dropdown-menu{right:0;left:auto}.dropup .caret,.navbar-fixed-bottom .dropdown .caret{border-top:0;border-bottom:4px solid #000;content:"\2191"}.dropup .dropdown-menu,.navbar-fixed-bottom .dropdown .dropdown-menu{top:auto;bottom:100%;margin-bottom:1px}.typeahead{margin-top:2px;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.well{min-height:20px;padding:19px;margin-bottom:20px;background-color:#f5f5f5;border:1px solid #eee;border:1px solid rgba(0,0,0,0.05);-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.05);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.05);box-shadow:inset 0 1px 1px rgba(0,0,0,0.05)}.well blockquote{border-color:#ddd;border-color:rgba(0,0,0,0.15)}.well-large{padding:24px;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px}.well-small{padding:9px;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px}.fade{opacity:0;-webkit-transition:opacity .15s linear;-moz-transition:opacity .15s linear;-ms-transition:opacity .15s linear;-o-transition:opacity .15s linear;transition:opacity .15s linear}.fade.in{opacity:1}.collapse{position:relative;height:0;overflow:hidden;-webkit-transition:height .35s ease;-moz-transition:height .35s ease;-ms-transition:height .35s ease;-o-transition:height .35s ease;transition:height .35s ease}.collapse.in{height:auto}.close{float:right;font-size:20px;font-weight:bold;line-height:18px;color:#000;text-shadow:0 1px 0 #fff;opacity:.2;filter:alpha(opacity=20)}.close:hover{color:#000;text-decoration:none;cursor:pointer;opacity:.4;filter:alpha(opacity=40)}button.close{padding:0;cursor:pointer;background:transparent;border:0;-webkit-appearance:none}.btn{display:inline-block;*display:inline;padding:4px 10px 4px;margin-bottom:0;*margin-left:.3em;font-size:13px;line-height:18px;*line-height:20px;color:#333;text-align:center;text-shadow:0 1px 1px rgba(255,255,255,0.75);vertical-align:middle;cursor:pointer;background-color:#f5f5f5;*background-color:#e6e6e6;background-image:-ms-linear-gradient(top,#fff,#e6e6e6);background-image:-webkit-gradient(linear,0 0,0 100%,from(#fff),to(#e6e6e6));background-image:-webkit-linear-gradient(top,#fff,#e6e6e6);background-image:-o-linear-gradient(top,#fff,#e6e6e6);background-image:linear-gradient(top,#fff,#e6e6e6);background-image:-moz-linear-gradient(top,#fff,#e6e6e6);background-repeat:repeat-x;border:1px solid #ccc;*border:0;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);border-color:#e6e6e6 #e6e6e6 #bfbfbf;border-bottom-color:#b3b3b3;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;filter:progid:dximagetransform.microsoft.gradient(startColorstr='#ffffff',endColorstr='#e6e6e6',GradientType=0);filter:progid:dximagetransform.microsoft.gradient(enabled=false);*zoom:1;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,0.2),0 1px 2px rgba(0,0,0,0.05);-moz-box-shadow:inset 0 1px 0 rgba(255,255,255,0.2),0 1px 2px rgba(0,0,0,0.05);box-shadow:inset 0 1px 0 rgba(255,255,255,0.2),0 1px 2px rgba(0,0,0,0.05)}.btn:hover,.btn:active,.btn.active,.btn.disabled,.btn[disabled]{background-color:#e6e6e6;*background-color:#d9d9d9}.btn:active,.btn.active{background-color:#ccc \9}.btn:first-child{*margin-left:0}.btn:hover{color:#333;text-decoration:none;background-color:#e6e6e6;*background-color:#d9d9d9;background-position:0 -15px;-webkit-transition:background-position .1s linear;-moz-transition:background-position .1s linear;-ms-transition:background-position .1s linear;-o-transition:background-position .1s linear;transition:background-position .1s linear}.btn:focus{outline:thin dotted #333;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}.btn.active,.btn:active{background-color:#e6e6e6;background-color:#d9d9d9 \9;background-image:none;outline:0;-webkit-box-shadow:inset 0 2px 4px rgba(0,0,0,0.15),0 1px 2px rgba(0,0,0,0.05);-moz-box-shadow:inset 0 2px 4px rgba(0,0,0,0.15),0 1px 2px rgba(0,0,0,0.05);box-shadow:inset 0 2px 4px rgba(0,0,0,0.15),0 1px 2px rgba(0,0,0,0.05)}.btn.disabled,.btn[disabled]{cursor:default;background-color:#e6e6e6;background-image:none;opacity:.65;filter:alpha(opacity=65);-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none}.btn-large{padding:9px 14px;font-size:15px;line-height:normal;-webkit-border-radius:5px;-moz-border-radius:5px;border-radius:5px}.btn-large [class^="icon-"]{margin-top:1px}.btn-small{padding:5px 9px;font-size:11px;line-height:16px}.btn-small [class^="icon-"]{margin-top:-1px}.btn-mini{padding:2px 6px;font-size:11px;line-height:14px}.btn-primary,.btn-primary:hover,.btn-warning,.btn-warning:hover,.btn-danger,.btn-danger:hover,.btn-success,.btn-success:hover,.btn-info,.btn-info:hover,.btn-inverse,.btn-inverse:hover{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25)}.btn-primary.active,.btn-warning.active,.btn-danger.active,.btn-success.active,.btn-info.active,.btn-inverse.active{color:rgba(255,255,255,0.75)}.btn{border-color:#ccc;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25)}.btn-primary{background-color:#0074cc;*background-color:#05c;background-image:-ms-linear-gradient(top,#08c,#05c);background-image:-webkit-gradient(linear,0 0,0 100%,from(#08c),to(#05c));background-image:-webkit-linear-gradient(top,#08c,#05c);background-image:-o-linear-gradient(top,#08c,#05c);background-image:-moz-linear-gradient(top,#08c,#05c);background-image:linear-gradient(top,#08c,#05c);background-repeat:repeat-x;border-color:#05c #05c #003580;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:dximagetransform.microsoft.gradient(startColorstr='#0088cc',endColorstr='#0055cc',GradientType=0);filter:progid:dximagetransform.microsoft.gradient(enabled=false)}.btn-primary:hover,.btn-primary:active,.btn-primary.active,.btn-primary.disabled,.btn-primary[disabled]{background-color:#05c;*background-color:#004ab3}.btn-primary:active,.btn-primary.active{background-color:#004099 \9}.btn-warning{background-color:#faa732;*background-color:#f89406;background-image:-ms-linear-gradient(top,#fbb450,#f89406);background-image:-webkit-gradient(linear,0 0,0 100%,from(#fbb450),to(#f89406));background-image:-webkit-linear-gradient(top,#fbb450,#f89406);background-image:-o-linear-gradient(top,#fbb450,#f89406);background-image:-moz-linear-gradient(top,#fbb450,#f89406);background-image:linear-gradient(top,#fbb450,#f89406);background-repeat:repeat-x;border-color:#f89406 #f89406 #ad6704;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:dximagetransform.microsoft.gradient(startColorstr='#fbb450',endColorstr='#f89406',GradientType=0);filter:progid:dximagetransform.microsoft.gradient(enabled=false)}.btn-warning:hover,.btn-warning:active,.btn-warning.active,.btn-warning.disabled,.btn-warning[disabled]{background-color:#f89406;*background-color:#df8505}.btn-warning:active,.btn-warning.active{background-color:#c67605 \9}.btn-danger{background-color:#da4f49;*background-color:#bd362f;background-image:-ms-linear-gradient(top,#ee5f5b,#bd362f);background-image:-webkit-gradient(linear,0 0,0 100%,from(#ee5f5b),to(#bd362f));background-image:-webkit-linear-gradient(top,#ee5f5b,#bd362f);background-image:-o-linear-gradient(top,#ee5f5b,#bd362f);background-image:-moz-linear-gradient(top,#ee5f5b,#bd362f);background-image:linear-gradient(top,#ee5f5b,#bd362f);background-repeat:repeat-x;border-color:#bd362f #bd362f #802420;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:dximagetransform.microsoft.gradient(startColorstr='#ee5f5b',endColorstr='#bd362f',GradientType=0);filter:progid:dximagetransform.microsoft.gradient(enabled=false)}.btn-danger:hover,.btn-danger:active,.btn-danger.active,.btn-danger.disabled,.btn-danger[disabled]{background-color:#bd362f;*background-color:#a9302a}.btn-danger:active,.btn-danger.active{background-color:#942a25 \9}.btn-success{background-color:#5bb75b;*background-color:#51a351;background-image:-ms-linear-gradient(top,#62c462,#51a351);background-image:-webkit-gradient(linear,0 0,0 100%,from(#62c462),to(#51a351));background-image:-webkit-linear-gradient(top,#62c462,#51a351);background-image:-o-linear-gradient(top,#62c462,#51a351);background-image:-moz-linear-gradient(top,#62c462,#51a351);background-image:linear-gradient(top,#62c462,#51a351);background-repeat:repeat-x;border-color:#51a351 #51a351 #387038;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:dximagetransform.microsoft.gradient(startColorstr='#62c462',endColorstr='#51a351',GradientType=0);filter:progid:dximagetransform.microsoft.gradient(enabled=false)}.btn-success:hover,.btn-success:active,.btn-success.active,.btn-success.disabled,.btn-success[disabled]{background-color:#51a351;*background-color:#499249}.btn-success:active,.btn-success.active{background-color:#408140 \9}.btn-info{background-color:#49afcd;*background-color:#2f96b4;background-image:-ms-linear-gradient(top,#5bc0de,#2f96b4);background-image:-webkit-gradient(linear,0 0,0 100%,from(#5bc0de),to(#2f96b4));background-image:-webkit-linear-gradient(top,#5bc0de,#2f96b4);background-image:-o-linear-gradient(top,#5bc0de,#2f96b4);background-image:-moz-linear-gradient(top,#5bc0de,#2f96b4);background-image:linear-gradient(top,#5bc0de,#2f96b4);background-repeat:repeat-x;border-color:#2f96b4 #2f96b4 #1f6377;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:dximagetransform.microsoft.gradient(startColorstr='#5bc0de',endColorstr='#2f96b4',GradientType=0);filter:progid:dximagetransform.microsoft.gradient(enabled=false)}.btn-info:hover,.btn-info:active,.btn-info.active,.btn-info.disabled,.btn-info[disabled]{background-color:#2f96b4;*background-color:#2a85a0}.btn-info:active,.btn-info.active{background-color:#24748c \9}.btn-inverse{background-color:#414141;*background-color:#222;background-image:-ms-linear-gradient(top,#555,#222);background-image:-webkit-gradient(linear,0 0,0 100%,from(#555),to(#222));background-image:-webkit-linear-gradient(top,#555,#222);background-image:-o-linear-gradient(top,#555,#222);background-image:-moz-linear-gradient(top,#555,#222);background-image:linear-gradient(top,#555,#222);background-repeat:repeat-x;border-color:#222 #222 #000;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:dximagetransform.microsoft.gradient(startColorstr='#555555',endColorstr='#222222',GradientType=0);filter:progid:dximagetransform.microsoft.gradient(enabled=false)}.btn-inverse:hover,.btn-inverse:active,.btn-inverse.active,.btn-inverse.disabled,.btn-inverse[disabled]{background-color:#222;*background-color:#151515}.btn-inverse:active,.btn-inverse.active{background-color:#080808 \9}button.btn,input[type="submit"].btn{*padding-top:2px;*padding-bottom:2px}button.btn::-moz-focus-inner,input[type="submit"].btn::-moz-focus-inner{padding:0;border:0}button.btn.btn-large,input[type="submit"].btn.btn-large{*padding-top:7px;*padding-bottom:7px}button.btn.btn-small,input[type="submit"].btn.btn-small{*padding-top:3px;*padding-bottom:3px}button.btn.btn-mini,input[type="submit"].btn.btn-mini{*padding-top:1px;*padding-bottom:1px}.btn-group{position:relative;*margin-left:.3em;*zoom:1}.btn-group:before,.btn-group:after{display:table;content:""}.btn-group:after{clear:both}.btn-group:first-child{*margin-left:0}.btn-group+.btn-group{margin-left:5px}.btn-toolbar{margin-top:9px;margin-bottom:9px}.btn-toolbar .btn-group{display:inline-block;*display:inline;*zoom:1}.btn-group>.btn{position:relative;float:left;margin-left:-1px;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.btn-group>.btn:first-child{margin-left:0;-webkit-border-bottom-left-radius:4px;border-bottom-left-radius:4px;-webkit-border-top-left-radius:4px;border-top-left-radius:4px;-moz-border-radius-bottomleft:4px;-moz-border-radius-topleft:4px}.btn-group>.btn:last-child,.btn-group>.dropdown-toggle{-webkit-border-top-right-radius:4px;border-top-right-radius:4px;-webkit-border-bottom-right-radius:4px;border-bottom-right-radius:4px;-moz-border-radius-topright:4px;-moz-border-radius-bottomright:4px}.btn-group>.btn.large:first-child{margin-left:0;-webkit-border-bottom-left-radius:6px;border-bottom-left-radius:6px;-webkit-border-top-left-radius:6px;border-top-left-radius:6px;-moz-border-radius-bottomleft:6px;-moz-border-radius-topleft:6px}.btn-group>.btn.large:last-child,.btn-group>.large.dropdown-toggle{-webkit-border-top-right-radius:6px;border-top-right-radius:6px;-webkit-border-bottom-right-radius:6px;border-bottom-right-radius:6px;-moz-border-radius-topright:6px;-moz-border-radius-bottomright:6px}.btn-group>.btn:hover,.btn-group>.btn:focus,.btn-group>.btn:active,.btn-group>.btn.active{z-index:2}.btn-group .dropdown-toggle:active,.btn-group.open .dropdown-toggle{outline:0}.btn-group>.dropdown-toggle{*padding-top:4px;padding-right:8px;*padding-bottom:4px;padding-left:8px;-webkit-box-shadow:inset 1px 0 0 rgba(255,255,255,0.125),inset 0 1px 0 rgba(255,255,255,0.2),0 1px 2px rgba(0,0,0,0.05);-moz-box-shadow:inset 1px 0 0 rgba(255,255,255,0.125),inset 0 1px 0 rgba(255,255,255,0.2),0 1px 2px rgba(0,0,0,0.05);box-shadow:inset 1px 0 0 rgba(255,255,255,0.125),inset 0 1px 0 rgba(255,255,255,0.2),0 1px 2px rgba(0,0,0,0.05)}.btn-group>.btn-mini.dropdown-toggle{padding-right:5px;padding-left:5px}.btn-group>.btn-small.dropdown-toggle{*padding-top:4px;*padding-bottom:4px}.btn-group>.btn-large.dropdown-toggle{padding-right:12px;padding-left:12px}.btn-group.open .dropdown-toggle{background-image:none;-webkit-box-shadow:inset 0 2px 4px rgba(0,0,0,0.15),0 1px 2px rgba(0,0,0,0.05);-moz-box-shadow:inset 0 2px 4px rgba(0,0,0,0.15),0 1px 2px rgba(0,0,0,0.05);box-shadow:inset 0 2px 4px rgba(0,0,0,0.15),0 1px 2px rgba(0,0,0,0.05)}.btn-group.open .btn.dropdown-toggle{background-color:#e6e6e6}.btn-group.open .btn-primary.dropdown-toggle{background-color:#05c}.btn-group.open .btn-warning.dropdown-toggle{background-color:#f89406}.btn-group.open .btn-danger.dropdown-toggle{background-color:#bd362f}.btn-group.open .btn-success.dropdown-toggle{background-color:#51a351}.btn-group.open .btn-info.dropdown-toggle{background-color:#2f96b4}.btn-group.open .btn-inverse.dropdown-toggle{background-color:#222}.btn .caret{margin-top:7px;margin-left:0}.btn:hover .caret,.open.btn-group .caret{opacity:1;filter:alpha(opacity=100)}.btn-mini .caret{margin-top:5px}.btn-small .caret{margin-top:6px}.btn-large .caret{margin-top:6px;border-top-width:5px;border-right-width:5px;border-left-width:5px}.dropup .btn-large .caret{border-top:0;border-bottom:5px solid #000}.btn-primary .caret,.btn-warning .caret,.btn-danger .caret,.btn-info .caret,.btn-success .caret,.btn-inverse .caret{border-top-color:#fff;border-bottom-color:#fff;opacity:.75;filter:alpha(opacity=75)}.alert{padding:8px 35px 8px 14px;margin-bottom:18px;color:#c09853;text-shadow:0 1px 0 rgba(255,255,255,0.5);background-color:#fcf8e3;border:1px solid #fbeed5;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.alert-heading{color:inherit}.alert .close{position:relative;top:-2px;right:-21px;line-height:18px}.alert-success{color:#468847;background-color:#dff0d8;border-color:#d6e9c6}.alert-danger,.alert-error{color:#b94a48;background-color:#f2dede;border-color:#eed3d7}.alert-info{color:#3a87ad;background-color:#d9edf7;border-color:#bce8f1}.alert-block{padding-top:14px;padding-bottom:14px}.alert-block>p,.alert-block>ul{margin-bottom:0}.alert-block p+p{margin-top:5px}.nav{margin-bottom:18px;margin-left:0;list-style:none}.nav>li>a{display:block}.nav>li>a:hover{text-decoration:none;background-color:#eee}.nav>.pull-right{float:right}.nav .nav-header{display:block;padding:3px 15px;font-size:11px;font-weight:bold;line-height:18px;color:#999;text-shadow:0 1px 0 rgba(255,255,255,0.5);text-transform:uppercase}.nav li+.nav-header{margin-top:9px}.nav-list{padding-right:15px;padding-left:15px;margin-bottom:0}.nav-list>li>a,.nav-list .nav-header{margin-right:-15px;margin-left:-15px;text-shadow:0 1px 0 rgba(255,255,255,0.5)}.nav-list>li>a{padding:3px 15px}.nav-list>.active>a,.nav-list>.active>a:hover{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.2);background-color:#08c}.nav-list [class^="icon-"]{margin-right:2px}.nav-list .divider{*width:100%;height:1px;margin:8px 1px;*margin:-5px 0 5px;overflow:hidden;background-color:#e5e5e5;border-bottom:1px solid #fff}.nav-tabs,.nav-pills{*zoom:1}.nav-tabs:before,.nav-pills:before,.nav-tabs:after,.nav-pills:after{display:table;content:""}.nav-tabs:after,.nav-pills:after{clear:both}.nav-tabs>li,.nav-pills>li{float:left}.nav-tabs>li>a,.nav-pills>li>a{padding-right:12px;padding-left:12px;margin-right:2px;line-height:14px}.nav-tabs{border-bottom:1px solid #ddd}.nav-tabs>li{margin-bottom:-1px}.nav-tabs>li>a{padding-top:8px;padding-bottom:8px;line-height:18px;border:1px solid transparent;-webkit-border-radius:4px 4px 0 0;-moz-border-radius:4px 4px 0 0;border-radius:4px 4px 0 0}.nav-tabs>li>a:hover{border-color:#eee #eee #ddd}.nav-tabs>.active>a,.nav-tabs>.active>a:hover{color:#555;cursor:default;background-color:#fff;border:1px solid #ddd;border-bottom-color:transparent}.nav-pills>li>a{padding-top:8px;padding-bottom:8px;margin-top:2px;margin-bottom:2px;-webkit-border-radius:5px;-moz-border-radius:5px;border-radius:5px}.nav-pills>.active>a,.nav-pills>.active>a:hover{color:#fff;background-color:#08c}.nav-stacked>li{float:none}.nav-stacked>li>a{margin-right:0}.nav-tabs.nav-stacked{border-bottom:0}.nav-tabs.nav-stacked>li>a{border:1px solid #ddd;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.nav-tabs.nav-stacked>li:first-child>a{-webkit-border-radius:4px 4px 0 0;-moz-border-radius:4px 4px 0 0;border-radius:4px 4px 0 0}.nav-tabs.nav-stacked>li:last-child>a{-webkit-border-radius:0 0 4px 4px;-moz-border-radius:0 0 4px 4px;border-radius:0 0 4px 4px}.nav-tabs.nav-stacked>li>a:hover{z-index:2;border-color:#ddd}.nav-pills.nav-stacked>li>a{margin-bottom:3px}.nav-pills.nav-stacked>li:last-child>a{margin-bottom:1px}.nav-tabs .dropdown-menu{-webkit-border-radius:0 0 5px 5px;-moz-border-radius:0 0 5px 5px;border-radius:0 0 5px 5px}.nav-pills .dropdown-menu{-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.nav-tabs .dropdown-toggle .caret,.nav-pills .dropdown-toggle .caret{margin-top:6px;border-top-color:#08c;border-bottom-color:#08c}.nav-tabs .dropdown-toggle:hover .caret,.nav-pills .dropdown-toggle:hover .caret{border-top-color:#005580;border-bottom-color:#005580}.nav-tabs .active .dropdown-toggle .caret,.nav-pills .active .dropdown-toggle .caret{border-top-color:#333;border-bottom-color:#333}.nav>.dropdown.active>a:hover{color:#000;cursor:pointer}.nav-tabs .open .dropdown-toggle,.nav-pills .open .dropdown-toggle,.nav>li.dropdown.open.active>a:hover{color:#fff;background-color:#999;border-color:#999}.nav li.dropdown.open .caret,.nav li.dropdown.open.active .caret,.nav li.dropdown.open a:hover .caret{border-top-color:#fff;border-bottom-color:#fff;opacity:1;filter:alpha(opacity=100)}.tabs-stacked .open>a:hover{border-color:#999}.tabbable{*zoom:1}.tabbable:before,.tabbable:after{display:table;content:""}.tabbable:after{clear:both}.tab-content{overflow:auto}.tabs-below>.nav-tabs,.tabs-right>.nav-tabs,.tabs-left>.nav-tabs{border-bottom:0}.tab-content>.tab-pane,.pill-content>.pill-pane{display:none}.tab-content>.active,.pill-content>.active{display:block}.tabs-below>.nav-tabs{border-top:1px solid #ddd}.tabs-below>.nav-tabs>li{margin-top:-1px;margin-bottom:0}.tabs-below>.nav-tabs>li>a{-webkit-border-radius:0 0 4px 4px;-moz-border-radius:0 0 4px 4px;border-radius:0 0 4px 4px}.tabs-below>.nav-tabs>li>a:hover{border-top-color:#ddd;border-bottom-color:transparent}.tabs-below>.nav-tabs>.active>a,.tabs-below>.nav-tabs>.active>a:hover{border-color:transparent #ddd #ddd #ddd}.tabs-left>.nav-tabs>li,.tabs-right>.nav-tabs>li{float:none}.tabs-left>.nav-tabs>li>a,.tabs-right>.nav-tabs>li>a{min-width:74px;margin-right:0;margin-bottom:3px}.tabs-left>.nav-tabs{float:left;margin-right:19px;border-right:1px solid #ddd}.tabs-left>.nav-tabs>li>a{margin-right:-1px;-webkit-border-radius:4px 0 0 4px;-moz-border-radius:4px 0 0 4px;border-radius:4px 0 0 4px}.tabs-left>.nav-tabs>li>a:hover{border-color:#eee #ddd #eee #eee}.tabs-left>.nav-tabs .active>a,.tabs-left>.nav-tabs .active>a:hover{border-color:#ddd transparent #ddd #ddd;*border-right-color:#fff}.tabs-right>.nav-tabs{float:right;margin-left:19px;border-left:1px solid #ddd}.tabs-right>.nav-tabs>li>a{margin-left:-1px;-webkit-border-radius:0 4px 4px 0;-moz-border-radius:0 4px 4px 0;border-radius:0 4px 4px 0}.tabs-right>.nav-tabs>li>a:hover{border-color:#eee #eee #eee #ddd}.tabs-right>.nav-tabs .active>a,.tabs-right>.nav-tabs .active>a:hover{border-color:#ddd #ddd #ddd transparent;*border-left-color:#fff}.navbar{*position:relative;*z-index:2;margin-bottom:18px;overflow:visible}.navbar-inner{min-height:40px;padding-right:20px;padding-left:20px;background-color:#2c2c2c;background-image:-moz-linear-gradient(top,#333,#222);background-image:-ms-linear-gradient(top,#333,#222);background-image:-webkit-gradient(linear,0 0,0 100%,from(#333),to(#222));background-image:-webkit-linear-gradient(top,#333,#222);background-image:-o-linear-gradient(top,#333,#222);background-image:linear-gradient(top,#333,#222);background-repeat:repeat-x;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;filter:progid:dximagetransform.microsoft.gradient(startColorstr='#333333',endColorstr='#222222',GradientType=0);-webkit-box-shadow:0 1px 3px rgba(0,0,0,0.25),inset 0 -1px 0 rgba(0,0,0,0.1);-moz-box-shadow:0 1px 3px rgba(0,0,0,0.25),inset 0 -1px 0 rgba(0,0,0,0.1);box-shadow:0 1px 3px rgba(0,0,0,0.25),inset 0 -1px 0 rgba(0,0,0,0.1)}.navbar .container{width:auto}.nav-collapse.collapse{height:auto}.navbar{color:#999}.navbar .brand:hover{text-decoration:none}.navbar .brand{display:block;float:left;padding:8px 20px 12px;margin-left:-20px;font-size:20px;font-weight:200;line-height:1;color:#999}.navbar .navbar-text{margin-bottom:0;line-height:40px}.navbar .navbar-link{color:#999}.navbar .navbar-link:hover{color:#fff}.navbar .btn,.navbar .btn-group{margin-top:5px}.navbar .btn-group .btn{margin:0}.navbar-form{margin-bottom:0;*zoom:1}.navbar-form:before,.navbar-form:after{display:table;content:""}.navbar-form:after{clear:both}.navbar-form input,.navbar-form select,.navbar-form .radio,.navbar-form .checkbox{margin-top:5px}.navbar-form input,.navbar-form select{display:inline-block;margin-bottom:0}.navbar-form input[type="image"],.navbar-form input[type="checkbox"],.navbar-form input[type="radio"]{margin-top:3px}.navbar-form .input-append,.navbar-form .input-prepend{margin-top:6px;white-space:nowrap}.navbar-form .input-append input,.navbar-form .input-prepend input{margin-top:0}.navbar-search{position:relative;float:left;margin-top:6px;margin-bottom:0}.navbar-search .search-query{padding:4px 9px;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:13px;font-weight:normal;line-height:1;color:#fff;background-color:#626262;border:1px solid #151515;-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,0.1),0 1px 0 rgba(255,255,255,0.15);-moz-box-shadow:inset 0 1px 2px rgba(0,0,0,0.1),0 1px 0 rgba(255,255,255,0.15);box-shadow:inset 0 1px 2px rgba(0,0,0,0.1),0 1px 0 rgba(255,255,255,0.15);-webkit-transition:none;-moz-transition:none;-ms-transition:none;-o-transition:none;transition:none}.navbar-search .search-query:-moz-placeholder{color:#ccc}.navbar-search .search-query:-ms-input-placeholder{color:#ccc}.navbar-search .search-query::-webkit-input-placeholder{color:#ccc}.navbar-search .search-query:focus,.navbar-search .search-query.focused{padding:5px 10px;color:#333;text-shadow:0 1px 0 #fff;background-color:#fff;border:0;outline:0;-webkit-box-shadow:0 0 3px rgba(0,0,0,0.15);-moz-box-shadow:0 0 3px rgba(0,0,0,0.15);box-shadow:0 0 3px rgba(0,0,0,0.15)}.navbar-fixed-top,.navbar-fixed-bottom{position:fixed;right:0;left:0;z-index:1030;margin-bottom:0}.navbar-fixed-top .navbar-inner,.navbar-fixed-bottom .navbar-inner{padding-right:0;padding-left:0;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.navbar-fixed-top .container,.navbar-fixed-bottom .container{width:940px}.navbar-fixed-top{top:0}.navbar-fixed-bottom{bottom:0}.navbar .nav{position:relative;left:0;display:block;float:left;margin:0 10px 0 0}.navbar .nav.pull-right{float:right}.navbar .nav>li{display:block;float:left}.navbar .nav>li>a{float:none;padding:9px 10px 11px;line-height:19px;color:#999;text-decoration:none;text-shadow:0 -1px 0 rgba(0,0,0,0.25)}.navbar .btn{display:inline-block;padding:4px 10px 4px;margin:5px 5px 6px;line-height:18px}.navbar .btn-group{padding:5px 5px 6px;margin:0}.navbar .nav>li>a:hover{color:#fff;text-decoration:none;background-color:transparent}.navbar .nav .active>a,.navbar .nav .active>a:hover{color:#fff;text-decoration:none;background-color:#222}.navbar .divider-vertical{width:1px;height:40px;margin:0 9px;overflow:hidden;background-color:#222;border-right:1px solid #333}.navbar .nav.pull-right{margin-right:0;margin-left:10px}.navbar .btn-navbar{display:none;float:right;padding:7px 10px;margin-right:5px;margin-left:5px;background-color:#2c2c2c;*background-color:#222;background-image:-ms-linear-gradient(top,#333,#222);background-image:-webkit-gradient(linear,0 0,0 100%,from(#333),to(#222));background-image:-webkit-linear-gradient(top,#333,#222);background-image:-o-linear-gradient(top,#333,#222);background-image:linear-gradient(top,#333,#222);background-image:-moz-linear-gradient(top,#333,#222);background-repeat:repeat-x;border-color:#222 #222 #000;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:dximagetransform.microsoft.gradient(startColorstr='#333333',endColorstr='#222222',GradientType=0);filter:progid:dximagetransform.microsoft.gradient(enabled=false);-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.075);-moz-box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.075);box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.075)}.navbar .btn-navbar:hover,.navbar .btn-navbar:active,.navbar .btn-navbar.active,.navbar .btn-navbar.disabled,.navbar .btn-navbar[disabled]{background-color:#222;*background-color:#151515}.navbar .btn-navbar:active,.navbar .btn-navbar.active{background-color:#080808 \9}.navbar .btn-navbar .icon-bar{display:block;width:18px;height:2px;background-color:#f5f5f5;-webkit-border-radius:1px;-moz-border-radius:1px;border-radius:1px;-webkit-box-shadow:0 1px 0 rgba(0,0,0,0.25);-moz-box-shadow:0 1px 0 rgba(0,0,0,0.25);box-shadow:0 1px 0 rgba(0,0,0,0.25)}.btn-navbar .icon-bar+.icon-bar{margin-top:3px}.navbar .dropdown-menu:before{position:absolute;top:-7px;left:9px;display:inline-block;border-right:7px solid transparent;border-bottom:7px solid #ccc;border-left:7px solid transparent;border-bottom-color:rgba(0,0,0,0.2);content:''}.navbar .dropdown-menu:after{position:absolute;top:-6px;left:10px;display:inline-block;border-right:6px solid transparent;border-bottom:6px solid #fff;border-left:6px solid transparent;content:''}.navbar-fixed-bottom .dropdown-menu:before{top:auto;bottom:-7px;border-top:7px solid #ccc;border-bottom:0;border-top-color:rgba(0,0,0,0.2)}.navbar-fixed-bottom .dropdown-menu:after{top:auto;bottom:-6px;border-top:6px solid #fff;border-bottom:0}.navbar .nav li.dropdown .dropdown-toggle .caret,.navbar .nav li.dropdown.open .caret{border-top-color:#fff;border-bottom-color:#fff}.navbar .nav li.dropdown.active .caret{opacity:1;filter:alpha(opacity=100)}.navbar .nav li.dropdown.open>.dropdown-toggle,.navbar .nav li.dropdown.active>.dropdown-toggle,.navbar .nav li.dropdown.open.active>.dropdown-toggle{background-color:transparent}.navbar .nav li.dropdown.active>.dropdown-toggle:hover{color:#fff}.navbar .pull-right .dropdown-menu,.navbar .dropdown-menu.pull-right{right:0;left:auto}.navbar .pull-right .dropdown-menu:before,.navbar .dropdown-menu.pull-right:before{right:12px;left:auto}.navbar .pull-right .dropdown-menu:after,.navbar .dropdown-menu.pull-right:after{right:13px;left:auto}.breadcrumb{padding:7px 14px;margin:0 0 18px;list-style:none;background-color:#fbfbfb;background-image:-moz-linear-gradient(top,#fff,#f5f5f5);background-image:-ms-linear-gradient(top,#fff,#f5f5f5);background-image:-webkit-gradient(linear,0 0,0 100%,from(#fff),to(#f5f5f5));background-image:-webkit-linear-gradient(top,#fff,#f5f5f5);background-image:-o-linear-gradient(top,#fff,#f5f5f5);background-image:linear-gradient(top,#fff,#f5f5f5);background-repeat:repeat-x;border:1px solid #ddd;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;filter:progid:dximagetransform.microsoft.gradient(startColorstr='#ffffff',endColorstr='#f5f5f5',GradientType=0);-webkit-box-shadow:inset 0 1px 0 #fff;-moz-box-shadow:inset 0 1px 0 #fff;box-shadow:inset 0 1px 0 #fff}.breadcrumb li{display:inline-block;*display:inline;text-shadow:0 1px 0 #fff;*zoom:1}.breadcrumb .divider{padding:0 5px;color:#999}.breadcrumb .active a{color:#333}.pagination{height:36px;margin:18px 0}.pagination ul{display:inline-block;*display:inline;margin-bottom:0;margin-left:0;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;*zoom:1;-webkit-box-shadow:0 1px 2px rgba(0,0,0,0.05);-moz-box-shadow:0 1px 2px rgba(0,0,0,0.05);box-shadow:0 1px 2px rgba(0,0,0,0.05)}.pagination li{display:inline}.pagination a{float:left;padding:0 14px;line-height:34px;text-decoration:none;border:1px solid #ddd;border-left-width:0}.pagination a:hover,.pagination .active a{background-color:#f5f5f5}.pagination .active a{color:#999;cursor:default}.pagination .disabled span,.pagination .disabled a,.pagination .disabled a:hover{color:#999;cursor:default;background-color:transparent}.pagination li:first-child a{border-left-width:1px;-webkit-border-radius:3px 0 0 3px;-moz-border-radius:3px 0 0 3px;border-radius:3px 0 0 3px}.pagination li:last-child a{-webkit-border-radius:0 3px 3px 0;-moz-border-radius:0 3px 3px 0;border-radius:0 3px 3px 0}.pagination-centered{text-align:center}.pagination-right{text-align:right}.pager{margin-bottom:18px;margin-left:0;text-align:center;list-style:none;*zoom:1}.pager:before,.pager:after{display:table;content:""}.pager:after{clear:both}.pager li{display:inline}.pager a{display:inline-block;padding:5px 14px;background-color:#fff;border:1px solid #ddd;-webkit-border-radius:15px;-moz-border-radius:15px;border-radius:15px}.pager a:hover{text-decoration:none;background-color:#f5f5f5}.pager .next a{float:right}.pager .previous a{float:left}.pager .disabled a,.pager .disabled a:hover{color:#999;cursor:default;background-color:#fff}.modal-open .dropdown-menu{z-index:2050}.modal-open .dropdown.open{*z-index:2050}.modal-open .popover{z-index:2060}.modal-open .tooltip{z-index:2070}.modal-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1040;background-color:#000}.modal-backdrop.fade{opacity:0}.modal-backdrop,.modal-backdrop.fade.in{opacity:.8;filter:alpha(opacity=80)}.modal{position:fixed;top:50%;left:50%;z-index:1050;width:560px;margin:-250px 0 0 -280px;overflow:auto;background-color:#fff;border:1px solid #999;border:1px solid rgba(0,0,0,0.3);*border:1px solid #999;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px;-webkit-box-shadow:0 3px 7px rgba(0,0,0,0.3);-moz-box-shadow:0 3px 7px rgba(0,0,0,0.3);box-shadow:0 3px 7px rgba(0,0,0,0.3);-webkit-background-clip:padding-box;-moz-background-clip:padding-box;background-clip:padding-box}.modal.fade{top:-25%;-webkit-transition:opacity .3s linear,top .3s ease-out;-moz-transition:opacity .3s linear,top .3s ease-out;-ms-transition:opacity .3s linear,top .3s ease-out;-o-transition:opacity .3s linear,top .3s ease-out;transition:opacity .3s linear,top .3s ease-out}.modal.fade.in{top:50%}.modal-header{padding:9px 15px;border-bottom:1px solid #eee}.modal-header .close{margin-top:2px}.modal-body{max-height:400px;padding:15px;overflow-y:auto}.modal-form{margin-bottom:0}.modal-footer{padding:14px 15px 15px;margin-bottom:0;text-align:right;background-color:#f5f5f5;border-top:1px solid #ddd;-webkit-border-radius:0 0 6px 6px;-moz-border-radius:0 0 6px 6px;border-radius:0 0 6px 6px;*zoom:1;-webkit-box-shadow:inset 0 1px 0 #fff;-moz-box-shadow:inset 0 1px 0 #fff;box-shadow:inset 0 1px 0 #fff}.modal-footer:before,.modal-footer:after{display:table;content:""}.modal-footer:after{clear:both}.modal-footer .btn+.btn{margin-bottom:0;margin-left:5px}.modal-footer .btn-group .btn+.btn{margin-left:-1px}.tooltip{position:absolute;z-index:1020;display:block;padding:5px;font-size:11px;opacity:0;filter:alpha(opacity=0);visibility:visible}.tooltip.in{opacity:.8;filter:alpha(opacity=80)}.tooltip.top{margin-top:-2px}.tooltip.right{margin-left:2px}.tooltip.bottom{margin-top:2px}.tooltip.left{margin-left:-2px}.tooltip.top .tooltip-arrow{bottom:0;left:50%;margin-left:-5px;border-top:5px solid #000;border-right:5px solid transparent;border-left:5px solid transparent}.tooltip.left .tooltip-arrow{top:50%;right:0;margin-top:-5px;border-top:5px solid transparent;border-bottom:5px solid transparent;border-left:5px solid #000}.tooltip.bottom .tooltip-arrow{top:0;left:50%;margin-left:-5px;border-right:5px solid transparent;border-bottom:5px solid #000;border-left:5px solid transparent}.tooltip.right .tooltip-arrow{top:50%;left:0;margin-top:-5px;border-top:5px solid transparent;border-right:5px solid #000;border-bottom:5px solid transparent}.tooltip-inner{max-width:200px;padding:3px 8px;color:#fff;text-align:center;text-decoration:none;background-color:#000;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.tooltip-arrow{position:absolute;width:0;height:0}.popover{position:absolute;top:0;left:0;z-index:1010;display:none;padding:5px}.popover.top{margin-top:-5px}.popover.right{margin-left:5px}.popover.bottom{margin-top:5px}.popover.left{margin-left:-5px}.popover.top .arrow{bottom:0;left:50%;margin-left:-5px;border-top:5px solid #000;border-right:5px solid transparent;border-left:5px solid transparent}.popover.right .arrow{top:50%;left:0;margin-top:-5px;border-top:5px solid transparent;border-right:5px solid #000;border-bottom:5px solid transparent}.popover.bottom .arrow{top:0;left:50%;margin-left:-5px;border-right:5px solid transparent;border-bottom:5px solid #000;border-left:5px solid transparent}.popover.left .arrow{top:50%;right:0;margin-top:-5px;border-top:5px solid transparent;border-bottom:5px solid transparent;border-left:5px solid #000}.popover .arrow{position:absolute;width:0;height:0}.popover-inner{width:280px;padding:3px;overflow:hidden;background:#000;background:rgba(0,0,0,0.8);-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px;-webkit-box-shadow:0 3px 7px rgba(0,0,0,0.3);-moz-box-shadow:0 3px 7px rgba(0,0,0,0.3);box-shadow:0 3px 7px rgba(0,0,0,0.3)}.popover-title{padding:9px 15px;line-height:1;background-color:#f5f5f5;border-bottom:1px solid #eee;-webkit-border-radius:3px 3px 0 0;-moz-border-radius:3px 3px 0 0;border-radius:3px 3px 0 0}.popover-content{padding:14px;background-color:#fff;-webkit-border-radius:0 0 3px 3px;-moz-border-radius:0 0 3px 3px;border-radius:0 0 3px 3px;-webkit-background-clip:padding-box;-moz-background-clip:padding-box;background-clip:padding-box}.popover-content p,.popover-content ul,.popover-content ol{margin-bottom:0}.thumbnails{margin-left:-20px;list-style:none;*zoom:1}.thumbnails:before,.thumbnails:after{display:table;content:""}.thumbnails:after{clear:both}.row-fluid .thumbnails{margin-left:0}.thumbnails>li{float:left;margin-bottom:18px;margin-left:20px}.thumbnail{display:block;padding:4px;line-height:1;border:1px solid #ddd;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;-webkit-box-shadow:0 1px 1px rgba(0,0,0,0.075);-moz-box-shadow:0 1px 1px rgba(0,0,0,0.075);box-shadow:0 1px 1px rgba(0,0,0,0.075)}a.thumbnail:hover{border-color:#08c;-webkit-box-shadow:0 1px 4px rgba(0,105,214,0.25);-moz-box-shadow:0 1px 4px rgba(0,105,214,0.25);box-shadow:0 1px 4px rgba(0,105,214,0.25)}.thumbnail>img{display:block;max-width:100%;margin-right:auto;margin-left:auto}.thumbnail .caption{padding:9px}.label,.badge{font-size:10.998px;font-weight:bold;line-height:14px;color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);white-space:nowrap;vertical-align:baseline;background-color:#999}.label{padding:1px 4px 2px;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px}.badge{padding:1px 9px 2px;-webkit-border-radius:9px;-moz-border-radius:9px;border-radius:9px}a.label:hover,a.badge:hover{color:#fff;text-decoration:none;cursor:pointer}.label-important,.badge-important{background-color:#b94a48}.label-important[href],.badge-important[href]{background-color:#953b39}.label-warning,.badge-warning{background-color:#f89406}.label-warning[href],.badge-warning[href]{background-color:#c67605}.label-success,.badge-success{background-color:#468847}.label-success[href],.badge-success[href]{background-color:#356635}.label-info,.badge-info{background-color:#3a87ad}.label-info[href],.badge-info[href]{background-color:#2d6987}.label-inverse,.badge-inverse{background-color:#333}.label-inverse[href],.badge-inverse[href]{background-color:#1a1a1a}@-webkit-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@-moz-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@-ms-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@-o-keyframes progress-bar-stripes{from{background-position:0 0}to{background-position:40px 0}}@keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}.progress{height:18px;margin-bottom:18px;overflow:hidden;background-color:#f7f7f7;background-image:-moz-linear-gradient(top,#f5f5f5,#f9f9f9);background-image:-ms-linear-gradient(top,#f5f5f5,#f9f9f9);background-image:-webkit-gradient(linear,0 0,0 100%,from(#f5f5f5),to(#f9f9f9));background-image:-webkit-linear-gradient(top,#f5f5f5,#f9f9f9);background-image:-o-linear-gradient(top,#f5f5f5,#f9f9f9);background-image:linear-gradient(top,#f5f5f5,#f9f9f9);background-repeat:repeat-x;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;filter:progid:dximagetransform.microsoft.gradient(startColorstr='#f5f5f5',endColorstr='#f9f9f9',GradientType=0);-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,0.1);-moz-box-shadow:inset 0 1px 2px rgba(0,0,0,0.1);box-shadow:inset 0 1px 2px rgba(0,0,0,0.1)}.progress .bar{width:0;height:18px;font-size:12px;color:#fff;text-align:center;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#0e90d2;background-image:-moz-linear-gradient(top,#149bdf,#0480be);background-image:-webkit-gradient(linear,0 0,0 100%,from(#149bdf),to(#0480be));background-image:-webkit-linear-gradient(top,#149bdf,#0480be);background-image:-o-linear-gradient(top,#149bdf,#0480be);background-image:linear-gradient(top,#149bdf,#0480be);background-image:-ms-linear-gradient(top,#149bdf,#0480be);background-repeat:repeat-x;filter:progid:dximagetransform.microsoft.gradient(startColorstr='#149bdf',endColorstr='#0480be',GradientType=0);-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,0.15);-moz-box-shadow:inset 0 -1px 0 rgba(0,0,0,0.15);box-shadow:inset 0 -1px 0 rgba(0,0,0,0.15);-webkit-box-sizing:border-box;-moz-box-sizing:border-box;-ms-box-sizing:border-box;box-sizing:border-box;-webkit-transition:width .6s ease;-moz-transition:width .6s ease;-ms-transition:width .6s ease;-o-transition:width .6s ease;transition:width .6s ease}.progress-striped .bar{background-color:#149bdf;background-image:-o-linear-gradient(-45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-webkit-linear-gradient(-45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-moz-linear-gradient(-45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-ms-linear-gradient(-45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-webkit-gradient(linear,0 100%,100% 0,color-stop(0.25,rgba(255,255,255,0.15)),color-stop(0.25,transparent),color-stop(0.5,transparent),color-stop(0.5,rgba(255,255,255,0.15)),color-stop(0.75,rgba(255,255,255,0.15)),color-stop(0.75,transparent),to(transparent));background-image:linear-gradient(-45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);-webkit-background-size:40px 40px;-moz-background-size:40px 40px;-o-background-size:40px 40px;background-size:40px 40px}.progress.active .bar{-webkit-animation:progress-bar-stripes 2s linear infinite;-moz-animation:progress-bar-stripes 2s linear infinite;-ms-animation:progress-bar-stripes 2s linear infinite;-o-animation:progress-bar-stripes 2s linear infinite;animation:progress-bar-stripes 2s linear infinite}.progress-danger .bar{background-color:#dd514c;background-image:-moz-linear-gradient(top,#ee5f5b,#c43c35);background-image:-ms-linear-gradient(top,#ee5f5b,#c43c35);background-image:-webkit-gradient(linear,0 0,0 100%,from(#ee5f5b),to(#c43c35));background-image:-webkit-linear-gradient(top,#ee5f5b,#c43c35);background-image:-o-linear-gradient(top,#ee5f5b,#c43c35);background-image:linear-gradient(top,#ee5f5b,#c43c35);background-repeat:repeat-x;filter:progid:dximagetransform.microsoft.gradient(startColorstr='#ee5f5b',endColorstr='#c43c35',GradientType=0)}.progress-danger.progress-striped .bar{background-color:#ee5f5b;background-image:-webkit-gradient(linear,0 100%,100% 0,color-stop(0.25,rgba(255,255,255,0.15)),color-stop(0.25,transparent),color-stop(0.5,transparent),color-stop(0.5,rgba(255,255,255,0.15)),color-stop(0.75,rgba(255,255,255,0.15)),color-stop(0.75,transparent),to(transparent));background-image:-webkit-linear-gradient(-45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-moz-linear-gradient(-45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-ms-linear-gradient(-45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(-45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:linear-gradient(-45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent)}.progress-success .bar{background-color:#5eb95e;background-image:-moz-linear-gradient(top,#62c462,#57a957);background-image:-ms-linear-gradient(top,#62c462,#57a957);background-image:-webkit-gradient(linear,0 0,0 100%,from(#62c462),to(#57a957));background-image:-webkit-linear-gradient(top,#62c462,#57a957);background-image:-o-linear-gradient(top,#62c462,#57a957);background-image:linear-gradient(top,#62c462,#57a957);background-repeat:repeat-x;filter:progid:dximagetransform.microsoft.gradient(startColorstr='#62c462',endColorstr='#57a957',GradientType=0)}.progress-success.progress-striped .bar{background-color:#62c462;background-image:-webkit-gradient(linear,0 100%,100% 0,color-stop(0.25,rgba(255,255,255,0.15)),color-stop(0.25,transparent),color-stop(0.5,transparent),color-stop(0.5,rgba(255,255,255,0.15)),color-stop(0.75,rgba(255,255,255,0.15)),color-stop(0.75,transparent),to(transparent));background-image:-webkit-linear-gradient(-45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-moz-linear-gradient(-45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-ms-linear-gradient(-45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(-45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:linear-gradient(-45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent)}.progress-info .bar{background-color:#4bb1cf;background-image:-moz-linear-gradient(top,#5bc0de,#339bb9);background-image:-ms-linear-gradient(top,#5bc0de,#339bb9);background-image:-webkit-gradient(linear,0 0,0 100%,from(#5bc0de),to(#339bb9));background-image:-webkit-linear-gradient(top,#5bc0de,#339bb9);background-image:-o-linear-gradient(top,#5bc0de,#339bb9);background-image:linear-gradient(top,#5bc0de,#339bb9);background-repeat:repeat-x;filter:progid:dximagetransform.microsoft.gradient(startColorstr='#5bc0de',endColorstr='#339bb9',GradientType=0)}.progress-info.progress-striped .bar{background-color:#5bc0de;background-image:-webkit-gradient(linear,0 100%,100% 0,color-stop(0.25,rgba(255,255,255,0.15)),color-stop(0.25,transparent),color-stop(0.5,transparent),color-stop(0.5,rgba(255,255,255,0.15)),color-stop(0.75,rgba(255,255,255,0.15)),color-stop(0.75,transparent),to(transparent));background-image:-webkit-linear-gradient(-45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-moz-linear-gradient(-45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-ms-linear-gradient(-45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(-45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:linear-gradient(-45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent)}.progress-warning .bar{background-color:#faa732;background-image:-moz-linear-gradient(top,#fbb450,#f89406);background-image:-ms-linear-gradient(top,#fbb450,#f89406);background-image:-webkit-gradient(linear,0 0,0 100%,from(#fbb450),to(#f89406));background-image:-webkit-linear-gradient(top,#fbb450,#f89406);background-image:-o-linear-gradient(top,#fbb450,#f89406);background-image:linear-gradient(top,#fbb450,#f89406);background-repeat:repeat-x;filter:progid:dximagetransform.microsoft.gradient(startColorstr='#fbb450',endColorstr='#f89406',GradientType=0)}.progress-warning.progress-striped .bar{background-color:#fbb450;background-image:-webkit-gradient(linear,0 100%,100% 0,color-stop(0.25,rgba(255,255,255,0.15)),color-stop(0.25,transparent),color-stop(0.5,transparent),color-stop(0.5,rgba(255,255,255,0.15)),color-stop(0.75,rgba(255,255,255,0.15)),color-stop(0.75,transparent),to(transparent));background-image:-webkit-linear-gradient(-45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-moz-linear-gradient(-45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-ms-linear-gradient(-45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(-45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:linear-gradient(-45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent)}.accordion{margin-bottom:18px}.accordion-group{margin-bottom:2px;border:1px solid #e5e5e5;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.accordion-heading{border-bottom:0}.accordion-heading .accordion-toggle{display:block;padding:8px 15px}.accordion-toggle{cursor:pointer}.accordion-inner{padding:9px 15px;border-top:1px solid #e5e5e5}.carousel{position:relative;margin-bottom:18px;line-height:1}.carousel-inner{position:relative;width:100%;overflow:hidden}.carousel .item{position:relative;display:none;-webkit-transition:.6s ease-in-out left;-moz-transition:.6s ease-in-out left;-ms-transition:.6s ease-in-out left;-o-transition:.6s ease-in-out left;transition:.6s ease-in-out left}.carousel .item>img{display:block;line-height:1}.carousel .active,.carousel .next,.carousel .prev{display:block}.carousel .active{left:0}.carousel .next,.carousel .prev{position:absolute;top:0;width:100%}.carousel .next{left:100%}.carousel .prev{left:-100%}.carousel .next.left,.carousel .prev.right{left:0}.carousel .active.left{left:-100%}.carousel .active.right{left:100%}.carousel-control{position:absolute;top:40%;left:15px;width:40px;height:40px;margin-top:-20px;font-size:60px;font-weight:100;line-height:30px;color:#fff;text-align:center;background:#222;border:3px solid #fff;-webkit-border-radius:23px;-moz-border-radius:23px;border-radius:23px;opacity:.5;filter:alpha(opacity=50)}.carousel-control.right{right:15px;left:auto}.carousel-control:hover{color:#fff;text-decoration:none;opacity:.9;filter:alpha(opacity=90)}.carousel-caption{position:absolute;right:0;bottom:0;left:0;padding:10px 15px 5px;background:#333;background:rgba(0,0,0,0.75)}.carousel-caption h4,.carousel-caption p{color:#fff}.hero-unit{padding:60px;margin-bottom:30px;background-color:#eee;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px}.hero-unit h1{margin-bottom:0;font-size:60px;line-height:1;letter-spacing:-1px;color:inherit}.hero-unit p{font-size:18px;font-weight:200;line-height:27px;color:inherit}.pull-right{float:right}.pull-left{float:left}.hide{display:none}.show{display:block}.invisible{visibility:hidden} diff --git a/www/assets/css/nv.d3.css b/www/assets/css/nv.d3.css deleted file mode 100644 index ca63f839..00000000 --- a/www/assets/css/nv.d3.css +++ /dev/null @@ -1,671 +0,0 @@ - -/******************** - * HTML CSS - */ - - -.chartWrap { - margin: 0; - padding: 0; - overflow: hidden; -} - - -/******************** - * TOOLTIP CSS - */ - -.nvtooltip { - position: absolute; - background-color: rgba(255,255,255,1); - padding: 1px; - border: 1px solid rgba(0,0,0,.2); - z-index: 10000; - - font-family: Arial; - font-size: 13px; - - transition: opacity 500ms linear; - -moz-transition: opacity 500ms linear; - -webkit-transition: opacity 500ms linear; - - transition-delay: 500ms; - -moz-transition-delay: 500ms; - -webkit-transition-delay: 500ms; - - -moz-box-shadow: 0 5px 10px rgba(0,0,0,.2); - -webkit-box-shadow: 0 5px 10px rgba(0,0,0,.2); - box-shadow: 0 5px 10px rgba(0,0,0,.2); - - -webkit-border-radius: 6px; - -moz-border-radius: 6px; - border-radius: 6px; - - pointer-events: none; - - -webkit-touch-callout: none; - -webkit-user-select: none; - -khtml-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; -} - -.nvtooltip.x-nvtooltip, -.nvtooltip.y-nvtooltip { - padding: 8px; -} - -.nvtooltip h3 { - margin: 0; - padding: 4px 14px; - line-height: 18px; - font-weight: normal; - background-color: #f7f7f7; - text-align: center; - - border-bottom: 1px solid #ebebeb; - - -webkit-border-radius: 5px 5px 0 0; - -moz-border-radius: 5px 5px 0 0; - border-radius: 5px 5px 0 0; -} - -.nvtooltip p { - margin: 0; - padding: 5px 14px; - text-align: center; -} - -.nvtooltip span { - display: inline-block; - margin: 2px 0; -} - -.nvtooltip-pending-removal { - position: absolute; - pointer-events: none; -} - - -/******************** - * SVG CSS - */ - - -svg { - -webkit-touch-callout: none; - -webkit-user-select: none; - -khtml-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; - /* Trying to get SVG to act like a greedy block in all browsers */ - display: block; - width:100%; - height:100%; -} - - -svg text { - font: normal 12px Arial; -} - -svg .title { - font: bold 14px Arial; -} - -.nvd3 .nv-background { - fill: white; - fill-opacity: 0; - /* - pointer-events: none; - */ -} - -.nvd3.nv-noData { - font-size: 18px; - font-weight: bold; -} - - -/********** -* Brush -*/ - -.nv-brush .extent { - fill-opacity: .125; - shape-rendering: crispEdges; -} - - - -/********** -* Legend -*/ - -.nvd3 .nv-legend .nv-series { - cursor: pointer; -} - -.nvd3 .nv-legend .disabled circle { - fill-opacity: 0; -} - - - -/********** -* Axes -*/ - -.nvd3 .nv-axis path { - fill: none; - stroke: #000; - stroke-opacity: .75; - shape-rendering: crispEdges; -} - -.nvd3 .nv-axis path.domain { - stroke-opacity: .75; -} - -.nvd3 .nv-axis.nv-x path.domain { - stroke-opacity: 0; -} - -.nvd3 .nv-axis line { - fill: none; - stroke: #000; - stroke-opacity: .25; - shape-rendering: crispEdges; -} - -.nvd3 .nv-axis line.zero { - stroke-opacity: .75; -} - -.nvd3 .nv-axis .nv-axisMaxMin text { - font-weight: bold; -} - -.nvd3 .x .nv-axis .nv-axisMaxMin text, -.nvd3 .x2 .nv-axis .nv-axisMaxMin text, -.nvd3 .x3 .nv-axis .nv-axisMaxMin text { - text-anchor: middle -} - - - -/********** -* Brush -*/ - -.nv-brush .resize path { - fill: #eee; - stroke: #666; -} - - - -/********** -* Bars -*/ - -.nvd3 .nv-bars .negative rect { - zfill: brown; -} - -.nvd3 .nv-bars rect { - zfill: steelblue; - fill-opacity: .75; - - transition: fill-opacity 250ms linear; - -moz-transition: fill-opacity 250ms linear; - -webkit-transition: fill-opacity 250ms linear; -} - -.nvd3 .nv-bars rect:hover { - fill-opacity: 1; -} - -.nvd3 .nv-bars .hover rect { - fill: lightblue; -} - -.nvd3 .nv-bars text { - fill: rgba(0,0,0,0); -} - -.nvd3 .nv-bars .hover text { - fill: rgba(0,0,0,1); -} - - -/********** -* Bars -*/ - -.nvd3 .nv-multibar .nv-groups rect, -.nvd3 .nv-multibarHorizontal .nv-groups rect, -.nvd3 .nv-discretebar .nv-groups rect { - stroke-opacity: 0; - - transition: fill-opacity 250ms linear; - -moz-transition: fill-opacity 250ms linear; - -webkit-transition: fill-opacity 250ms linear; -} - -.nvd3 .nv-multibar .nv-groups rect:hover, -.nvd3 .nv-multibarHorizontal .nv-groups rect:hover, -.nvd3 .nv-discretebar .nv-groups rect:hover { - fill-opacity: 1; -} - -.nvd3 .nv-discretebar .nv-groups text, -.nvd3 .nv-multibarHorizontal .nv-groups text { - font-weight: bold; - fill: rgba(0,0,0,1); - stroke: rgba(0,0,0,0); -} - -/*********** -* Pie Chart -*/ - -.nvd3.nv-pie path { - stroke-opacity: 0; - - transition: fill-opacity 250ms linear, stroke-width 250ms linear, stroke-opacity 250ms linear; - -moz-transition: fill-opacity 250ms linear, stroke-width 250ms linear, stroke-opacity 250ms linear; - -webkit-transition: fill-opacity 250ms linear, stroke-width 250ms linear, stroke-opacity 250ms linear; - -} - -.nvd3.nv-pie .nv-slice text { - stroke: #000; - stroke-width: 0; -} - -.nvd3.nv-pie path { - stroke: #fff; - stroke-width: 1px; - stroke-opacity: 1; -} - -.nvd3.nv-pie .hover path { - fill-opacity: .7; -/* - stroke-width: 6px; - stroke-opacity: 1; -*/ -} - -.nvd3.nv-pie .nv-label rect { - fill-opacity: 0; - stroke-opacity: 0; -} - -/********** -* Lines -*/ - -.nvd3 .nv-groups path.nv-line { - fill: none; - stroke-width: 2.5px; - /* - stroke-linecap: round; - shape-rendering: geometricPrecision; - - transition: stroke-width 250ms linear; - -moz-transition: stroke-width 250ms linear; - -webkit-transition: stroke-width 250ms linear; - - transition-delay: 250ms - -moz-transition-delay: 250ms; - -webkit-transition-delay: 250ms; - */ -} - -.nvd3 .nv-groups path.nv-area { - stroke: none; - /* - stroke-linecap: round; - shape-rendering: geometricPrecision; - - stroke-width: 2.5px; - transition: stroke-width 250ms linear; - -moz-transition: stroke-width 250ms linear; - -webkit-transition: stroke-width 250ms linear; - - transition-delay: 250ms - -moz-transition-delay: 250ms; - -webkit-transition-delay: 250ms; - */ -} - -.nvd3 .nv-line.hover path { - stroke-width: 6px; -} - -/* -.nvd3.scatter .groups .point { - fill-opacity: 0.1; - stroke-opacity: 0.1; -} - */ - -.nvd3.nv-line .nvd3.nv-scatter .nv-groups .nv-point { - fill-opacity: 0; - stroke-opacity: 0; -} - -.nvd3.nv-scatter.nv-single-point .nv-groups .nv-point { - fill-opacity: .5 !important; - stroke-opacity: .5 !important; -} - - -.nvd3 .nv-groups .nv-point { - transition: stroke-width 250ms linear, stroke-opacity 250ms linear; - -moz-transition: stroke-width 250ms linear, stroke-opacity 250ms linear; - -webkit-transition: stroke-width 250ms linear, stroke-opacity 250ms linear; -} - -.nvd3.nv-scatter .nv-groups .nv-point.hover, -.nvd3 .nv-groups .nv-point.hover { - stroke-width: 20px; - fill-opacity: .5 !important; - stroke-opacity: .5 !important; -} - - -.nvd3 .nv-point-paths path { - stroke: #aaa; - stroke-opacity: 0; - fill: #eee; - fill-opacity: 0; -} - - - -.nvd3 .nv-indexLine { - cursor: ew-resize; -} - - -/********** -* Distribution -*/ - -.nvd3 .nv-distribution { - pointer-events: none; -} - - - -/********** -* Scatter -*/ - -/* **Attempting to remove this for useVoronoi(false), need to see if it's required anywhere -.nvd3 .nv-groups .nv-point { - pointer-events: none; -} -*/ - -.nvd3 .nv-groups .nv-point.hover { - stroke-width: 20px; - stroke-opacity: .5; -} - -.nvd3 .nv-scatter .nv-point.hover { - fill-opacity: 1; -} - -/* -.nv-group.hover .nv-point { - fill-opacity: 1; -} -*/ - - -/********** -* Stacked Area -*/ - -.nvd3.nv-stackedarea path.nv-area { - fill-opacity: .7; - /* - stroke-opacity: .65; - fill-opacity: 1; - */ - stroke-opacity: 0; - - transition: fill-opacity 250ms linear, stroke-opacity 250ms linear; - -moz-transition: fill-opacity 250ms linear, stroke-opacity 250ms linear; - -webkit-transition: fill-opacity 250ms linear, stroke-opacity 250ms linear; - - /* - transition-delay: 500ms; - -moz-transition-delay: 500ms; - -webkit-transition-delay: 500ms; - */ - -} - -.nvd3.nv-stackedarea path.nv-area.hover { - fill-opacity: .9; - /* - stroke-opacity: .85; - */ -} -/* -.d3stackedarea .groups path { - stroke-opacity: 0; -} - */ - - - -.nvd3.nv-stackedarea .nv-groups .nv-point { - stroke-opacity: 0; - fill-opacity: 0; -} - -.nvd3.nv-stackedarea .nv-groups .nv-point.hover { - stroke-width: 20px; - stroke-opacity: .75; - fill-opacity: 1; -} - - - -/********** -* Line Plus Bar -*/ - -.nvd3.nv-linePlusBar .nv-bar rect { - fill-opacity: .75; -} - -.nvd3.nv-linePlusBar .nv-bar rect:hover { - fill-opacity: 1; -} - - -/********** -* Bullet -*/ - -.nvd3.nv-bullet { font: 10px sans-serif; } -.nvd3.nv-bullet .nv-measure { fill-opacity: .8; } -.nvd3.nv-bullet .nv-measure:hover { fill-opacity: 1; } -.nvd3.nv-bullet .nv-marker { stroke: #000; stroke-width: 2px; } -.nvd3.nv-bullet .nv-markerTriangle { stroke: #000; fill: #fff; stroke-width: 1.5px; } -.nvd3.nv-bullet .nv-tick line { stroke: #666; stroke-width: .5px; } -.nvd3.nv-bullet .nv-range.nv-s0 { fill: #eee; } -.nvd3.nv-bullet .nv-range.nv-s1 { fill: #ddd; } -.nvd3.nv-bullet .nv-range.nv-s2 { fill: #ccc; } -.nvd3.nv-bullet .nv-title { font-size: 14px; font-weight: bold; } -.nvd3.nv-bullet .nv-subtitle { fill: #999; } - - -.nvd3.nv-bullet .nv-range { - fill: #999; - fill-opacity: .4; -} -.nvd3.nv-bullet .nv-range:hover { - fill-opacity: .7; -} - - - -/********** -* Sparkline -*/ - -.nvd3.nv-sparkline path { - fill: none; -} - -.nvd3.nv-sparklineplus g.nv-hoverValue { - pointer-events: none; -} - -.nvd3.nv-sparklineplus .nv-hoverValue line { - stroke: #333; - stroke-width: 1.5px; - } - -.nvd3.nv-sparklineplus, -.nvd3.nv-sparklineplus g { - pointer-events: all; -} - -.nvd3 .nv-hoverArea { - fill-opacity: 0; - stroke-opacity: 0; -} - -.nvd3.nv-sparklineplus .nv-xValue, -.nvd3.nv-sparklineplus .nv-yValue { - /* - stroke: #666; - */ - stroke-width: 0; - font-size: .9em; - font-weight: normal; -} - -.nvd3.nv-sparklineplus .nv-yValue { - stroke: #f66; -} - -.nvd3.nv-sparklineplus .nv-maxValue { - stroke: #2ca02c; - fill: #2ca02c; -} - -.nvd3.nv-sparklineplus .nv-minValue { - stroke: #d62728; - fill: #d62728; -} - -.nvd3.nv-sparklineplus .nv-currentValue { - /* - stroke: #444; - fill: #000; - */ - font-weight: bold; - font-size: 1.1em; -} - -/********** -* historical stock -*/ - -.nvd3.nv-ohlcBar .nv-ticks .nv-tick { - stroke-width: 2px; -} - -.nvd3.nv-ohlcBar .nv-ticks .nv-tick.hover { - stroke-width: 4px; -} - -.nvd3.nv-ohlcBar .nv-ticks .nv-tick.positive { - stroke: #2ca02c; -} - -.nvd3.nv-ohlcBar .nv-ticks .nv-tick.negative { - stroke: #d62728; -} - -.nvd3.nv-historicalStockChart .nv-axis .nv-axislabel { - font-weight: bold; -} - -.nvd3.nv-historicalStockChart .nv-dragTarget { - fill-opacity: 0; - stroke: none; - cursor: move; -} - -.nvd3 .nv-brush .extent { - /* - cursor: ew-resize !important; - */ - fill-opacity: 0 !important; -} - -.nvd3 .nv-brushBackground rect { - stroke: #000; - stroke-width: .4; - fill: #fff; - fill-opacity: .7; -} - - - -/********** -* Indented Tree -*/ - - -/** - * TODO: the following 3 selectors are based on classes used in the example. I should either make them standard and leave them here, or move to a CSS file not included in the library - */ -.nvd3.nv-indentedtree .name { - margin-left: 5px; -} - -.nvd3.nv-indentedtree .clickable { - color: #08C; - cursor: pointer; -} - -.nvd3.nv-indentedtree span.clickable:hover { - color: #005580; - text-decoration: underline; -} - - -.nvd3.nv-indentedtree .nv-childrenCount { - display: inline-block; - margin-left: 5px; -} - -.nvd3.nv-indentedtree .nv-treeicon { - cursor: pointer; - /* - cursor: n-resize; - */ -} - -.nvd3.nv-indentedtree .nv-treeicon.nv-folded { - cursor: pointer; - /* - cursor: s-resize; - */ -} - - diff --git a/www/assets/ico/apple-touch-icon-114-precomposed.png b/www/assets/ico/apple-touch-icon-114-precomposed.png deleted file mode 100644 index f1c93e6f..00000000 Binary files a/www/assets/ico/apple-touch-icon-114-precomposed.png and /dev/null differ diff --git a/www/assets/ico/apple-touch-icon-144-precomposed.png b/www/assets/ico/apple-touch-icon-144-precomposed.png deleted file mode 100644 index 3c80087b..00000000 Binary files a/www/assets/ico/apple-touch-icon-144-precomposed.png and /dev/null differ diff --git a/www/assets/ico/apple-touch-icon-57-precomposed.png b/www/assets/ico/apple-touch-icon-57-precomposed.png deleted file mode 100644 index 34b8dd6b..00000000 Binary files a/www/assets/ico/apple-touch-icon-57-precomposed.png and /dev/null differ diff --git a/www/assets/ico/apple-touch-icon-72-precomposed.png b/www/assets/ico/apple-touch-icon-72-precomposed.png deleted file mode 100644 index f77bd6c9..00000000 Binary files a/www/assets/ico/apple-touch-icon-72-precomposed.png and /dev/null differ diff --git a/www/assets/ico/favicon.ico b/www/assets/ico/favicon.ico deleted file mode 100644 index e1c310e4..00000000 Binary files a/www/assets/ico/favicon.ico and /dev/null differ diff --git a/www/assets/img/glyphicons-halflings-white.png b/www/assets/img/glyphicons-halflings-white.png deleted file mode 100644 index 3bf6484a..00000000 Binary files a/www/assets/img/glyphicons-halflings-white.png and /dev/null differ diff --git a/www/assets/img/glyphicons-halflings.png b/www/assets/img/glyphicons-halflings.png deleted file mode 100644 index 79bc568c..00000000 Binary files a/www/assets/img/glyphicons-halflings.png and /dev/null differ diff --git a/www/assets/js/application.js b/www/assets/js/application.js deleted file mode 100755 index 6463b902..00000000 --- a/www/assets/js/application.js +++ /dev/null @@ -1,184 +0,0 @@ -// NOTICE!! DO NOT USE ANY OF THIS JAVASCRIPT -// IT'S ALL JUST JUNK FOR OUR DOCS! -// ++++++++++++++++++++++++++++++++++++++++++ - -!function ($) { - - $(function(){ - - // Disable certain links in docs - $('section [href^=#]').click(function (e) { - e.preventDefault() - }) - - // make code pretty - window.prettyPrint && prettyPrint() - - // add-ons - $('.add-on :checkbox').on('click', function () { - var $this = $(this) - , method = $this.attr('checked') ? 'addClass' : 'removeClass' - $(this).parents('.add-on')[method]('active') - }) - - // position static twipsies for components page - if ($(".twipsies a").length) { - $(window).on('load resize', function () { - $(".twipsies a").each(function () { - $(this) - .tooltip({ - placement: $(this).attr('title') - , trigger: 'manual' - }) - .tooltip('show') - }) - }) - } - - // add tipsies to grid for scaffolding - if ($('#grid-system').length) { - $('#grid-system').tooltip({ - selector: '.show-grid > div' - , title: function () { return $(this).width() + 'px' } - }) - } - - // fix sub nav on scroll - var $win = $(window) - , $nav = $('.subnav') - , navTop = $('.subnav').length && $('.subnav').offset().top - 40 - , isFixed = 0 - - processScroll() - - // hack sad times - holdover until rewrite for 2.1 - $nav.on('click', function () { - if (!isFixed) setTimeout(function () { $win.scrollTop($win.scrollTop() - 47) }, 10) - }) - - $win.on('scroll', processScroll) - - function processScroll() { - var i, scrollTop = $win.scrollTop() - if (scrollTop >= navTop && !isFixed) { - isFixed = 1 - $nav.addClass('subnav-fixed') - } else if (scrollTop <= navTop && isFixed) { - isFixed = 0 - $nav.removeClass('subnav-fixed') - } - } - - // tooltip demo - $('.tooltip-demo.well').tooltip({ - selector: "a[rel=tooltip]" - }) - - $('.tooltip-test').tooltip() - $('.popover-test').popover() - - // popover demo - $("a[rel=popover]") - .popover() - .click(function(e) { - e.preventDefault() - }) - - // button state demo - $('#fat-btn') - .click(function () { - var btn = $(this) - btn.button('loading') - setTimeout(function () { - btn.button('reset') - }, 3000) - }) - - // carousel demo - $('#myCarousel').carousel() - - // javascript build logic - var inputsComponent = $("#components.download input") - , inputsPlugin = $("#plugins.download input") - , inputsVariables = $("#variables.download input") - - // toggle all plugin checkboxes - $('#components.download .toggle-all').on('click', function (e) { - e.preventDefault() - inputsComponent.attr('checked', !inputsComponent.is(':checked')) - }) - - $('#plugins.download .toggle-all').on('click', function (e) { - e.preventDefault() - inputsPlugin.attr('checked', !inputsPlugin.is(':checked')) - }) - - $('#variables.download .toggle-all').on('click', function (e) { - e.preventDefault() - inputsVariables.val('') - }) - - // request built javascript - $('.download-btn').on('click', function () { - - var css = $("#components.download input:checked") - .map(function () { return this.value }) - .toArray() - , js = $("#plugins.download input:checked") - .map(function () { return this.value }) - .toArray() - , vars = {} - , img = ['glyphicons-halflings.png', 'glyphicons-halflings-white.png'] - - $("#variables.download input") - .each(function () { - $(this).val() && (vars[ $(this).prev().text() ] = $(this).val()) - }) - - $.ajax({ - type: 'POST' - , url: /\?dev/.test(window.location) ? 'http://localhost:3000' : 'http://bootstrap.herokuapp.com' - , dataType: 'jsonpi' - , params: { - js: js - , css: css - , vars: vars - , img: img - } - }) - }) - }) - -// Modified from the original jsonpi https://github.com/benvinegar/jquery-jsonpi -$.ajaxTransport('jsonpi', function(opts, originalOptions, jqXHR) { - var url = opts.url; - - return { - send: function(_, completeCallback) { - var name = 'jQuery_iframe_' + jQuery.now() - , iframe, form - - iframe = $('