├── .java_tmp └── .gitignore ├── project ├── build.properties └── plugins.sbt ├── sims ├── verilator │ ├── .gitignore │ ├── verilator.mk │ └── Makefile └── tools.mk ├── generators └── chipyard │ └── src │ ├── main │ ├── scala │ │ ├── Generator.scala │ │ ├── unittest │ │ │ ├── TestHarness.scala │ │ │ └── UnitTestSuite.scala │ │ ├── stage │ │ │ ├── ChipyardCli.scala │ │ │ ├── ChipyardAnnotations.scala │ │ │ ├── ChipyardStage.scala │ │ │ └── phases │ │ │ │ ├── GenerateTestSuiteMakefrags.scala │ │ │ │ └── AddDefaultTests.scala │ │ ├── clocking │ │ │ ├── ClockDividerN.scala │ │ │ ├── ClockGroupNamePrefixer.scala │ │ │ └── DividerOnlyClockGenerator.scala │ │ ├── config │ │ │ ├── BoomConfigs.scala │ │ │ ├── AbstractConfig.scala │ │ │ └── RocketConfigs.scala │ │ ├── DigitalTop.scala │ │ ├── ChipTop.scala │ │ ├── CustomBusTopologies.scala │ │ ├── Subsystem.scala │ │ ├── System.scala │ │ ├── TestSuites.scala │ │ ├── TestHarness.scala │ │ ├── Clocks.scala │ │ ├── ConfigFragments.scala │ │ ├── HarnessBinders.scala │ │ └── IOBinders.scala │ └── resources │ │ ├── vsrc │ │ ├── GCDMMIOBlackBox.v │ │ └── ClockDividerN.sv │ │ └── csrc │ │ └── emulator.cc │ └── test │ └── scala │ └── clocking │ └── SimplePllConfigurationSpec.scala ├── CHANGELOG.md ├── .gitignore ├── docker ├── README.md └── Dockerfile ├── .gitmodules ├── scripts ├── setup-prerequisites.sh └── blackbox_resolver.py ├── LICENSE.Chipyard ├── README.md ├── LICENSE.SiFive └── LICENSE /.java_tmp/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /project/build.properties: -------------------------------------------------------------------------------- 1 | sbt.version=1.4.9 2 | -------------------------------------------------------------------------------- /sims/verilator/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | !Makefile 4 | !verilator.mk 5 | -------------------------------------------------------------------------------- /generators/chipyard/src/main/scala/Generator.scala: -------------------------------------------------------------------------------- 1 | package chipyard 2 | 3 | import firrtl.options.{StageMain} 4 | import chipyard.stage.ChipyardStage 5 | 6 | object Generator extends StageMain(new ChipyardStage) 7 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | All notable changes to the Bossa will be documented in this file. 4 | 5 | ## 0.0.2 - 2021-12-16 6 | 7 | ### Fixed 8 | 9 | * Version problem of `verilator`. 10 | * Problems about Frenda. 11 | 12 | ## 0.0.1 - 2021-11-29 13 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # from chipyard 2 | bootrom/* 3 | /Makefrag.pkgs 4 | target 5 | *.jar 6 | *.stamp 7 | *.vcd 8 | *.swp 9 | *.swo 10 | *.log 11 | *# 12 | *~ 13 | .idea 14 | tags 15 | .bsp/ 16 | 17 | # macOS 18 | *.DS_Store 19 | 20 | # debugging 21 | debug 22 | 23 | # toolchain installations 24 | toolchain-install 25 | -------------------------------------------------------------------------------- /generators/chipyard/src/main/scala/unittest/TestHarness.scala: -------------------------------------------------------------------------------- 1 | package chipyard.unittest 2 | 3 | import chisel3._ 4 | import freechips.rocketchip.config.Parameters 5 | 6 | class TestHarness(implicit val p: Parameters) extends Module { 7 | val io = IO(new Bundle { val success = Output(Bool()) }) 8 | io.success := Module(new UnitTestSuite).io.finished 9 | } 10 | -------------------------------------------------------------------------------- /generators/chipyard/src/main/scala/unittest/UnitTestSuite.scala: -------------------------------------------------------------------------------- 1 | package chipyard.unittest 2 | 3 | import freechips.rocketchip.config.Parameters 4 | import freechips.rocketchip.util.{ElaborationArtefacts, PlusArgArtefacts} 5 | 6 | class UnitTestSuite(implicit p: Parameters) extends freechips.rocketchip.unittest.UnitTestSuite { 7 | ElaborationArtefacts.add("plusArgs", PlusArgArtefacts.serialize_cHeader) 8 | } 9 | -------------------------------------------------------------------------------- /generators/chipyard/src/main/scala/stage/ChipyardCli.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE for license details. 2 | // Based on Rocket Chip's stage implementation 3 | 4 | package chipyard.stage 5 | 6 | import firrtl.options.Shell 7 | 8 | trait ChipyardCli { this: Shell => 9 | 10 | parser.note("Chipyard Generator Options") 11 | Seq( 12 | UnderscoreDelimitedConfigsAnnotation 13 | ) 14 | .foreach(_.addOptions(parser)) 15 | } 16 | -------------------------------------------------------------------------------- /docker/README.md: -------------------------------------------------------------------------------- 1 | # Dockerfile of Bossa 2 | 3 | You can use the `Dockerfile` in the current directory to build a Docker image of Bossa: 4 | 5 | ```sh 6 | # build a Docker image 7 | docker build -t bossa-image . 8 | # build a Docker image from a specific Bossa commit 9 | docker build -t bossa-image --build-arg BOSSA_HASH= . 10 | # setup GitHub proxy when building image 11 | docker build -t bossa-image --build-arg GITHUB_PROXY= . 12 | ``` 13 | -------------------------------------------------------------------------------- /sims/tools.mk: -------------------------------------------------------------------------------- 1 | ################################################################################ 2 | # Toolchain settings 3 | ################################################################################ 4 | 5 | # Directories 6 | BOSSA_DIR := $(abspath $(dir $(lastword $(MAKEFILE_LIST)))/..) 7 | JAVA_TMP_DIR := $(BOSSA_DIR)/.java_tmp 8 | 9 | # SBT 10 | SBT_JAR := $(BOSSA_DIR)/generators/rocket-chip/sbt-launch.jar 11 | SBT := java -Xmx8G -Xss8M -XX:MaxPermSize=256M -Djava.io.tmpdir=$(JAVA_TMP_DIR) -jar $(SBT_JAR) 12 | SBT_BOSSA := cd $(BOSSA_DIR) && $(SBT) 13 | 14 | # Blackbox resolver 15 | BLACKBOX_RESOLVER := $(BOSSA_DIR)/scripts/blackbox_resolver.py -r $(BOSSA_DIR) 16 | -------------------------------------------------------------------------------- /generators/chipyard/src/main/scala/clocking/ClockDividerN.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE for license details. 2 | 3 | package chipyard.clocking 4 | 5 | import chisel3._ 6 | import chisel3.util._ 7 | 8 | class ClockDividerN(div: Int) extends BlackBox(Map("DIV" -> div)) with HasBlackBoxResource { 9 | require(div > 0); 10 | val io = IO(new Bundle { 11 | val clk_out = Output(Clock()) 12 | val clk_in = Input(Clock()) 13 | }) 14 | addResource("/vsrc/ClockDividerN.sv") 15 | } 16 | 17 | object ClockDivideByN { 18 | def apply(clockIn: Clock, div: Int): Clock = { 19 | val clockDivider = Module(new ClockDividerN(div)) 20 | clockDivider.io.clk_in := clockIn 21 | clockDivider.io.clk_out 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /docker/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu:20.04 2 | 3 | ARG GITHUB_PROXY 4 | ARG BOSSA_HASH 5 | 6 | # Install Git 7 | RUN apt-get update && \ 8 | DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \ 9 | git ca-certificates 10 | 11 | # Clone Bossa 12 | WORKDIR /root 13 | RUN if [ -n "$GITHUB_PROXY" ]; then \ 14 | git config --global url."$GITHUB_PROXY".insteadOf "https://github.com/" && \ 15 | git config --global protocol.https.allow always; \ 16 | fi 17 | RUN git clone https://github.com/MaxXSoft/Bossa.git bossa && \ 18 | cd bossa && \ 19 | git checkout $BOSSA_HASH 20 | 21 | # Setup prerequisites 22 | WORKDIR /root/bossa 23 | RUN ./scripts/setup-prerequisites.sh 24 | 25 | # Initialize submodules 26 | RUN git submodule update --init --recursive --depth=1 27 | 28 | CMD ["/bin/bash"] 29 | -------------------------------------------------------------------------------- /project/plugins.sbt: -------------------------------------------------------------------------------- 1 | addSbtPlugin("net.virtual-void" % "sbt-dependency-graph" % "0.9.2") 2 | addSbtPlugin("com.typesafe.sbt" % "sbt-ghpages" % "0.6.2") 3 | addSbtPlugin("com.typesafe.sbt" % "sbt-site" % "1.3.1") 4 | addSbtPlugin("com.eed3si9n" % "sbt-buildinfo" % "0.10.0") 5 | addSbtPlugin("org.xerial.sbt" % "sbt-pack" % "0.9.3") 6 | addSbtPlugin("com.eed3si9n" % "sbt-unidoc" % "0.4.1") 7 | addSbtPlugin("org.scoverage" % "sbt-scoverage" % "1.5.1") 8 | addSbtPlugin("org.scalastyle" %% "scalastyle-sbt-plugin" % "1.0.0") 9 | addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.15.0") 10 | addSbtPlugin("com.simplytyped" % "sbt-antlr4" % "0.8.2") 11 | addSbtPlugin("com.github.gseitz" % "sbt-protobuf" % "0.6.3") 12 | addSbtPlugin("ch.epfl.scala" % "sbt-scalafix" % "0.9.21") 13 | addSbtPlugin("com.typesafe" % "sbt-mima-plugin" % "0.6.1") 14 | addSbtPlugin("com.eed3si9n" % "sbt-sriracha" % "0.1.0") 15 | addSbtPlugin("org.scalameta" % "sbt-mdoc" % "2.2.5" ) 16 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "generators/boom"] 2 | path = generators/boom 3 | url = https://github.com/riscv-boom/riscv-boom.git 4 | [submodule "generators/rocket-chip"] 5 | path = generators/rocket-chip 6 | url = https://github.com/chipsalliance/rocket-chip.git 7 | [submodule "generators/sifive-blocks"] 8 | path = generators/sifive-blocks 9 | url = https://github.com/sifive/sifive-blocks.git 10 | [submodule "generators/testchipip"] 11 | path = generators/testchipip 12 | url = https://github.com/ucb-bar/testchipip.git 13 | [submodule "tools/barstools"] 14 | path = tools/barstools 15 | url = https://github.com/ucb-bar/barstools.git 16 | [submodule "tools/DRAMSim2"] 17 | path = tools/DRAMSim2 18 | url = https://github.com/firesim/DRAMSim2.git 19 | [submodule "tools/frenda"] 20 | path = tools/frenda 21 | url = https://github.com/MaxXSoft/Frenda.git 22 | [submodule "toolchains/riscv-isa-sim"] 23 | path = toolchains/riscv-isa-sim 24 | url = https://github.com/riscv-software-src/riscv-isa-sim.git 25 | -------------------------------------------------------------------------------- /generators/chipyard/src/main/scala/config/BoomConfigs.scala: -------------------------------------------------------------------------------- 1 | package chipyard 2 | 3 | import freechips.rocketchip.config.{Config} 4 | 5 | // --------------------- 6 | // BOOM Configs 7 | // --------------------- 8 | 9 | class SmallBoomConfig extends Config( 10 | new boom.common.WithNSmallBooms(1) ++ // small boom config 11 | new chipyard.config.AbstractConfig) 12 | 13 | class MediumBoomConfig extends Config( 14 | new boom.common.WithNMediumBooms(1) ++ // medium boom config 15 | new chipyard.config.AbstractConfig) 16 | 17 | class LargeBoomConfig extends Config( 18 | new boom.common.WithNLargeBooms(1) ++ // large boom config 19 | new chipyard.config.AbstractConfig) 20 | 21 | class MegaBoomConfig extends Config( 22 | new boom.common.WithNMegaBooms(1) ++ // mega boom config 23 | new chipyard.config.AbstractConfig) 24 | 25 | class DualSmallBoomConfig extends Config( 26 | new boom.common.WithNSmallBooms(2) ++ // 2 boom cores 27 | new chipyard.config.AbstractConfig) 28 | 29 | -------------------------------------------------------------------------------- /generators/chipyard/src/main/scala/stage/ChipyardAnnotations.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE for license details. 2 | // Based on Rocket Chip's stage implementation 3 | 4 | package chipyard.stage 5 | 6 | import freechips.rocketchip.stage.ConfigsAnnotation 7 | import firrtl.options.{HasShellOptions, ShellOption} 8 | 9 | /** This hijacks the existing ConfigAnnotation to accept the legacy _-delimited format */ 10 | private[stage] object UnderscoreDelimitedConfigsAnnotation extends HasShellOptions { 11 | override val options = Seq( 12 | new ShellOption[String]( 13 | longOption = "legacy-configs", 14 | toAnnotationSeq = a => { 15 | val split = a.split(':') 16 | assert(split.length == 2) 17 | val packageName = split.head 18 | val configs = split.last.split("_") 19 | Seq(new ConfigsAnnotation(configs map { config => if (config contains ".") s"${config}" else s"${packageName}.${config}" } )) 20 | }, 21 | helpText = "A string of underscore-delimited configs (configs have decreasing precendence from left to right).", 22 | shortOption = Some("LC") 23 | ) 24 | ) 25 | } 26 | 27 | -------------------------------------------------------------------------------- /generators/chipyard/src/test/scala/clocking/SimplePllConfigurationSpec.scala: -------------------------------------------------------------------------------- 1 | //See LICENSE for license details. 2 | package chipyard.clocking 3 | 4 | import freechips.rocketchip.prci._ 5 | 6 | class SimplePllConfigurationSpec extends org.scalatest.flatspec.AnyFlatSpec { 7 | 8 | def genConf(freqMHz: Iterable[Double]): SimplePllConfiguration = new SimplePllConfiguration( 9 | "testPLL", 10 | freqMHz.map({ f => ClockSinkParameters( 11 | name = Some(s"desiredFreq_$f"), 12 | take = Some(ClockParameters(f))) }).toSeq, 13 | maximumAllowableFreqMHz = 16000.0) 14 | 15 | def trySuccessfulConf(requestedFreqs: Seq[Double], expected: Double): Unit = { 16 | val freqStr = requestedFreqs.mkString(", ") 17 | it should s"select a reference of ${expected} MHz for ${freqStr} MHz" in { 18 | val conf = genConf(requestedFreqs) 19 | conf.emitSummaries 20 | assert(expected == conf.referenceFreqMHz) 21 | } 22 | } 23 | 24 | trySuccessfulConf(Seq(3200.0, 1600.0, 1000.0, 100.0), 16000.0) 25 | trySuccessfulConf(Seq(3200.0, 1600.0), 3200.0) 26 | trySuccessfulConf(Seq(3200.0, 1066.7), 3200.0) 27 | trySuccessfulConf(Seq(100, 50, 6.67), 100) 28 | trySuccessfulConf(Seq(1, 2, 3, 5, 7, 11, 13).map(_ * 10.0), 1560.0) 29 | } 30 | -------------------------------------------------------------------------------- /generators/chipyard/src/main/resources/vsrc/GCDMMIOBlackBox.v: -------------------------------------------------------------------------------- 1 | // DOC include start: GCD portlist 2 | module GCDMMIOBlackBox 3 | #(parameter WIDTH) 4 | ( 5 | input clock, 6 | input reset, 7 | output input_ready, 8 | input input_valid, 9 | input [WIDTH-1:0] x, 10 | input [WIDTH-1:0] y, 11 | input output_ready, 12 | output output_valid, 13 | output reg [WIDTH-1:0] gcd, 14 | output busy 15 | ); 16 | // DOC include end: GCD portlist 17 | 18 | localparam S_IDLE = 2'b00, S_RUN = 2'b01, S_DONE = 2'b10; 19 | 20 | reg [1:0] state; 21 | reg [WIDTH-1:0] tmp; 22 | 23 | assign input_ready = state == S_IDLE; 24 | assign output_valid = state == S_DONE; 25 | assign busy = state != S_IDLE; 26 | 27 | always @(posedge clock) begin 28 | if (reset) 29 | state <= S_IDLE; 30 | else if (state == S_IDLE && input_valid) 31 | state <= S_RUN; 32 | else if (state == S_RUN && tmp == 0) 33 | state <= S_DONE; 34 | else if (state == S_DONE && output_ready) 35 | state <= S_IDLE; 36 | end 37 | 38 | always @(posedge clock) begin 39 | if (state == S_IDLE && input_valid) begin 40 | gcd <= x; 41 | tmp <= y; 42 | end else if (state == S_RUN) begin 43 | if (gcd > tmp) 44 | gcd <= gcd - tmp; 45 | else 46 | tmp <= tmp - gcd; 47 | end 48 | end 49 | 50 | endmodule // GCDMMIOBlackBox 51 | -------------------------------------------------------------------------------- /scripts/setup-prerequisites.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | 4 | # Tests if the command exists. 5 | updated=0 6 | function test_cmd() { 7 | command -v $1 &> /dev/null 8 | local ret=$? 9 | if [ $ret -ne 0 ] && [ $updated -eq 0 ]; then 10 | apt-get update 11 | updated=1 12 | fi 13 | return $ret 14 | } 15 | 16 | # Prints messages to `stderr`. 17 | function echoe() { 18 | echo -e "\033[31m\033[1m$1\033[0m" 1>&2 19 | } 20 | 21 | # Installs the specific package. 22 | function install_pkg() { 23 | DEBIAN_FRONTEND="noninteractive" apt-get install -y $@ 24 | } 25 | 26 | # Setup JDK 27 | if ! test_cmd javac; then 28 | echoe "Setting up JDK..." 29 | # TODO: tzdata stucked 30 | install_pkg default-jdk 31 | fi 32 | 33 | # Setup build-essential 34 | if ! test_cmd g++ || ! test_cmd make; then 35 | echoe "Setting up build-essential..." 36 | install_pkg build-essential 37 | fi 38 | 39 | # Setup Python 3 40 | if ! test_cmd python3; then 41 | echoe "Setting up Python 3..." 42 | install_pkg python3 43 | fi 44 | 45 | # Setup device tree compiler 46 | if ! test_cmd dtc; then 47 | echoe "Setting up device tree compiler..." 48 | install_pkg device-tree-compiler 49 | fi 50 | 51 | # Setup Git 52 | if ! test_cmd git; then 53 | echoe "Setting up Git..." 54 | install_pkg git 55 | fi 56 | 57 | # Setup Verilator 58 | if ! test_cmd verilator; then 59 | echoe "Setting up Verilator..." 60 | # Build from source 61 | install_pkg autoconf flex bison zlib1g-dev 62 | git clone --single-branch --depth 1 http://git.veripool.org/git/verilator 63 | cd verilator && autoconf && ./configure && make -j`nproc` && make install && rm -rf ../verilator 64 | fi 65 | -------------------------------------------------------------------------------- /LICENSE.Chipyard: -------------------------------------------------------------------------------- 1 | BSD 3-Clause License 2 | 3 | Copyright (c) 2017-2020, The Regents of the University of California (Regents) 4 | All Rights Reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | 1. Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | 2. Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | 3. Neither the name of the copyright holder nor the names of its 17 | contributors may be used to endorse or promote products derived from 18 | this software without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | 31 | -------------------------------------------------------------------------------- /generators/chipyard/src/main/resources/vsrc/ClockDividerN.sv: -------------------------------------------------------------------------------- 1 | // See LICENSE for license details. 2 | 3 | /** 4 | * An unsynthesizable divide-by-N clock divider. 5 | * Duty cycle is 100 * (ceil(DIV / 2)) / DIV. 6 | */ 7 | 8 | module ClockDividerN #(parameter DIV = 1)(output logic clk_out = 1'b0, input clk_in); 9 | 10 | localparam CWIDTH = $clog2(DIV); 11 | localparam LOW_CYCLES = DIV / 2; 12 | localparam HIGH_TRANSITION = LOW_CYCLES - 1; 13 | localparam LOW_TRANSITION = DIV - 1; 14 | 15 | generate 16 | if (DIV == 1) begin 17 | // This needs to be procedural because of the assignment on declaration 18 | always @(clk_in) begin 19 | clk_out = clk_in; 20 | end 21 | end else begin 22 | reg [CWIDTH - 1: 0] count = HIGH_TRANSITION[CWIDTH-1:0]; 23 | // The blocking assignment to clock out is used to conform what was done 24 | // in RC's clock dividers. 25 | // It should have the effect of preventing registers in the divided clock 26 | // domain latching register updates launched by the fast clock-domain edge 27 | // that occurs at the same simulated time (as the divided clock edge). 28 | always @(posedge clk_in) begin 29 | if (count == LOW_TRANSITION[CWIDTH-1:0]) begin 30 | clk_out = 1'b0; 31 | count <= '0; 32 | end 33 | else begin 34 | if (count == HIGH_TRANSITION[CWIDTH-1:0]) begin 35 | clk_out = 1'b1; 36 | end 37 | count <= count + 1'b1; 38 | end 39 | end 40 | end 41 | endgenerate 42 | endmodule // ClockDividerN 43 | -------------------------------------------------------------------------------- /generators/chipyard/src/main/scala/stage/ChipyardStage.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE for license details. 2 | // Based on Rocket Chip's stage implementation 3 | 4 | package chipyard.stage 5 | 6 | import chisel3.stage.{ChiselCli, ChiselStage} 7 | import firrtl.options.PhaseManager.PhaseDependency 8 | import firrtl.options.{Phase, PreservesAll, Shell} 9 | import firrtl.stage.FirrtlCli 10 | import freechips.rocketchip.stage.RocketChipCli 11 | import freechips.rocketchip.system.RocketChipStage 12 | 13 | import firrtl.options.{Phase, PhaseManager, PreservesAll, Shell, Stage, StageError, StageMain, Dependency} 14 | import firrtl.options.phases.DeletedWrapper 15 | 16 | class ChipyardStage extends ChiselStage with PreservesAll[Phase] { 17 | override val shell = new Shell("chipyard") with ChipyardCli with RocketChipCli with ChiselCli with FirrtlCli 18 | override val targets: Seq[PhaseDependency] = Seq( 19 | Dependency[freechips.rocketchip.stage.phases.Checks], 20 | Dependency[freechips.rocketchip.stage.phases.TransformAnnotations], 21 | Dependency[freechips.rocketchip.stage.phases.PreElaboration], 22 | Dependency[chisel3.stage.phases.Checks], 23 | Dependency[chisel3.stage.phases.Elaborate], 24 | Dependency[freechips.rocketchip.stage.phases.GenerateROMs], 25 | Dependency[chisel3.stage.phases.AddImplicitOutputFile], 26 | Dependency[chisel3.stage.phases.AddImplicitOutputAnnotationFile], 27 | Dependency[chisel3.stage.phases.MaybeAspectPhase], 28 | Dependency[chisel3.stage.phases.Emitter], 29 | Dependency[chisel3.stage.phases.Convert], 30 | Dependency[freechips.rocketchip.stage.phases.GenerateFirrtlAnnos], 31 | Dependency[freechips.rocketchip.stage.phases.AddDefaultTests], 32 | Dependency[chipyard.stage.phases.AddDefaultTests], 33 | Dependency[chipyard.stage.phases.GenerateTestSuiteMakefrags], 34 | Dependency[freechips.rocketchip.stage.phases.GenerateArtefacts], 35 | ) 36 | } 37 | -------------------------------------------------------------------------------- /generators/chipyard/src/main/scala/stage/phases/GenerateTestSuiteMakefrags.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE for license details. 2 | // Based on Rocket Chip's stage implementation 3 | 4 | package chipyard.stage.phases 5 | 6 | import scala.collection.mutable 7 | 8 | import firrtl.AnnotationSeq 9 | import firrtl.annotations.{Annotation, NoTargetAnnotation} 10 | import firrtl.options.{Phase, PreservesAll, StageOptions, Unserializable, Dependency} 11 | import firrtl.options.Viewer.view 12 | import freechips.rocketchip.stage.RocketChipOptions 13 | import freechips.rocketchip.stage.phases.{RocketTestSuiteAnnotation} 14 | import freechips.rocketchip.system.TestGeneration 15 | import freechips.rocketchip.util.HasRocketChipStageUtils 16 | 17 | trait MakefragSnippet { self: Annotation => 18 | def toMakefrag: String 19 | } 20 | 21 | case class CustomMakefragSnippet(val toMakefrag: String) extends NoTargetAnnotation with MakefragSnippet with Unserializable 22 | 23 | /** Generates a make script to run tests in [[RocketTestSuiteAnnotation]]. */ 24 | class GenerateTestSuiteMakefrags extends Phase with PreservesAll[Phase] with HasRocketChipStageUtils { 25 | 26 | // Our annotations tend not to be serializable, but are not marked as such. 27 | override val prerequisites = Seq(Dependency[freechips.rocketchip.stage.phases.GenerateFirrtlAnnos], 28 | Dependency[chipyard.stage.phases.AddDefaultTests]) 29 | 30 | override def transform(annotations: AnnotationSeq): AnnotationSeq = { 31 | val targetDir = view[StageOptions](annotations).targetDir 32 | val fileName = s"${view[RocketChipOptions](annotations).longName.get}.d" 33 | 34 | val makefragBuilder = new mutable.StringBuilder() 35 | val outputAnnotations = annotations.flatMap { 36 | case RocketTestSuiteAnnotation(tests) => 37 | // Unfortunately the gen method of TestGeneration is rocketchip package 38 | // private, so we either have to copy code in or use the stateful form 39 | TestGeneration.addSuites(tests) 40 | None 41 | case a: MakefragSnippet => 42 | makefragBuilder :+ ("\n" + a.toMakefrag) 43 | None 44 | case a => Some(a) 45 | } 46 | writeOutputFile(targetDir, fileName, TestGeneration.generateMakeFrag ++ makefragBuilder.toString) 47 | outputAnnotations 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /generators/chipyard/src/main/scala/DigitalTop.scala: -------------------------------------------------------------------------------- 1 | package chipyard 2 | 3 | import chisel3._ 4 | 5 | import freechips.rocketchip.subsystem._ 6 | import freechips.rocketchip.system._ 7 | import freechips.rocketchip.config.Parameters 8 | import freechips.rocketchip.devices.tilelink._ 9 | 10 | // ------------------------------------ 11 | // BOOM and/or Rocket Top Level Systems 12 | // ------------------------------------ 13 | 14 | // DOC include start: DigitalTop 15 | class DigitalTop(implicit p: Parameters) extends ChipyardSystem 16 | with testchipip.CanHavePeripheryCustomBootPin // Enables optional custom boot pin 17 | with testchipip.HasPeripheryBootAddrReg // Use programmable boot address register 18 | with testchipip.CanHaveTraceIO // Enables optionally adding trace IO 19 | with testchipip.CanHaveBackingScratchpad // Enables optionally adding a backing scratchpad 20 | with testchipip.CanHavePeripheryBlockDevice // Enables optionally adding the block device 21 | with testchipip.CanHavePeripheryTLSerial // Enables optionally adding the backing memory and serial adapter 22 | with sifive.blocks.devices.i2c.HasPeripheryI2C // Enables optionally adding the sifive I2C 23 | with sifive.blocks.devices.pwm.HasPeripheryPWM // Enables optionally adding the sifive PWM 24 | with sifive.blocks.devices.uart.HasPeripheryUART // Enables optionally adding the sifive UART 25 | with sifive.blocks.devices.gpio.HasPeripheryGPIO // Enables optionally adding the sifive GPIOs 26 | with sifive.blocks.devices.spi.HasPeripherySPIFlash // Enables optionally adding the sifive SPI flash controller 27 | with sifive.blocks.devices.spi.HasPeripherySPI // Enables optionally adding the sifive SPI port 28 | { 29 | override lazy val module = new DigitalTopModule(this) 30 | } 31 | 32 | class DigitalTopModule[+L <: DigitalTop](l: L) extends ChipyardSystemModule(l) 33 | with testchipip.CanHaveTraceIOModuleImp 34 | with sifive.blocks.devices.i2c.HasPeripheryI2CModuleImp 35 | with sifive.blocks.devices.pwm.HasPeripheryPWMModuleImp 36 | with sifive.blocks.devices.uart.HasPeripheryUARTModuleImp 37 | with sifive.blocks.devices.gpio.HasPeripheryGPIOModuleImp 38 | with sifive.blocks.devices.spi.HasPeripherySPIFlashModuleImp 39 | with sifive.blocks.devices.spi.HasPeripherySPIModuleImp 40 | with freechips.rocketchip.util.DontTouch 41 | // DOC include end: DigitalTop 42 | -------------------------------------------------------------------------------- /sims/verilator/verilator.mk: -------------------------------------------------------------------------------- 1 | ################################################################################ 2 | # Verilator flags 3 | ################################################################################ 4 | 5 | # Directories 6 | DRAMSIM_DIR := $(BOSSA_DIR)/tools/DRAMSim2 7 | 8 | # Tracing flags 9 | TRACING_OPTS := $(if $(filter $(VERILATOR_FST_MODE),0),\ 10 | --trace,--trace-fst --trace-threads 1) 11 | TRACING_CFLAGS := $(if $(filter $(VERILATOR_FST_MODE),0),,-DCY_FST_TRACE) 12 | 13 | # C++/linker flags 14 | SIM_CXXFLAGS := \ 15 | -std=c++11 \ 16 | -I$(ISA_SIM_INSTALL_DIR)/include \ 17 | -I$(DRAMSIM_DIR) \ 18 | -I$(BUILD_DIR) 19 | SIM_LDFLAGS := \ 20 | -L$(ISA_SIM_INSTALL_DIR)/lib \ 21 | -Wl,-rpath,$(ISA_SIM_INSTALL_DIR)/lib \ 22 | -L$(TOP_DIR) \ 23 | -L$(DRAMSIM_DIR) \ 24 | -lfesvr \ 25 | -ldramsim 26 | 27 | # Verilator C++/linker flags 28 | VERILATOR_CXXFLAGS := \ 29 | $(SIM_CXXFLAGS) \ 30 | $(TRACING_CFLAGS) \ 31 | -D__STDC_FORMAT_MACROS \ 32 | -DTEST_HARNESS=V$(TOP_MODULE) \ 33 | -DVERILATOR \ 34 | -include $(BUILD_DIR)/$(CIRCUIT_NAME).plusArgs \ 35 | -include $(BUILD_DIR)/verilator.h 36 | VERILATOR_LDFLAGS := $(SIM_LDFLAGS) 37 | VERILATOR_CC_OPTS := \ 38 | -CFLAGS "$(VERILATOR_CXXFLAGS)" \ 39 | -LDFLAGS "$(VERILATOR_LDFLAGS)" 40 | 41 | # Multi-threading related flags 42 | RUNTIME_THREADS := --threads $(VERILATOR_THREADS) --threads-dpi all 43 | 44 | # Optimization flags 45 | VERILATOR_OPT_FLAGS ?= \ 46 | -O2 \ 47 | --x-assign fast \ 48 | --x-initial fast \ 49 | --output-split 30000 \ 50 | --output-split-cfuncs 30000 51 | 52 | # Other flags 53 | CHIPYARD_VERILATOR_FLAGS := \ 54 | --assert 55 | TIMESCALE_OPTS := $(shell verilator --version | perl -lne 'if (/(\d.\d+)/ && $$1 >= 4.034) { print "--timescale 1ns/1ps"; }') 56 | MAX_WIDTH_OPTS = $(shell verilator --version | perl -lne 'if (/(\d.\d+)/ && $$1 > 4.016) { print "--max-num-width 1048576"; }') 57 | PREPROC_DEFINES := \ 58 | +define+PRINTF_COND=\$$c\(\"verbose\",\"\&\&\"\,\"done_reset\"\) \ 59 | +define+STOP_COND=\$$c\(\"done_reset\"\) 60 | 61 | # Verilator non-C++ flags 62 | VERILATOR_NONCC_OPTS := \ 63 | $(RUNTIME_THREADS) \ 64 | $(VERILATOR_OPT_FLAGS) \ 65 | $(CHIPYARD_VERILATOR_FLAGS) \ 66 | -Wno-fatal \ 67 | $(TIMESCALE_OPTS) \ 68 | $(MAX_WIDTH_OPTS) \ 69 | $(PREPROC_DEFINES) \ 70 | --top-module $(TOP_MODULE) \ 71 | --vpi \ 72 | -f $(SIM_COMMON_FILES) \ 73 | -f $(VERILOG_FILES) 74 | 75 | # All Verilator related flags 76 | VERILATOR_OPTS := $(VERILATOR_CC_OPTS) $(VERILATOR_NONCC_OPTS) 77 | -------------------------------------------------------------------------------- /generators/chipyard/src/main/scala/stage/phases/AddDefaultTests.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE for license details. 2 | // Based on Rocket Chip's stage implementation 3 | 4 | package chipyard.stage.phases 5 | 6 | import scala.util.Try 7 | import scala.collection.mutable 8 | 9 | import chipsalliance.rocketchip.config.Parameters 10 | import chisel3.stage.phases.Elaborate 11 | import firrtl.AnnotationSeq 12 | import firrtl.annotations.{Annotation, NoTargetAnnotation} 13 | import firrtl.options.{Phase, PreservesAll, Dependency} 14 | import firrtl.options.Viewer.view 15 | import freechips.rocketchip.stage.RocketChipOptions 16 | import freechips.rocketchip.stage.phases.{RocketTestSuiteAnnotation} 17 | import freechips.rocketchip.system.{RocketTestSuite, TestGeneration} 18 | import freechips.rocketchip.subsystem.{TilesLocated, InSubsystem} 19 | import freechips.rocketchip.util.HasRocketChipStageUtils 20 | import freechips.rocketchip.tile.XLen 21 | 22 | import chipyard.TestSuiteHelper 23 | import chipyard.TestSuitesKey 24 | 25 | class AddDefaultTests extends Phase with PreservesAll[Phase] with HasRocketChipStageUtils { 26 | // Make sure we run both after RocketChip's version of this phase, and Rocket Chip's annotation emission phase 27 | // because the RocketTestSuiteAnnotation is not serializable (but is not marked as such). 28 | override val prerequisites = Seq( 29 | Dependency[freechips.rocketchip.stage.phases.GenerateFirrtlAnnos], 30 | Dependency[freechips.rocketchip.stage.phases.AddDefaultTests]) 31 | override val dependents = Seq(Dependency[freechips.rocketchip.stage.phases.GenerateTestSuiteMakefrags]) 32 | 33 | private def addTestSuiteAnnotations(implicit p: Parameters): Seq[Annotation] = { 34 | val annotations = mutable.ArrayBuffer[Annotation]() 35 | val suiteHelper = new TestSuiteHelper 36 | // Use Xlen as a proxy for detecting if we are a processor-like target 37 | // The underlying test suites expect this field to be defined 38 | val tileParams = p(TilesLocated(InSubsystem)) map (tp => tp.tileParams) 39 | if (p.lift(XLen).nonEmpty) 40 | // If a custom test suite is set up, use the custom test suite 41 | annotations += CustomMakefragSnippet(p(TestSuitesKey).apply(tileParams, suiteHelper, p)) 42 | 43 | RocketTestSuiteAnnotation(suiteHelper.suites.values.toSeq) +: annotations 44 | } 45 | 46 | 47 | override def transform(annotations: AnnotationSeq): AnnotationSeq = { 48 | val (testSuiteAnnos, oAnnos) = annotations.partition { 49 | case RocketTestSuiteAnnotation(_) => true 50 | case o => false 51 | } 52 | implicit val p = getConfig(view[RocketChipOptions](annotations).configNames.get).toInstance 53 | addTestSuiteAnnotations ++ oAnnos 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /generators/chipyard/src/main/scala/ChipTop.scala: -------------------------------------------------------------------------------- 1 | package chipyard 2 | 3 | import chisel3._ 4 | 5 | import scala.collection.mutable.{ArrayBuffer} 6 | 7 | import freechips.rocketchip.prci.{ClockGroupIdentityNode, ClockSinkParameters, ClockSinkNode, ClockGroup} 8 | import freechips.rocketchip.subsystem.{BaseSubsystem, SubsystemDriveAsyncClockGroupsKey} 9 | import freechips.rocketchip.config.{Parameters, Field} 10 | import freechips.rocketchip.diplomacy.{LazyModule, LazyModuleImp, LazyRawModuleImp, LazyModuleImpLike, BindingScope} 11 | import freechips.rocketchip.util.{ResetCatchAndSync} 12 | import chipyard.iobinders._ 13 | 14 | import barstools.iocell.chisel._ 15 | 16 | case object BuildSystem extends Field[Parameters => LazyModule]((p: Parameters) => new DigitalTop()(p)) 17 | 18 | trait HasReferenceClockFreq { 19 | def refClockFreqMHz: Double 20 | } 21 | 22 | /** 23 | * The base class used for building chips. This constructor instantiates a module specified by the BuildSystem parameter, 24 | * named "system", which is an instance of DigitalTop by default. The diplomatic clocks of System, as well as its implicit clock, 25 | * is aggregated into the clockGroupNode. The parameterized functions controlled by ClockingSchemeKey and GlobalResetSchemeKey 26 | * drive clock and reset generation 27 | */ 28 | 29 | class ChipTop(implicit p: Parameters) extends LazyModule with BindingScope 30 | with HasTestHarnessFunctions with HasReferenceClockFreq with HasIOBinders { 31 | // The system module specified by BuildSystem 32 | lazy val lazySystem = LazyModule(p(BuildSystem)(p)).suggestName("system") 33 | 34 | // The implicitClockSinkNode provides the implicit clock and reset for the system (connected by clocking scheme) 35 | val implicitClockSinkNode = ClockSinkNode(Seq(ClockSinkParameters(name = Some("implicit_clock")))) 36 | 37 | // Generate Clocks and Reset 38 | val mvRefClkFreq = p(ClockingSchemeKey)(this) 39 | def refClockFreqMHz: Double = mvRefClkFreq.getWrappedValue 40 | 41 | // NOTE: Making this a LazyRawModule is moderately dangerous, as anonymous children 42 | // of ChipTop (ex: ClockGroup) do not receive clock or reset. 43 | // However. anonymous children of ChipTop should not need an implicit Clock or Reset 44 | // anyways, they probably need to be explicitly clocked. 45 | lazy val module: LazyModuleImpLike = new LazyRawModuleImp(this) { 46 | // These become the implicit clock and reset to the System 47 | val implicit_clock = implicitClockSinkNode.in.head._1.clock 48 | val implicit_reset = implicitClockSinkNode.in.head._1.reset 49 | 50 | // Connect the implicit clock/reset, if present 51 | lazySystem.module match { case l: LazyModuleImp => { 52 | l.clock := implicit_clock 53 | l.reset := implicit_reset 54 | }} 55 | } 56 | } 57 | 58 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Boosa: BOOM's Simulation Accelerator 2 | 3 | Bossa is a [Chipyard](https://github.com/ucb-bar/chipyard)-based framework designed to accelerate the BOOM simulation process. 4 | 5 | Bossa keeps only the necessary components for simulating BOOM, and the submodules in Chipyard, such as Gemmini, Hwacha, IceNet, NVDLA, etc. are all removed. 6 | 7 | Bossa will use [Frenda](https://github.com/MaxXSoft/Frenda) to incrementally compile the generated FIRRTL. This will be very helpful if you keep modifying the BOOM and then run simulation again and again, it can save you a lot of time. 8 | 9 | Bossa currently supports only Verilator-based simulations. 10 | 11 | ## Prerequisites 12 | 13 | ### Using Bossa's Docker Image 14 | 15 | Just run: 16 | 17 | ```sh 18 | docker pull maxxing/bossa-image 19 | docker run -it maxxing/bossa-image bash 20 | ``` 21 | 22 | See [docker/README.md](docker/README.md) for more details. 23 | 24 | ### Using Bossa on Your Local Machine 25 | 26 | * Ubuntu (20.04+ recommended). 27 | * JDK 11+. 28 | * C++ compiler and Make (`build-essential`). 29 | * Python 3.7+. 30 | * Verilator. 31 | * Device tree compiler (for building `riscv-isa-sim`). 32 | * Git. 33 | 34 | You can run the following command to setup prerequisites on Ubuntu: 35 | 36 | ```sh 37 | sudo scripts/setup-prerequisites.sh 38 | ``` 39 | 40 | ## Getting Started 41 | 42 | ### Setting Up Prerequisites and Initializing 43 | 44 | ```sh 45 | sudo scripts/setup-prerequisites.sh 46 | git submodule update --init --recursive --depth=1 47 | ``` 48 | 49 | ### Building for Simulation 50 | 51 | ```sh 52 | cd sims/verilator 53 | # build simulation for small BOOM 54 | make CONFIG=SmallBoomConfig -j`nproc` 55 | # or, enable multi-threading 56 | make CONFIG=SmallBoomConfig VERILATOR_THREADS=8 -j`nproc` 57 | # or, enable debugging with VCD waveform dump 58 | make CONFIG=SmallBoomConfig debug -j`nproc` 59 | # or, enable debugging with FST waveform dump 60 | make CONFIG=SmallBoomConfig VERILATOR_FST_MODE=1 debug -j`nproc` 61 | ``` 62 | 63 | ### Bulding and Running Simulator 64 | 65 | ```sh 66 | cd sims/verilator 67 | make CONFIG=SmallBoomConfig -j`nproc` 68 | ./simulator-SmallBoomConfig path/to/riscv/program 69 | ``` 70 | 71 | ## Make Options Supported during Simulator Build 72 | 73 | * `CONFIG`: the configuration class to give the parameters for the project (default `SmallBoomConfig`). 74 | * `FRENDA_THREADS`: how many threads the incremental FIRRTL compiler will use (default `nproc`). 75 | * `FRENDA_CLEAN_BUILD`: perform clean FIRRTL build instead of incremental FIRRTL build. 76 | * `VERILATOR_THREADS`: how many threads the simulator will use (default 1). 77 | * `VERILATOR_FST_MODE`: enable FST waveform instead of VCD. use with debug build. 78 | * `TOP_MODULE`: the top level module of the project (default `TestHarness`). 79 | * `VERILATOR_OPT_FLAGS`: Verilator optimization flags (default `-O2 --x-assign fast --x-initial fast --output-split 30000 --output-split-cfuncs 30000`). 80 | 81 | ## Changelog 82 | 83 | See [CHANGELOG.md](CHANGELOG.md). 84 | -------------------------------------------------------------------------------- /generators/chipyard/src/main/scala/clocking/ClockGroupNamePrefixer.scala: -------------------------------------------------------------------------------- 1 | package chipyard.clocking 2 | 3 | import chisel3._ 4 | 5 | import freechips.rocketchip.config.{Parameters} 6 | import freechips.rocketchip.diplomacy._ 7 | import freechips.rocketchip.prci._ 8 | 9 | /** 10 | * This sort of node can be used when it is a connectivity passthrough, but modifies 11 | * the flow of parameters (which may result in changing the names of the underlying signals). 12 | */ 13 | class ClockGroupParameterModifier( 14 | sourceFn: ClockGroupSourceParameters => ClockGroupSourceParameters = { m => m }, 15 | sinkFn: ClockGroupSinkParameters => ClockGroupSinkParameters = { s => s })( 16 | implicit p: Parameters, v: ValName) extends LazyModule { 17 | val node = ClockGroupAdapterNode(sourceFn, sinkFn) 18 | lazy val module = new LazyRawModuleImp(this) { 19 | (node.out zip node.in).map { case ((o, _), (i, _)) => 20 | (o.member.data zip i.member.data).foreach { case (oD, iD) => oD := iD } 21 | } 22 | } 23 | } 24 | 25 | /** 26 | * Pushes the ClockGroup's name into each member's name field as a prefix. This is 27 | * intended to be used before a ClockGroupAggregator so that sources from 28 | * different aggregated ClockGroups can be disambiguated by their names. 29 | */ 30 | object ClockGroupNamePrefixer { 31 | def apply()(implicit p: Parameters, valName: ValName): ClockGroupAdapterNode = 32 | LazyModule(new ClockGroupParameterModifier(sinkFn = { s => s.copy(members = s.members.zipWithIndex.map { case (m, idx) => 33 | m.copy(name = m.name match { 34 | // This matches what the chisel would do if the names were not modified 35 | case Some(clockName) => Some(s"${s.name}_${clockName}") 36 | case None => Some(s"${s.name}_${idx}") 37 | }) 38 | })})).node 39 | } 40 | 41 | /** 42 | * [Word from on high is that Strings are in...] 43 | * Overrides the take field of all clocks in a group, by attempting to apply a 44 | * series of assignment functions: 45 | * (name: String) => freq-in-MHz: Option[Double] 46 | * to each sink. Later functions that return non-empty values take priority. 47 | * The default if all functions return None. 48 | */ 49 | object ClockGroupFrequencySpecifier { 50 | def apply( 51 | assigners: Seq[(String) => Option[Double]], 52 | defaultFreq: Double)( 53 | implicit p: Parameters, valName: ValName): ClockGroupAdapterNode = { 54 | 55 | def lookupFrequencyForName(clock: ClockSinkParameters): ClockSinkParameters = { 56 | require(clock.name.nonEmpty, "All clocks in clock group must have an assigned name") 57 | val clockFreq = assigners.foldLeft(defaultFreq)( 58 | (currentFreq, candidateFunc) => candidateFunc(clock.name.get).getOrElse(currentFreq)) 59 | 60 | clock.copy(take = clock.take match { 61 | case Some(cp) => 62 | println(s"Clock ${clock.name.get}: using diplomatically specified frequency of ${cp.freqMHz}.") 63 | Some(cp) 64 | case None => Some(ClockParameters(clockFreq)) 65 | }) 66 | } 67 | 68 | LazyModule(new ClockGroupParameterModifier(sinkFn = { s => s.copy(members = s.members.map(lookupFrequencyForName)) })).node 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /generators/chipyard/src/main/scala/CustomBusTopologies.scala: -------------------------------------------------------------------------------- 1 | 2 | package chipyard 3 | 4 | import freechips.rocketchip.config.{Field, Config, Parameters} 5 | import freechips.rocketchip.diplomacy._ 6 | import freechips.rocketchip.tilelink._ 7 | import freechips.rocketchip.util.{Location, Symmetric} 8 | import freechips.rocketchip.subsystem._ 9 | 10 | // I'm putting this code here temporarily as I think it should be a candidate 11 | // for upstreaming based on input from Henry Cook, but don't wnat to deal with 12 | // an RC branch just yet. 13 | 14 | // For subsystem/BusTopology.scala 15 | 16 | // Biancolin: This, modified from Henry's email 17 | /** Parameterization of a topology containing a banked coherence manager and a bus for attaching memory devices. */ 18 | case class CoherentMulticlockBusTopologyParams( 19 | sbus: SystemBusParams, // TODO remove this after better width propagation 20 | mbus: MemoryBusParams, 21 | l2: BankedL2Params, 22 | sbusToMbusXType: ClockCrossingType = NoCrossing 23 | ) extends TLBusWrapperTopology( 24 | instantiations = (if (l2.nBanks == 0) Nil else List( 25 | (MBUS, mbus), 26 | (L2, CoherenceManagerWrapperParams(mbus.blockBytes, mbus.beatBytes, l2.nBanks, L2.name)(l2.coherenceManager)))), 27 | connections = if (l2.nBanks == 0) Nil else List( 28 | (SBUS, L2, TLBusWrapperConnection(xType = NoCrossing, driveClockFromMaster = Some(true), nodeBinding = BIND_STAR)()), 29 | (L2, MBUS, TLBusWrapperConnection.crossTo( 30 | xType = sbusToMbusXType, 31 | driveClockFromMaster = None, 32 | nodeBinding = BIND_QUERY)) 33 | ) 34 | ) 35 | 36 | // This differs from upstream only in that it does not use the legacy crossTo 37 | // and crossFrom functions, and it ensures driveClockFromMaster = None 38 | case class HierarchicalMulticlockBusTopologyParams( 39 | pbus: PeripheryBusParams, 40 | fbus: FrontBusParams, 41 | cbus: PeripheryBusParams, 42 | xTypes: SubsystemCrossingParams 43 | ) extends TLBusWrapperTopology( 44 | instantiations = List( 45 | (PBUS, pbus), 46 | (FBUS, fbus), 47 | (CBUS, cbus)), 48 | connections = List( 49 | (SBUS, CBUS, TLBusWrapperConnection. crossTo(xType = xTypes.sbusToCbusXType, driveClockFromMaster = None)), 50 | (CBUS, PBUS, TLBusWrapperConnection. crossTo(xType = xTypes.cbusToPbusXType, driveClockFromMaster = None)), 51 | (FBUS, SBUS, TLBusWrapperConnection.crossFrom(xType = xTypes.fbusToSbusXType, driveClockFromMaster = None))) 52 | ) 53 | 54 | // For subsystem/Configs.scala 55 | 56 | class WithMulticlockCoherentBusTopology extends Config((site, here, up) => { 57 | case TLNetworkTopologyLocated(InSubsystem) => List( 58 | JustOneBusTopologyParams(sbus = site(SystemBusKey)), 59 | HierarchicalMulticlockBusTopologyParams( 60 | pbus = site(PeripheryBusKey), 61 | fbus = site(FrontBusKey), 62 | cbus = site(ControlBusKey), 63 | xTypes = SubsystemCrossingParams( 64 | sbusToCbusXType = site(SbusToCbusXTypeKey), 65 | cbusToPbusXType = site(CbusToPbusXTypeKey), 66 | fbusToSbusXType = site(FbusToSbusXTypeKey))), 67 | CoherentMulticlockBusTopologyParams( 68 | sbus = site(SystemBusKey), 69 | mbus = site(MemoryBusKey), 70 | l2 = site(BankedL2Key), 71 | sbusToMbusXType = site(SbusToMbusXTypeKey))) 72 | }) 73 | 74 | class WithMulticlockIncoherentBusTopology extends Config((site, here, up) => { 75 | case TLNetworkTopologyLocated(InSubsystem) => List( 76 | JustOneBusTopologyParams(sbus = site(SystemBusKey)), 77 | HierarchicalMulticlockBusTopologyParams( 78 | pbus = site(PeripheryBusKey), 79 | fbus = site(FrontBusKey), 80 | cbus = site(ControlBusKey), 81 | xTypes = SubsystemCrossingParams())) 82 | }) 83 | -------------------------------------------------------------------------------- /generators/chipyard/src/main/scala/Subsystem.scala: -------------------------------------------------------------------------------- 1 | //****************************************************************************** 2 | // Copyright (c) 2019 - 2019, The Regents of the University of California (Regents). 3 | // All Rights Reserved. See LICENSE and LICENSE.SiFive for license details. 4 | //------------------------------------------------------------------------------ 5 | 6 | package chipyard 7 | 8 | import chisel3._ 9 | import chisel3.internal.sourceinfo.{SourceInfo} 10 | 11 | import freechips.rocketchip.prci._ 12 | import freechips.rocketchip.config.{Field, Parameters} 13 | import freechips.rocketchip.devices.tilelink._ 14 | import freechips.rocketchip.devices.debug.{HasPeripheryDebug, HasPeripheryDebugModuleImp, ExportDebug, DebugModuleKey} 15 | import freechips.rocketchip.diplomacy._ 16 | import freechips.rocketchip.diplomaticobjectmodel.model.{OMInterrupt} 17 | import freechips.rocketchip.diplomaticobjectmodel.logicaltree.{RocketTileLogicalTreeNode, LogicalModuleTree} 18 | import freechips.rocketchip.tile._ 19 | import freechips.rocketchip.tilelink._ 20 | import freechips.rocketchip.interrupts._ 21 | import freechips.rocketchip.util._ 22 | import freechips.rocketchip.subsystem._ 23 | import freechips.rocketchip.amba.axi4._ 24 | 25 | import boom.common.{BoomTile} 26 | 27 | 28 | import testchipip.{CanHavePeripheryTLSerial, SerialTLKey} 29 | 30 | trait CanHaveHTIF { this: BaseSubsystem => 31 | // Advertise HTIF if system can communicate with fesvr 32 | if (this match { 33 | case _: CanHavePeripheryTLSerial if p(SerialTLKey).nonEmpty => true 34 | case _: HasPeripheryDebug if (!p(DebugModuleKey).isEmpty && p(ExportDebug).dmi) => true 35 | case _ => false 36 | }) { 37 | ResourceBinding { 38 | val htif = new Device { 39 | def describe(resources: ResourceBindings): Description = { 40 | val compat = resources("compat").map(_.value) 41 | Description("htif", Map( 42 | "compatible" -> compat)) 43 | } 44 | } 45 | Resource(htif, "compat").bind(ResourceString("ucb,htif0")) 46 | } 47 | } 48 | } 49 | 50 | class ChipyardSubsystem(implicit p: Parameters) extends BaseSubsystem 51 | with HasTiles 52 | with CanHaveHTIF 53 | { 54 | def coreMonitorBundles = tiles.map { 55 | case r: RocketTile => r.module.core.rocketImpl.coreMonitorBundle 56 | case b: BoomTile => b.module.core.coreMonitorBundle 57 | }.toList 58 | 59 | 60 | // Relying on [[TLBusWrapperConnection]].driveClockFromMaster for 61 | // bus-couplings that are not asynchronous strips the bus name from the sink 62 | // ClockGroup. This makes it impossible to determine which clocks are driven 63 | // by which bus based on the member names, which is problematic when there is 64 | // a rational crossing between two buses. Instead, provide all bus clocks 65 | // directly from the asyncClockGroupsNode in the subsystem to ensure bus 66 | // names are always preserved in the top-level clock names. 67 | // 68 | // For example, using a RationalCrossing between the Sbus and Cbus, and 69 | // driveClockFromMaster = Some(true) results in all cbus-attached device and 70 | // bus clocks to be given names of the form "subsystem_sbus_[0-9]*". 71 | // Conversly, if an async crossing is used, they instead receive names of the 72 | // form "subsystem_cbus_[0-9]*". The assignment below provides the latter names in all cases. 73 | Seq(PBUS, FBUS, MBUS, CBUS).foreach { loc => 74 | tlBusWrapperLocationMap.lift(loc).foreach { _.clockGroupNode := asyncClockGroupsNode } 75 | } 76 | override lazy val module = new ChipyardSubsystemModuleImp(this) 77 | } 78 | 79 | class ChipyardSubsystemModuleImp[+L <: ChipyardSubsystem](_outer: L) extends BaseSubsystemModuleImp(_outer) 80 | with HasTilesModuleImp 81 | { 82 | // create file with core params 83 | ElaborationArtefacts.add("""core.config""", outer.tiles.map(x => x.module.toString).mkString("\n")) 84 | } 85 | 86 | -------------------------------------------------------------------------------- /generators/chipyard/src/main/scala/System.scala: -------------------------------------------------------------------------------- 1 | //****************************************************************************** 2 | // Copyright (c) 2019 - 2019, The Regents of the University of California (Regents). 3 | // All Rights Reserved. See LICENSE and LICENSE.SiFive for license details. 4 | //------------------------------------------------------------------------------ 5 | 6 | package chipyard 7 | 8 | import chisel3._ 9 | 10 | import freechips.rocketchip.config.{Parameters, Field} 11 | import freechips.rocketchip.subsystem._ 12 | import freechips.rocketchip.tilelink._ 13 | import freechips.rocketchip.devices.tilelink._ 14 | import freechips.rocketchip.diplomacy._ 15 | import freechips.rocketchip.util.{DontTouch} 16 | 17 | // --------------------------------------------------------------------- 18 | // Base system that uses the debug test module (dtm) to bringup the core 19 | // --------------------------------------------------------------------- 20 | 21 | /** 22 | * Base top with periphery devices and ports, and a BOOM + Rocket subsystem 23 | */ 24 | class ChipyardSystem(implicit p: Parameters) extends ChipyardSubsystem 25 | with HasAsyncExtInterrupts 26 | with CanHaveMasterTLMemPort // export TL port for outer memory 27 | with CanHaveMasterAXI4MemPort // expose AXI port for outer mem 28 | with CanHaveMasterAXI4MMIOPort 29 | with CanHaveSlaveAXI4Port 30 | { 31 | 32 | val bootROM = p(BootROMLocated(location)).map { BootROM.attach(_, this, CBUS) } 33 | val maskROMs = p(MaskROMLocated(location)).map { MaskROM.attach(_, this, CBUS) } 34 | override lazy val module = new ChipyardSystemModule(this) 35 | } 36 | 37 | /** 38 | * Base top module implementation with periphery devices and ports, and a BOOM + Rocket subsystem 39 | */ 40 | class ChipyardSystemModule[+L <: ChipyardSystem](_outer: L) extends ChipyardSubsystemModuleImp(_outer) 41 | with HasRTCModuleImp 42 | with HasExtInterruptsModuleImp 43 | with DontTouch 44 | 45 | // ------------------------------------ 46 | // TL Mem Port Mixin 47 | // ------------------------------------ 48 | 49 | // Similar to ExtMem but instantiates a TL mem port 50 | case object ExtTLMem extends Field[Option[MemoryPortParams]](None) 51 | 52 | /** Adds a port to the system intended to master an TL DRAM controller. */ 53 | trait CanHaveMasterTLMemPort { this: BaseSubsystem => 54 | 55 | require(!(p(ExtTLMem).nonEmpty && p(ExtMem).nonEmpty), 56 | "Can only have 1 backing memory port. Use ExtTLMem for a TL memory port or ExtMem for an AXI memory port.") 57 | 58 | private val memPortParamsOpt = p(ExtTLMem) 59 | private val portName = "tl_mem" 60 | private val device = new MemoryDevice 61 | private val idBits = memPortParamsOpt.map(_.master.idBits).getOrElse(1) 62 | 63 | val memTLNode = TLManagerNode(memPortParamsOpt.map({ case MemoryPortParams(memPortParams, nMemoryChannels) => 64 | Seq.tabulate(nMemoryChannels) { channel => 65 | val base = AddressSet.misaligned(memPortParams.base, memPortParams.size) 66 | val filter = AddressSet(channel * mbus.blockBytes, ~((nMemoryChannels-1) * mbus.blockBytes)) 67 | 68 | TLSlavePortParameters.v1( 69 | managers = Seq(TLSlaveParameters.v1( 70 | address = base.flatMap(_.intersect(filter)), 71 | resources = device.reg, 72 | regionType = RegionType.UNCACHED, // cacheable 73 | executable = true, 74 | supportsGet = TransferSizes(1, mbus.blockBytes), 75 | supportsPutFull = TransferSizes(1, mbus.blockBytes), 76 | supportsPutPartial = TransferSizes(1, mbus.blockBytes))), 77 | beatBytes = memPortParams.beatBytes) 78 | } 79 | }).toList.flatten) 80 | 81 | mbus.coupleTo(s"memory_controller_port_named_$portName") { 82 | (memTLNode 83 | :*= TLBuffer() 84 | :*= TLSourceShrinker(1 << idBits) 85 | :*= TLWidthWidget(mbus.beatBytes) 86 | :*= _) 87 | } 88 | 89 | val mem_tl = InModuleBody { memTLNode.makeIOs() } 90 | } 91 | -------------------------------------------------------------------------------- /generators/chipyard/src/main/scala/TestSuites.scala: -------------------------------------------------------------------------------- 1 | package chipyard 2 | 3 | import scala.collection.mutable.{LinkedHashSet} 4 | 5 | import freechips.rocketchip.subsystem._ 6 | import freechips.rocketchip.tile.{XLen, TileParams} 7 | import freechips.rocketchip.config.{Parameters, Field, Config} 8 | import freechips.rocketchip.system.{TestGeneration, RegressionTestSuite, RocketTestSuite} 9 | 10 | /** 11 | * A set of pre-chosen regression tests 12 | */ 13 | object RegressionTestSuites 14 | { 15 | val rv64RegrTestNames = LinkedHashSet( 16 | "rv64ud-v-fcvt", 17 | "rv64ud-p-fdiv", 18 | "rv64ud-v-fadd", 19 | "rv64uf-v-fadd", 20 | "rv64um-v-mul", 21 | "rv64mi-p-breakpoint", 22 | "rv64uc-v-rvc", 23 | "rv64ud-v-structural", 24 | "rv64si-p-wfi", 25 | "rv64um-v-divw", 26 | "rv64ua-v-lrsc", 27 | "rv64ui-v-fence_i", 28 | "rv64ud-v-fcvt_w", 29 | "rv64uf-v-fmin", 30 | "rv64ui-v-sb", 31 | "rv64ua-v-amomax_d", 32 | "rv64ud-v-move", 33 | "rv64ud-v-fclass", 34 | "rv64ua-v-amoand_d", 35 | "rv64ua-v-amoxor_d", 36 | "rv64si-p-sbreak", 37 | "rv64ud-v-fmadd", 38 | "rv64uf-v-ldst", 39 | "rv64um-v-mulh", 40 | "rv64si-p-dirty") 41 | 42 | val rv32RegrTestNames = LinkedHashSet( 43 | "rv32mi-p-ma_addr", 44 | "rv32mi-p-csr", 45 | "rv32ui-p-sh", 46 | "rv32ui-p-lh", 47 | "rv32uc-p-rvc", 48 | "rv32mi-p-sbreak", 49 | "rv32ui-p-sll") 50 | } 51 | 52 | /** 53 | * Helper functions to add BOOM or Rocket tests 54 | */ 55 | class TestSuiteHelper 56 | { 57 | import freechips.rocketchip.system.DefaultTestSuites._ 58 | import RegressionTestSuites._ 59 | val suites = collection.mutable.ListMap[String, RocketTestSuite]() 60 | def addSuite(s: RocketTestSuite) { suites += (s.makeTargetName -> s) } 61 | def addSuites(s: Seq[RocketTestSuite]) { s.foreach(addSuite) } 62 | 63 | /** 64 | * Add generic tests (asm, bmark, regression) for all cores. 65 | */ 66 | def addGenericTestSuites(tiles: Seq[TileParams])(implicit p: Parameters) = { 67 | val xlen = p(XLen) 68 | tiles.find(_.hartId == 0).map { tileParams => 69 | val coreParams = tileParams.core 70 | val vm = coreParams.useVM 71 | val env = if (vm) List("p","v") else List("p") 72 | coreParams.fpu foreach { case cfg => 73 | if (xlen == 32) { 74 | addSuites(env.map(rv32uf)) 75 | if (cfg.fLen >= 64) 76 | addSuites(env.map(rv32ud)) 77 | } else { 78 | addSuite(rv32udBenchmarks) 79 | addSuites(env.map(rv64uf)) 80 | if (cfg.fLen >= 64) 81 | addSuites(env.map(rv64ud)) 82 | } 83 | } 84 | if (coreParams.useAtomics) { 85 | if (tileParams.dcache.flatMap(_.scratch).isEmpty) 86 | addSuites(env.map(if (xlen == 64) rv64ua else rv32ua)) 87 | else 88 | addSuites(env.map(if (xlen == 64) rv64uaSansLRSC else rv32uaSansLRSC)) 89 | } 90 | if (coreParams.useCompressed) addSuites(env.map(if (xlen == 64) rv64uc else rv32uc)) 91 | val (rvi, rvu) = 92 | if (xlen == 64) ((if (vm) rv64i else rv64pi), (if (coreParams.mulDiv.isDefined) rv64u else List(rv64ui))) 93 | else ((if (vm) rv32i else rv32pi), (if (coreParams.mulDiv.isDefined) rv32u else List(rv32ui))) 94 | 95 | addSuites(rvi.map(_("p"))) 96 | addSuites(rvu.map(_("p"))) 97 | addSuites((if (vm) List("v") else List()).flatMap(env => rvu.map(_(env)))) 98 | addSuite(benchmarks) 99 | addSuite(new RegressionTestSuite(if (xlen == 64) rv64RegrTestNames else rv32RegrTestNames)) 100 | } 101 | } 102 | } 103 | 104 | /** 105 | * Config key of custom test suite. 106 | */ 107 | case object TestSuitesKey extends Field[(Seq[TileParams], TestSuiteHelper, Parameters) => String]((tiles, helper, p) => { 108 | helper.addGenericTestSuites(tiles)(p) 109 | // Return an empty string as makefile additional snippets 110 | "" 111 | }) 112 | -------------------------------------------------------------------------------- /generators/chipyard/src/main/scala/config/AbstractConfig.scala: -------------------------------------------------------------------------------- 1 | package chipyard.config 2 | 3 | import freechips.rocketchip.config.{Config} 4 | 5 | // -------------- 6 | // Chipyard abstract ("base") configuration 7 | // NOTE: This configuration is NOT INSTANTIABLE, as it defines a empty system with no tiles 8 | // 9 | // The default set of IOBinders instantiate IOcells and ChipTop IOs for digital IO bundles. 10 | // The default set of HarnessBinders instantiate TestHarness hardware for interacting with ChipTop IOs 11 | // -------------- 12 | 13 | class AbstractConfig extends Config( 14 | // The HarnessBinders control generation of hardware in the TestHarness 15 | new chipyard.harness.WithUARTAdapter ++ // add UART adapter to display UART on stdout, if uart is present 16 | new chipyard.harness.WithBlackBoxSimMem ++ // add SimDRAM DRAM model for axi4 backing memory, if axi4 mem is enabled 17 | new chipyard.harness.WithSimSerial ++ // add external serial-adapter and RAM 18 | new chipyard.harness.WithSimDebug ++ // add SimJTAG or SimDTM adapters if debug module is enabled 19 | new chipyard.harness.WithGPIOTiedOff ++ // tie-off chiptop GPIOs, if GPIOs are present 20 | new chipyard.harness.WithSimSPIFlashModel ++ // add simulated SPI flash memory, if SPI is enabled 21 | new chipyard.harness.WithSimAXIMMIO ++ // add SimAXIMem for axi4 mmio port, if enabled 22 | new chipyard.harness.WithTieOffInterrupts ++ // tie-off interrupt ports, if present 23 | new chipyard.harness.WithTieOffL2FBusAXI ++ // tie-off external AXI4 master, if present 24 | new chipyard.harness.WithTieOffCustomBootPin ++ 25 | 26 | // The IOBinders instantiate ChipTop IOs to match desired digital IOs 27 | // IOCells are generated for "Chip-like" IOs, while simulation-only IOs are directly punched through 28 | new chipyard.iobinders.WithAXI4MemPunchthrough ++ 29 | new chipyard.iobinders.WithAXI4MMIOPunchthrough ++ 30 | new chipyard.iobinders.WithL2FBusAXI4Punchthrough ++ 31 | new chipyard.iobinders.WithBlockDeviceIOPunchthrough ++ 32 | new chipyard.iobinders.WithSerialTLIOCells ++ 33 | new chipyard.iobinders.WithDebugIOCells ++ 34 | new chipyard.iobinders.WithUARTIOCells ++ 35 | new chipyard.iobinders.WithGPIOCells ++ 36 | new chipyard.iobinders.WithUARTIOCells ++ 37 | new chipyard.iobinders.WithSPIIOCells ++ 38 | new chipyard.iobinders.WithTraceIOPunchthrough ++ 39 | new chipyard.iobinders.WithExtInterruptIOCells ++ 40 | new chipyard.iobinders.WithCustomBootPin ++ 41 | 42 | new testchipip.WithDefaultSerialTL ++ // use serialized tilelink port to external serialadapter/harnessRAM 43 | new chipyard.config.WithBootROM ++ // use default bootrom 44 | new chipyard.config.WithUART ++ // add a UART 45 | new chipyard.config.WithL2TLBs(1024) ++ // use L2 TLBs 46 | new chipyard.config.WithNoSubsystemDrivenClocks ++ // drive the subsystem diplomatic clocks from ChipTop instead of using implicit clocks 47 | new chipyard.config.WithInheritBusFrequencyAssignments ++ // Unspecified clocks within a bus will receive the bus frequency if set 48 | new chipyard.config.WithPeripheryBusFrequencyAsDefault ++ // Unspecified frequencies with match the pbus frequency (which is always set) 49 | new chipyard.config.WithMemoryBusFrequency(100.0) ++ // Default 100 MHz mbus 50 | new chipyard.config.WithPeripheryBusFrequency(100.0) ++ // Default 100 MHz pbus 51 | new freechips.rocketchip.subsystem.WithJtagDTM ++ // set the debug module to expose a JTAG port 52 | new freechips.rocketchip.subsystem.WithNoMMIOPort ++ // no top-level MMIO master port (overrides default set in rocketchip) 53 | new freechips.rocketchip.subsystem.WithNoSlavePort ++ // no top-level MMIO slave port (overrides default set in rocketchip) 54 | new freechips.rocketchip.subsystem.WithBufferlessBroadcastHub ++ // bufferless (without L2 cache) 55 | new freechips.rocketchip.subsystem.WithNExtTopInterrupts(0) ++ // no external interrupts 56 | new chipyard.WithMulticlockCoherentBusTopology ++ // hierarchical buses including mbus+l2 57 | new freechips.rocketchip.system.BaseConfig) // "base" rocketchip system 58 | -------------------------------------------------------------------------------- /generators/chipyard/src/main/scala/TestHarness.scala: -------------------------------------------------------------------------------- 1 | package chipyard 2 | 3 | import chisel3._ 4 | 5 | import scala.collection.mutable.{ArrayBuffer, LinkedHashMap} 6 | import freechips.rocketchip.diplomacy.{LazyModule} 7 | import freechips.rocketchip.config.{Field, Parameters} 8 | import freechips.rocketchip.util.{ResetCatchAndSync} 9 | import freechips.rocketchip.prci.{ClockBundle, ClockBundleParameters, ClockSinkParameters, ClockParameters} 10 | 11 | import chipyard.harness.{ApplyHarnessBinders, HarnessBinders} 12 | import chipyard.iobinders.HasIOBinders 13 | import chipyard.clocking.{SimplePllConfiguration, ClockDividerN} 14 | 15 | // ------------------------------- 16 | // Chipyard Test Harness 17 | // ------------------------------- 18 | 19 | case object BuildTop extends Field[Parameters => LazyModule]((p: Parameters) => new ChipTop()(p)) 20 | 21 | trait HasTestHarnessFunctions { 22 | val harnessFunctions = ArrayBuffer.empty[HasHarnessSignalReferences => Seq[Any]] 23 | } 24 | 25 | trait HasHarnessSignalReferences { 26 | // clock/reset of the chiptop reference clock (can be different than the implicit harness clock/reset) 27 | def buildtopClock: Clock 28 | def buildtopReset: Reset 29 | def dutReset: Reset 30 | def success: Bool 31 | } 32 | 33 | class HarnessClockInstantiator { 34 | private val _clockMap: LinkedHashMap[String, (Double, ClockBundle)] = LinkedHashMap.empty 35 | 36 | // request a clock bundle at a particular frequency 37 | def requestClockBundle(name: String, freqRequested: Double): ClockBundle = { 38 | val clockBundle = Wire(new ClockBundle(ClockBundleParameters())) 39 | _clockMap(name) = (freqRequested, clockBundle) 40 | clockBundle 41 | } 42 | 43 | // connect all clock wires specified to a divider only PLL 44 | def instantiateHarnessDividerPLL(refClock: ClockBundle): Unit = { 45 | val sinks = _clockMap.map({ case (name, (freq, bundle)) => 46 | ClockSinkParameters(take=Some(ClockParameters(freqMHz=freq / (1000 * 1000))), name=Some(name)) 47 | }).toSeq 48 | 49 | val pllConfig = new SimplePllConfiguration("harnessDividerOnlyClockGenerator", sinks) 50 | pllConfig.emitSummaries() 51 | 52 | val dividedClocks = LinkedHashMap[Int, Clock]() 53 | def instantiateDivider(div: Int): Clock = { 54 | val divider = Module(new ClockDividerN(div)) 55 | divider.suggestName(s"ClockDivideBy${div}") 56 | divider.io.clk_in := refClock.clock 57 | dividedClocks(div) = divider.io.clk_out 58 | divider.io.clk_out 59 | } 60 | 61 | // connect wires to clock source 62 | for (sinkParams <- sinks) { 63 | // bypass the reference freq. (don't create a divider + reset sync) 64 | val (divClock, divReset) = if (sinkParams.take.get.freqMHz != pllConfig.referenceFreqMHz) { 65 | val div = pllConfig.sinkDividerMap(sinkParams) 66 | val divClock = dividedClocks.getOrElse(div, instantiateDivider(div)) 67 | (divClock, ResetCatchAndSync(divClock, refClock.reset.asBool)) 68 | } else { 69 | (refClock.clock, refClock.reset) 70 | } 71 | 72 | _clockMap(sinkParams.name.get)._2.clock := divClock 73 | _clockMap(sinkParams.name.get)._2.reset := divReset 74 | } 75 | } 76 | } 77 | 78 | case object HarnessClockInstantiatorKey extends Field[HarnessClockInstantiator](new HarnessClockInstantiator) 79 | 80 | class TestHarness(implicit val p: Parameters) extends Module with HasHarnessSignalReferences { 81 | val io = IO(new Bundle { 82 | val success = Output(Bool()) 83 | }) 84 | 85 | val buildtopClock = Wire(Clock()) 86 | val buildtopReset = Wire(Reset()) 87 | 88 | val lazyDut = LazyModule(p(BuildTop)(p)).suggestName("chiptop") 89 | val dut = Module(lazyDut.module) 90 | 91 | io.success := false.B 92 | 93 | val freqMHz = lazyDut match { 94 | case d: HasReferenceClockFreq => d.refClockFreqMHz 95 | case _ => p(DefaultClockFrequencyKey) 96 | } 97 | val refClkBundle = p(HarnessClockInstantiatorKey).requestClockBundle("buildtop_reference_clock", freqMHz * (1000 * 1000)) 98 | 99 | buildtopClock := refClkBundle.clock 100 | buildtopReset := WireInit(refClkBundle.reset) 101 | val dutReset = refClkBundle.reset.asAsyncReset 102 | 103 | val success = io.success 104 | 105 | lazyDut match { case d: HasTestHarnessFunctions => 106 | d.harnessFunctions.foreach(_(this)) 107 | } 108 | lazyDut match { case d: HasIOBinders => 109 | ApplyHarnessBinders(this, d.lazySystem, d.portMap) 110 | } 111 | 112 | val implicitHarnessClockBundle = Wire(new ClockBundle(ClockBundleParameters())) 113 | implicitHarnessClockBundle.clock := clock 114 | implicitHarnessClockBundle.reset := reset 115 | p(HarnessClockInstantiatorKey).instantiateHarnessDividerPLL(implicitHarnessClockBundle) 116 | } 117 | 118 | -------------------------------------------------------------------------------- /scripts/blackbox_resolver.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | ''' 4 | A FIRRTL 'BlackBoxResourceAnno' resolver. 5 | ''' 6 | 7 | import json 8 | from typing import Dict, List, TextIO, Set, Optional 9 | from dataclasses import dataclass 10 | from os import walk, path 11 | from shutil import copyfile 12 | import argparse 13 | 14 | 15 | @dataclass(frozen=True) 16 | class ResourceInfo: 17 | ''' 18 | Resource information. 19 | ''' 20 | 21 | project: Optional[str] 22 | src_type: str 23 | path: str 24 | 25 | def __str__(self) -> str: 26 | p = f'{self.src_type}:{self.path}' 27 | return f'{self.project}:{p}' if self.project else p 28 | 29 | def __repr__(self) -> str: 30 | return self.__str__() 31 | 32 | 33 | ''' 34 | Resource directories. 35 | ''' 36 | ResourceDirs = Dict[str, List[str]] 37 | 38 | 39 | def get_resources(f: TextIO) -> Set[str]: 40 | ''' 41 | Gets the set of resource ids from the specific JSON file. 42 | ''' 43 | resources = set() 44 | for i in json.load(f): 45 | if i['class'] == 'firrtl.transforms.BlackBoxResourceAnno': 46 | resources.add(i['resourceId']) 47 | return resources 48 | 49 | 50 | def get_resource_infos(resources: Set[str]) -> List[ResourceInfo]: 51 | ''' 52 | Gets parsed resource information from the specific resource id set. 53 | ''' 54 | results = [] 55 | for res in resources: 56 | if 'csrc' in res: 57 | src_type = 'csrc' 58 | rs = res.split('csrc') 59 | elif 'vsrc' in res: 60 | src_type = 'vsrc' 61 | rs = res.split('vsrc') 62 | else: 63 | raise RuntimeError(f'invalid resource id "{res}"') 64 | project = rs[0].strip('/') 65 | if not project: 66 | project = None 67 | results.append(ResourceInfo(project, src_type, rs[1].lstrip('/'))) 68 | return results 69 | 70 | 71 | def find_resources_dirs(root: str) -> Dict[str, List[str]]: 72 | ''' 73 | Finds resources directories in the specific root directory. 74 | ''' 75 | results = {'csrc': [], 'vsrc': []} 76 | for dir, _, _ in walk(root): 77 | if f'{path.sep}.git' not in dir and f'{path.sep}resources' in dir: 78 | if dir.endswith(f'{path.sep}csrc'): 79 | results['csrc'].append(dir) 80 | elif dir.endswith(f'{path.sep}vsrc'): 81 | results['vsrc'].append(dir) 82 | return results 83 | 84 | 85 | def get_resource_files(infos: List[ResourceInfo], dirs: ResourceDirs) -> Set[str]: 86 | ''' 87 | Gets full paths of all resources. 88 | ''' 89 | results = set() 90 | for info in infos: 91 | # get target directories 92 | targets = dirs[info.src_type] 93 | if info.project: 94 | targets = list(filter(lambda d: info.project in d, targets)) 95 | if not len(targets): 96 | raise RuntimeError(f'no target directory found for resource "{info}"') 97 | # find in target directories 98 | found = False 99 | for t in targets: 100 | file = path.realpath(path.join(t, info.path)) 101 | if path.exists(file): 102 | if found: 103 | raise RuntimeError( 104 | f'found multiple target files for resource "{info}"') 105 | if file in results: 106 | raise RuntimeError( 107 | f'found multiple resources corresponding to file "{file}"') 108 | results.add(file) 109 | found = True 110 | if not found: 111 | raise RuntimeError(f'target file not found for resource "{info}"') 112 | return results 113 | 114 | 115 | def copy_to_cur_dir(files: Set[str], cur_dir: str) -> Set[str]: 116 | ''' 117 | Copies the specific files to the current directory. 118 | 119 | Returns paths to copied files. 120 | ''' 121 | results = set() 122 | for file in files: 123 | copied = path.realpath(path.join(cur_dir, path.basename(file))) 124 | copyfile(file, copied) 125 | results.add(copied) 126 | return results 127 | 128 | 129 | if __name__ == '__main__': 130 | # initialize argument parser 131 | parser = argparse.ArgumentParser( 132 | description='A FIRRTL `BlackBoxResourceAnno` resolver.') 133 | parser.add_argument('anno', metavar='ANNO', 134 | help='the input FIRRTL annotation file') 135 | parser.add_argument('-r', '--root', default=path.curdir, type=str, 136 | help='the root directory of the Scala project') 137 | parser.add_argument('-c', '--copy', default='', type=str, 138 | help='copies collected resource files to a specific directory') 139 | parser.add_argument('-f', '--dotf', default='', type=str, 140 | help='the output dot f file (default to stdout)') 141 | 142 | # parse arguments 143 | args = parser.parse_args() 144 | 145 | # collect resource files 146 | with open(args.anno) as f: 147 | infos = get_resource_infos(get_resources(f)) 148 | dirs = find_resources_dirs(args.root) 149 | files = get_resource_files(infos, dirs) 150 | if args.copy: 151 | files = copy_to_cur_dir(files, args.copy) 152 | 153 | # generate dot f file 154 | dotf = '\n'.join(files) 155 | if args.dotf: 156 | with open(args.dotf, 'w') as f: 157 | f.write(dotf + '\n') 158 | else: 159 | print(dotf) 160 | -------------------------------------------------------------------------------- /generators/chipyard/src/main/scala/Clocks.scala: -------------------------------------------------------------------------------- 1 | package chipyard 2 | 3 | import chisel3._ 4 | 5 | import scala.collection.mutable.{ArrayBuffer} 6 | 7 | import freechips.rocketchip.prci._ 8 | import freechips.rocketchip.subsystem.{BaseSubsystem, SubsystemDriveAsyncClockGroupsKey, InstantiatesTiles} 9 | import freechips.rocketchip.config.{Parameters, Field, Config} 10 | import freechips.rocketchip.diplomacy.{ModuleValue, OutwardNodeHandle, InModuleBody, LazyModule} 11 | import freechips.rocketchip.util.{ResetCatchAndSync} 12 | 13 | import barstools.iocell.chisel._ 14 | import testchipip.{TLTileResetCtrl} 15 | 16 | import chipyard.clocking._ 17 | import chipyard.iobinders._ 18 | 19 | /** 20 | * A simple reset implementation that punches out reset ports 21 | * for standard Module classes. The ChipTop reset pin is Async. 22 | * Synchronization is performed in the ClockGroupResetSynchronizer 23 | */ 24 | object GenerateReset { 25 | def apply(chiptop: ChipTop, clock: Clock): Reset = { 26 | implicit val p = chiptop.p 27 | // this needs directionality so generateIOFromSignal works 28 | val async_reset_wire = Wire(Input(AsyncReset())) 29 | val (reset_io, resetIOCell) = IOCell.generateIOFromSignal(async_reset_wire, "reset", p(IOCellKey), 30 | abstractResetAsAsync = true) 31 | 32 | chiptop.iocells ++= resetIOCell 33 | chiptop.harnessFunctions += ((th: HasHarnessSignalReferences) => { 34 | reset_io := th.dutReset 35 | Nil 36 | }) 37 | async_reset_wire 38 | } 39 | } 40 | 41 | 42 | case object ClockingSchemeKey extends Field[ChipTop => ModuleValue[Double]](ClockingSchemeGenerators.dividerOnlyClockGenerator) 43 | /* 44 | * This is a Seq of assignment functions, that accept a clock name and return an optional frequency. 45 | * Functions that appear later in this seq have higher precedence that earlier ones. 46 | * If no function returns a non-empty value, the value specified in 47 | * [[DefaultClockFrequencyKey]] will be used. 48 | */ 49 | case object ClockFrequencyAssignersKey extends Field[Seq[(String) => Option[Double]]](Seq.empty) 50 | case object DefaultClockFrequencyKey extends Field[Double]() 51 | 52 | class ClockNameMatchesAssignment(name: String, fMHz: Double) extends Config((site, here, up) => { 53 | case ClockFrequencyAssignersKey => up(ClockFrequencyAssignersKey, site) ++ 54 | Seq((cName: String) => if (cName == name) Some(fMHz) else None) 55 | }) 56 | 57 | class ClockNameContainsAssignment(name: String, fMHz: Double) extends Config((site, here, up) => { 58 | case ClockFrequencyAssignersKey => up(ClockFrequencyAssignersKey, site) ++ 59 | Seq((cName: String) => if (cName.contains(name)) Some(fMHz) else None) 60 | }) 61 | 62 | object ClockingSchemeGenerators { 63 | val dividerOnlyClockGenerator: ChipTop => ModuleValue[Double] = { chiptop => 64 | implicit val p = chiptop.p 65 | 66 | // Requires existence of undriven asyncClockGroups in subsystem 67 | val systemAsyncClockGroup = chiptop.lazySystem match { 68 | case l: BaseSubsystem if (p(SubsystemDriveAsyncClockGroupsKey).isEmpty) => 69 | l.asyncClockGroupsNode 70 | } 71 | 72 | // Add a control register for each tile's reset 73 | val resetSetter = chiptop.lazySystem match { 74 | case sys: BaseSubsystem with InstantiatesTiles => Some(TLTileResetCtrl(sys)) 75 | case _ => None 76 | } 77 | val resetSetterResetProvider = resetSetter.map(_.tileResetProviderNode).getOrElse(ClockGroupEphemeralNode()) 78 | 79 | val aggregator = LazyModule(new ClockGroupAggregator("allClocks")).node 80 | // provides the implicit clock to the system 81 | (chiptop.implicitClockSinkNode 82 | := ClockGroup() 83 | := aggregator) 84 | // provides the system clock (ex. the bus clocks) 85 | (systemAsyncClockGroup 86 | :*= ClockGroupNamePrefixer() 87 | :*= aggregator) 88 | 89 | val referenceClockSource = ClockSourceNode(Seq(ClockSourceParameters())) 90 | val dividerOnlyClkGenerator = LazyModule(new DividerOnlyClockGenerator("buildTopClockGenerator")) 91 | // provides all the divided clocks (from the top-level clock) 92 | (aggregator 93 | := ClockGroupFrequencySpecifier(p(ClockFrequencyAssignersKey), p(DefaultClockFrequencyKey)) 94 | := ClockGroupResetSynchronizer() 95 | := resetSetterResetProvider 96 | := dividerOnlyClkGenerator.node 97 | := referenceClockSource) 98 | 99 | val asyncResetBroadcast = FixedClockBroadcast(None) 100 | resetSetter.foreach(_.asyncResetSinkNode := asyncResetBroadcast) 101 | val asyncResetSource = ClockSourceNode(Seq(ClockSourceParameters())) 102 | asyncResetBroadcast := asyncResetSource 103 | 104 | InModuleBody { 105 | val clock_wire = Wire(Input(Clock())) 106 | val reset_wire = GenerateReset(chiptop, clock_wire) 107 | val (clock_io, clockIOCell) = IOCell.generateIOFromSignal(clock_wire, "clock", p(IOCellKey)) 108 | chiptop.iocells ++= clockIOCell 109 | 110 | referenceClockSource.out.unzip._1.map { o => 111 | o.clock := clock_wire 112 | o.reset := reset_wire 113 | } 114 | 115 | asyncResetSource.out.unzip._1.map { o => 116 | o.clock := false.B.asClock // async reset broadcast network does not provide a clock 117 | o.reset := reset_wire 118 | } 119 | 120 | chiptop.harnessFunctions += ((th: HasHarnessSignalReferences) => { 121 | clock_io := th.buildtopClock 122 | Nil }) 123 | 124 | // return the reference frequency 125 | dividerOnlyClkGenerator.module.referenceFreq 126 | } 127 | } 128 | } 129 | -------------------------------------------------------------------------------- /generators/chipyard/src/main/scala/clocking/DividerOnlyClockGenerator.scala: -------------------------------------------------------------------------------- 1 | package chipyard.clocking 2 | 3 | import chisel3._ 4 | 5 | import freechips.rocketchip.config.{Parameters} 6 | import freechips.rocketchip.diplomacy._ 7 | import freechips.rocketchip.prci._ 8 | import freechips.rocketchip.util.ElaborationArtefacts 9 | 10 | import scala.collection.mutable 11 | import scala.collection.immutable.ListMap 12 | 13 | /** 14 | * TODO: figure out how much division is acceptable in our simulators and redefine this. 15 | */ 16 | object FrequencyUtils { 17 | /** 18 | * Adds up the squared error between the generated clocks (refClock / [integer] divider) 19 | * and the requested frequencies. 20 | * 21 | * @param refMHz The candidate reference clock 22 | * @param desiredFreqMHz A list of the requested output frequencies 23 | */ 24 | def squaredError(refMHz: Double, desiredFreqMHz: List[Double], sum: Double = 0.0): Double = desiredFreqMHz match { 25 | case Nil => sum 26 | case desired :: xs => 27 | val divider = Math.round(refMHz / desired) 28 | val termError = ((refMHz / divider) - desired) / desired 29 | squaredError(refMHz, xs, sum + termError * termError) 30 | } 31 | 32 | /** 33 | * Picks a candidate reference frequency by doing a brute-force search over 34 | * multiples of the fastest requested clock. Choose the smallest multiple that 35 | * has an RMS error (across all output frequencies) that is: 36 | * 1) zero or failing that, 37 | * 2) is within the relativeThreshold of the best or is less than the absoluteThreshold 38 | * 39 | * @param requestedOutputs The desired output frequencies in MHz 40 | * @param maximumAllowableFreqMHz The maximum allowable reference in MHz 41 | * @param relativeThreshold See above 42 | * @param absoluteThreshold See above 43 | */ 44 | def computeReferenceAsMultipleOfFastestClock( 45 | requestedOutputs: Seq[ClockParameters], 46 | maximumAllowableFreqMHz: Double, 47 | relativeThreshold: Double = 1.10, 48 | absoluteThreshold: Double = 0.01): ClockParameters = { 49 | 50 | require(requestedOutputs.nonEmpty) 51 | require(!requestedOutputs.contains(0.0)) 52 | val requestedFreqs = requestedOutputs.map(_.freqMHz) 53 | val fastestFreq = requestedFreqs.max 54 | require(fastestFreq <= maximumAllowableFreqMHz) 55 | 56 | val candidateFreqs = 57 | Seq.tabulate(Math.ceil(maximumAllowableFreqMHz / fastestFreq).toInt)(i => (i + 1) * fastestFreq) 58 | val errorTuples = candidateFreqs.map { f => 59 | f -> Math.sqrt(squaredError(f, requestedFreqs.toList) / requestedFreqs.size) 60 | } 61 | val minError = errorTuples.map(_._2).min 62 | val viableFreqs = errorTuples.collect { 63 | case (f, error) if (error <= minError * relativeThreshold) || (minError > 0 && error < absoluteThreshold) => f 64 | } 65 | ClockParameters(viableFreqs.min) 66 | } 67 | } 68 | 69 | class SimplePllConfiguration( 70 | name: String, 71 | val sinks: Seq[ClockSinkParameters], 72 | maximumAllowableFreqMHz: Double = 16000.0 ) { 73 | val referenceFreqMHz = FrequencyUtils.computeReferenceAsMultipleOfFastestClock( 74 | sinks.flatMap(_.take), 75 | maximumAllowableFreqMHz).freqMHz 76 | val sinkDividerMap = ListMap((sinks.map({s => (s, Math.round(referenceFreqMHz / s.take.get.freqMHz).toInt) })):_*) 77 | 78 | private val preamble = s""" 79 | |${name} Frequency Summary 80 | | Input Reference Frequency: ${referenceFreqMHz} MHz\n""".stripMargin 81 | private val outputSummaries = sinkDividerMap.map { case (sink, division) => 82 | val requested = sink.take.get.freqMHz 83 | val actual = referenceFreqMHz / division.toDouble 84 | s" Output clock ${sink.name.get}, requested: ${requested} MHz, actual: ${actual} MHz (division of ${division})" 85 | } 86 | 87 | val summaryString = preamble + outputSummaries.mkString("\n") 88 | def emitSummaries(): Unit = { 89 | ElaborationArtefacts.add(s"${name}.freq-summary", summaryString) 90 | println(summaryString) 91 | } 92 | def referenceSinkParams(): ClockSinkParameters = sinkDividerMap.find(_._2 == 1).get._1 93 | } 94 | 95 | case class DividerOnlyClockGeneratorNode(pllName: String)(implicit valName: ValName) 96 | extends MixedNexusNode(ClockImp, ClockGroupImp)( 97 | dFn = { _ => ClockGroupSourceParameters() }, 98 | uFn = { u => 99 | require(u.size == 1) 100 | require(!u.head.members.contains(None), 101 | "All output clocks in group must set their take parameters. Use a ClockGroupDealiaser") 102 | ClockSinkParameters( 103 | name = Some(s"${pllName}_reference_input"), 104 | take = Some(ClockParameters(new SimplePllConfiguration(pllName, u.head.members).referenceFreqMHz))) } 105 | ) 106 | 107 | /** 108 | * Generates a digital-divider-only PLL model that verilator can simulate. 109 | * Inspects all take-specified frequencies in the output ClockGroup, calculates a 110 | * fast reference clock (roughly LCM(requested frequencies)) which is passed up the 111 | * diplomatic graph, and then generates dividers for each unique requested 112 | * frequency. 113 | * 114 | * Output resets are not synchronized to generated clocks and should be 115 | * synchronized by the user in a manner they see fit. 116 | * 117 | */ 118 | 119 | class DividerOnlyClockGenerator(pllName: String)(implicit p: Parameters, valName: ValName) extends LazyModule { 120 | val node = DividerOnlyClockGeneratorNode(pllName) 121 | 122 | lazy val module = new LazyRawModuleImp(this) { 123 | require(node.out.size == 1, "Idealized PLL expects to generate a single output clock group. Use a ClockGroupAggregator") 124 | val (refClock, ClockEdgeParameters(_, refSinkParam, _, _)) = node.in.head 125 | val (outClocks, ClockGroupEdgeParameters(_, outSinkParams, _, _)) = node.out.head 126 | 127 | val referenceFreq = refSinkParam.take.get.freqMHz 128 | val pllConfig = new SimplePllConfiguration(pllName, outSinkParams.members) 129 | pllConfig.emitSummaries() 130 | 131 | val dividedClocks = mutable.HashMap[Int, Clock]() 132 | def instantiateDivider(div: Int): Clock = { 133 | val divider = Module(new ClockDividerN(div)) 134 | divider.suggestName(s"ClockDivideBy${div}") 135 | divider.io.clk_in := refClock.clock 136 | dividedClocks(div) = divider.io.clk_out 137 | divider.io.clk_out 138 | } 139 | 140 | for (((sinkBName, sinkB), sinkP) <- outClocks.member.elements.zip(outSinkParams.members)) { 141 | val div = pllConfig.sinkDividerMap(sinkP) 142 | sinkB.clock := dividedClocks.getOrElse(div, instantiateDivider(div)) 143 | // Reset handling and synchronization is expected to be handled by a downstream node 144 | sinkB.reset := refClock.reset 145 | } 146 | } 147 | } 148 | -------------------------------------------------------------------------------- /sims/verilator/Makefile: -------------------------------------------------------------------------------- 1 | ################################################################################ 2 | # Global settings 3 | ################################################################################ 4 | 5 | # Parameters 6 | CONFIG ?= SmallBoomConfig 7 | FRENDA_THREADS ?= $(shell nproc) 8 | FRENDA_CLEAN_BUILD ?= 0 9 | VERILATOR_THREADS ?= 1 10 | VERILATOR_FST_MODE ?= 0 11 | TOP_MODULE ?= TestHarness 12 | CIRCUIT_NAME := $(TOP_MODULE).$(CONFIG) 13 | 14 | # Directories 15 | TOP_DIR := $(shell pwd) 16 | BUILD_DIR := $(TOP_DIR)/build/$(CIRCUIT_NAME) 17 | 18 | # Targets 19 | SIM := $(TOP_DIR)/simulator-$(CONFIG) 20 | SIM_DEBUG := $(TOP_DIR)/simulator-$(CONFIG)-debug 21 | 22 | include $(TOP_DIR)/../tools.mk 23 | 24 | .PHONY: default debug clean 25 | default: $(SIM) 26 | debug: $(SIM_DEBUG) 27 | clean: 28 | -rm -rf $(BUILD_DIR) $(SIM) $(SIM_DEBUG) 29 | 30 | 31 | ################################################################################ 32 | # riscv-isa-sim (fesvr) 33 | ################################################################################ 34 | 35 | # Directories 36 | ISA_SIM_DIR := $(BOSSA_DIR)/toolchains/riscv-isa-sim 37 | ISA_SIM_BUILD_DIR := $(ISA_SIM_DIR)/build 38 | ISA_SIM_INSTALL_DIR := $(BOSSA_DIR)/toolchain-install/riscv-isa-sim 39 | 40 | # Targets 41 | ISA_SIM_LIBFESVR := $(ISA_SIM_INSTALL_DIR)/lib/libfesvr.a 42 | 43 | $(ISA_SIM_LIBFESVR): 44 | mkdir -p $(ISA_SIM_BUILD_DIR) 45 | cd $(ISA_SIM_BUILD_DIR) && $(ISA_SIM_DIR)/configure --prefix=$(ISA_SIM_INSTALL_DIR) 46 | $(MAKE) -C $(ISA_SIM_BUILD_DIR) install 47 | rm -rf $(ISA_SIM_BUILD_DIR) 48 | 49 | 50 | ################################################################################ 51 | # Frenda 52 | ################################################################################ 53 | 54 | # Directories 55 | FRENDA_DIR := $(BOSSA_DIR)/tools/frenda 56 | 57 | # Targets 58 | FRENDA := $(FRENDA_DIR)/utils/bin/frenda 59 | FRENDA_JAR := $(FRENDA).jar 60 | 61 | $(FRENDA_JAR): 62 | cd $(FRENDA_DIR) && $(SBT) "assembly" 63 | 64 | 65 | ################################################################################ 66 | # FIRRTL circuit elaboration 67 | ################################################################################ 68 | 69 | # Directories 70 | BOOTROM_DIR := $(BOSSA_DIR)/generators/testchipip/bootrom 71 | 72 | # Files 73 | SCALA_SRCS := $(shell find $(BOSSA_DIR) -name "*.scala") 74 | BOOTROM_FILES := $(BOOTROM_DIR)/bootrom.rv64.img $(BOOTROM_DIR)/bootrom.rv32.img 75 | 76 | # Targets 77 | BOOTROM_TARGETS := $(BUILD_DIR)/bootrom.rv64.img $(BUILD_DIR)/bootrom.rv32.img 78 | FIR_CIRCUIT := $(BUILD_DIR)/$(CIRCUIT_NAME).fir 79 | FIR_ANNO := $(BUILD_DIR)/$(CIRCUIT_NAME).anno.json 80 | 81 | $(FIR_CIRCUIT): $(SCALA_SRCS) $(BOOTROM_TARGETS) 82 | mkdir -p $(dir $@) 83 | $(SBT_BOSSA) "project chipyard; runMain chipyard.Generator --target-dir $(BUILD_DIR) --name $(CIRCUIT_NAME) --top-module chipyard.$(TOP_MODULE) --legacy-configs chipyard:$(CONFIG)" 84 | 85 | $(FIR_ANNO): $(FIR_CIRCUIT) 86 | 87 | $(BUILD_DIR)/bootrom.%.img: $(BOOTROM_DIR)/bootrom.%.img 88 | mkdir -p $(dir $@) 89 | cp -f $^ $@ 90 | 91 | 92 | ################################################################################ 93 | # FIRRTL circuit compilation 94 | ################################################################################ 95 | 96 | # Flags 97 | FRENDA_FLAGS := $(if $(filter $(FRENDA_CLEAN_BUILD),0),,-cb) 98 | 99 | # Directories 100 | VERILOG_DIR := $(BUILD_DIR)/verilog 101 | 102 | # Targets 103 | VERILOG_FILES := $(BUILD_DIR)/verilog_files.f 104 | 105 | $(VERILOG_FILES): $(FIR_CIRCUIT) $(FRENDA_JAR) 106 | mkdir -p $(dir $@) 107 | $(FRENDA) $(FRENDA_FLAGS) -i $(FIR_CIRCUIT) -j $(FRENDA_THREADS) -td $(VERILOG_DIR) -off $(VERILOG_FILES) 108 | 109 | 110 | ################################################################################ 111 | # Dot f files generation 112 | ################################################################################ 113 | 114 | # Directories 115 | ROCKET_RES_DIR := $(BOSSA_DIR)/generators/rocket-chip/src/main/resources 116 | CHIPYARD_RES_DIR := $(BOSSA_DIR)/generators/chipyard/src/main/resources 117 | TESTCHIP_RES_DIR := $(BOSSA_DIR)/generators/testchipip/src/main/resources 118 | 119 | # Files 120 | SIM_FILE_REQS := \ 121 | $(ROCKET_RES_DIR)/vsrc/EICG_wrapper.v \ 122 | $(CHIPYARD_RES_DIR)/csrc/emulator.cc \ 123 | $(ROCKET_RES_DIR)/csrc/verilator.h \ 124 | $(TESTCHIP_RES_DIR)/testchipip/csrc/SimSerial.cc \ 125 | $(TESTCHIP_RES_DIR)/testchipip/csrc/testchip_tsi.cc \ 126 | $(TESTCHIP_RES_DIR)/testchipip/csrc/testchip_tsi.h \ 127 | $(TESTCHIP_RES_DIR)/testchipip/csrc/SimDRAM.cc \ 128 | $(TESTCHIP_RES_DIR)/testchipip/csrc/mm.h \ 129 | $(TESTCHIP_RES_DIR)/testchipip/csrc/mm.cc \ 130 | $(TESTCHIP_RES_DIR)/testchipip/csrc/mm_dramsim2.h \ 131 | $(TESTCHIP_RES_DIR)/testchipip/csrc/mm_dramsim2.cc \ 132 | $(ROCKET_RES_DIR)/csrc/SimDTM.cc \ 133 | $(ROCKET_RES_DIR)/csrc/SimJTAG.cc \ 134 | $(ROCKET_RES_DIR)/csrc/remote_bitbang.h \ 135 | $(ROCKET_RES_DIR)/csrc/remote_bitbang.cc 136 | 137 | # Targets 138 | SIM_FILES := $(BUILD_DIR)/sim_files.f 139 | BLACKBOX_FILES := $(BUILD_DIR)/blackbox_files.f 140 | SIM_COMMON_FILES := $(BUILD_DIR)/sim_files.common.f 141 | 142 | $(SIM_COMMON_FILES): $(SIM_FILES) $(BLACKBOX_FILES) 143 | awk '{print $1;}' $^ | sort -u | grep -v '.*\.\(svh\|h\)$$' > $@ 144 | 145 | $(SIM_FILES): $(SIM_FILE_REQS) 146 | mkdir -p $(dir $@) 147 | cp -f $^ $(BUILD_DIR) 148 | $(foreach file,\ 149 | $^,\ 150 | $(if $(filter %.h,$(file)),\ 151 | echo "-FI $(addprefix $(BUILD_DIR)/, $(notdir $(file)))" >> $@;,\ 152 | echo "$(addprefix $(BUILD_DIR)/, $(notdir $(file)))" >> $@;)) 153 | 154 | $(BLACKBOX_FILES): $(FIR_ANNO) 155 | mkdir -p $(dir $@) 156 | $(BLACKBOX_RESOLVER) $^ -c $(BUILD_DIR) -f $@ 157 | 158 | 159 | ################################################################################ 160 | # Verilator 161 | ################################################################################ 162 | 163 | include $(TOP_DIR)/verilator.mk 164 | 165 | # Directories 166 | MODEL_DIR := $(BUILD_DIR)/model 167 | MODEL_DEBUG_DIR := $(BUILD_DIR)/model.debug 168 | 169 | # Files 170 | MODEL_HEADER = $(MODEL_DIR)/V$(TOP_MODULE).h 171 | MODEL_DEBUG_HEADER = $(MODEL_DEBUG_DIR)/V$(TOP_MODULE).h 172 | 173 | # Targets 174 | MODEL_MK := $(MODEL_DIR)/V$(TOP_MODULE).mk 175 | MODEL_DEBUG_MK := $(MODEL_DEBUG_DIR)/V$(TOP_MODULE).mk 176 | 177 | $(MODEL_MK): $(SIM_COMMON_FILES) $(VERILOG_FILES) 178 | verilator --cc --exe $(VERILATOR_OPTS) -o $(SIM) -Mdir $(MODEL_DIR) -CFLAGS "-include $(MODEL_HEADER)" 179 | 180 | $(MODEL_DEBUG_MK): $(SIM_COMMON_FILES) $(VERILOG_FILES) 181 | verilator --cc --exe $(VERILATOR_OPTS) -o $(SIM_DEBUG) $(TRACING_OPTS) -Mdir $(MODEL_DEBUG_DIR) -CFLAGS "-include $(MODEL_DEBUG_HEADER)" 182 | 183 | 184 | ################################################################################ 185 | # DRAMSim library 186 | ################################################################################ 187 | 188 | # Directories 189 | DRAMSIM_DIR = $(BOSSA_DIR)/tools/DRAMSim2 190 | 191 | # Targets 192 | DRAMSIM_LIB = $(DRAMSIM_DIR)/libdramsim.a 193 | 194 | $(DRAMSIM_LIB): 195 | $(MAKE) -C $(DRAMSIM_DIR) $(notdir $@) 196 | 197 | 198 | ################################################################################ 199 | # Simulator targets 200 | ################################################################################ 201 | 202 | $(SIM): $(MODEL_MK) $(DRAMSIM_LIB) $(ISA_SIM_LIBFESVR) 203 | $(MAKE) VM_PARALLEL_BUILDS=1 OPT_FAST="-O3" -C $(MODEL_DIR) -f V$(TOP_MODULE).mk 204 | 205 | $(SIM_DEBUG): $(MODEL_DEBUG_MK) $(DRAMSIM_LIB) $(ISA_SIM_LIBFESVR) 206 | $(MAKE) VM_PARALLEL_BUILDS=1 OPT_FAST="-O3" -C $(MODEL_DEBUG_DIR) -f V$(TOP_MODULE).mk 207 | -------------------------------------------------------------------------------- /generators/chipyard/src/main/scala/config/RocketConfigs.scala: -------------------------------------------------------------------------------- 1 | package chipyard 2 | 3 | import freechips.rocketchip.config.{Config} 4 | import freechips.rocketchip.diplomacy.{AsynchronousCrossing} 5 | 6 | // -------------- 7 | // Rocket Configs 8 | // -------------- 9 | 10 | class RocketConfig extends Config( 11 | new freechips.rocketchip.subsystem.WithNBigCores(1) ++ // single rocket-core 12 | new chipyard.config.AbstractConfig) 13 | 14 | class TinyRocketConfig extends Config( 15 | new chipyard.config.WithTLSerialLocation( 16 | freechips.rocketchip.subsystem.FBUS, 17 | freechips.rocketchip.subsystem.PBUS) ++ // attach TL serial adapter to f/p busses 18 | new chipyard.WithMulticlockIncoherentBusTopology ++ // use incoherent bus topology 19 | new freechips.rocketchip.subsystem.WithNBanks(0) ++ // remove L2$ 20 | new freechips.rocketchip.subsystem.WithNoMemPort ++ // remove backing memory 21 | new freechips.rocketchip.subsystem.With1TinyCore ++ // single tiny rocket-core 22 | new chipyard.config.AbstractConfig) 23 | 24 | 25 | // DOC include start: DmiRocket 26 | class dmiRocketConfig extends Config( 27 | new chipyard.harness.WithSerialAdapterTiedOff ++ // don't attach an external SimSerial 28 | new chipyard.config.WithDMIDTM ++ // have debug module expose a clocked DMI port 29 | new freechips.rocketchip.subsystem.WithNBigCores(1) ++ 30 | new chipyard.config.AbstractConfig) 31 | // DOC include end: DmiRocket 32 | 33 | class LargeSPIFlashROMRocketConfig extends Config( 34 | new chipyard.harness.WithSimSPIFlashModel(true) ++ // add the SPI flash model in the harness (read-only) 35 | new chipyard.config.WithSPIFlash ++ // add the SPI flash controller 36 | new freechips.rocketchip.subsystem.WithNBigCores(1) ++ 37 | new chipyard.config.AbstractConfig) 38 | 39 | class SmallSPIFlashRocketConfig extends Config( 40 | new chipyard.harness.WithSimSPIFlashModel(false) ++ // add the SPI flash model in the harness (writeable) 41 | new chipyard.config.WithSPIFlash(0x100000) ++ // add the SPI flash controller (1 MiB) 42 | new freechips.rocketchip.subsystem.WithNBigCores(1) ++ 43 | new chipyard.config.AbstractConfig) 44 | 45 | class SimAXIRocketConfig extends Config( 46 | new chipyard.harness.WithSimAXIMem ++ // drive the master AXI4 memory with a SimAXIMem, a 1-cycle magic memory, instead of default SimDRAM 47 | new freechips.rocketchip.subsystem.WithNBigCores(1) ++ 48 | new chipyard.config.AbstractConfig) 49 | 50 | class SimBlockDeviceRocketConfig extends Config( 51 | new chipyard.harness.WithSimBlockDevice ++ // drive block-device IOs with SimBlockDevice 52 | new testchipip.WithBlockDevice ++ // add block-device module to peripherybus 53 | new freechips.rocketchip.subsystem.WithNBigCores(1) ++ 54 | new chipyard.config.AbstractConfig) 55 | 56 | class BlockDeviceModelRocketConfig extends Config( 57 | new chipyard.harness.WithBlockDeviceModel ++ // drive block-device IOs with a BlockDeviceModel 58 | new testchipip.WithBlockDevice ++ // add block-device module to periphery bus 59 | new freechips.rocketchip.subsystem.WithNBigCores(1) ++ 60 | new chipyard.config.AbstractConfig) 61 | 62 | // DOC include start: GPIORocketConfig 63 | class GPIORocketConfig extends Config( 64 | new chipyard.config.WithGPIO ++ // add GPIOs to the peripherybus 65 | new freechips.rocketchip.subsystem.WithNBigCores(1) ++ 66 | new chipyard.config.AbstractConfig) 67 | // DOC include end: GPIORocketConfig 68 | 69 | class QuadRocketConfig extends Config( 70 | new freechips.rocketchip.subsystem.WithNBigCores(4) ++ // quad-core (4 RocketTiles) 71 | new chipyard.config.AbstractConfig) 72 | 73 | class RV32RocketConfig extends Config( 74 | new freechips.rocketchip.subsystem.WithRV32 ++ // set RocketTiles to be 32-bit 75 | new freechips.rocketchip.subsystem.WithNBigCores(1) ++ 76 | new chipyard.config.AbstractConfig) 77 | 78 | class GB1MemoryRocketConfig extends Config( 79 | new freechips.rocketchip.subsystem.WithExtMemSize((1<<30) * 1L) ++ // use 1GB simulated external memory 80 | new freechips.rocketchip.subsystem.WithNBigCores(1) ++ 81 | new chipyard.config.AbstractConfig) 82 | 83 | // DOC include start: l1scratchpadrocket 84 | class ScratchpadOnlyRocketConfig extends Config( 85 | new testchipip.WithSerialPBusMem ++ 86 | new freechips.rocketchip.subsystem.WithNMemoryChannels(0) ++ // remove offchip mem port 87 | new freechips.rocketchip.subsystem.WithNBanks(0) ++ 88 | new freechips.rocketchip.subsystem.WithNoMemPort ++ 89 | new freechips.rocketchip.subsystem.WithScratchpadsOnly ++ // use rocket l1 DCache scratchpad as base phys mem 90 | new freechips.rocketchip.subsystem.WithNBigCores(1) ++ 91 | new chipyard.config.AbstractConfig) 92 | // DOC include end: l1scratchpadrocket 93 | 94 | class L1ScratchpadRocketConfig extends Config( 95 | new chipyard.config.WithRocketICacheScratchpad ++ // use rocket ICache scratchpad 96 | new chipyard.config.WithRocketDCacheScratchpad ++ // use rocket DCache scratchpad 97 | new freechips.rocketchip.subsystem.WithNBigCores(1) ++ 98 | new chipyard.config.AbstractConfig) 99 | 100 | // DOC include start: mbusscratchpadrocket 101 | class MbusScratchpadRocketConfig extends Config( 102 | new testchipip.WithBackingScratchpad ++ // add mbus backing scratchpad 103 | new freechips.rocketchip.subsystem.WithNoMemPort ++ // remove offchip mem port 104 | new freechips.rocketchip.subsystem.WithNBigCores(1) ++ 105 | new chipyard.config.AbstractConfig) 106 | // DOC include end: mbusscratchpadrocket 107 | 108 | // DOC include start: RingSystemBusRocket 109 | class RingSystemBusRocketConfig extends Config( 110 | new testchipip.WithRingSystemBus ++ // Ring-topology system bus 111 | new freechips.rocketchip.subsystem.WithNBigCores(1) ++ 112 | new chipyard.config.AbstractConfig) 113 | // DOC include end: RingSystemBusRocket 114 | 115 | class MMIORocketConfig extends Config( 116 | new freechips.rocketchip.subsystem.WithDefaultMMIOPort ++ // add default external master port 117 | new freechips.rocketchip.subsystem.WithDefaultSlavePort ++ // add default external slave port 118 | new freechips.rocketchip.subsystem.WithNBigCores(1) ++ 119 | new chipyard.config.AbstractConfig) 120 | 121 | class MulticlockRocketConfig extends Config( 122 | new freechips.rocketchip.subsystem.WithNBigCores(1) ++ 123 | // Frequency specifications 124 | new chipyard.config.WithTileFrequency(1600.0) ++ // Matches the maximum frequency of U540 125 | new chipyard.config.WithSystemBusFrequency(800.0) ++ // Ditto 126 | new chipyard.config.WithMemoryBusFrequency(1000.0) ++ // 2x the U540 freq (appropriate for a 128b Mbus) 127 | new chipyard.config.WithPeripheryBusFrequency(100) ++ // Retains the default pbus frequency 128 | new chipyard.config.WithSystemBusFrequencyAsDefault ++ // All unspecified clock frequencies, notably the implicit clock, will use the sbus freq (800 MHz) 129 | // Crossing specifications 130 | new chipyard.config.WithCbusToPbusCrossingType(AsynchronousCrossing()) ++ // Add Async crossing between PBUS and CBUS 131 | new chipyard.config.WithSbusToMbusCrossingType(AsynchronousCrossing()) ++ // Add Async crossings between backside of L2 and MBUS 132 | new freechips.rocketchip.subsystem.WithRationalRocketTiles ++ // Add rational crossings between RocketTile and uncore 133 | new testchipip.WithAsynchronousSerialSlaveCrossing ++ // Add Async crossing between serial and MBUS. Its master-side is tied to the FBUS 134 | new chipyard.config.AbstractConfig) 135 | 136 | class TestChipMulticlockRocketConfig extends Config( 137 | new freechips.rocketchip.subsystem.WithNBigCores(1) ++ 138 | new chipyard.config.WithTestChipBusFreqs ++ 139 | new chipyard.config.AbstractConfig) 140 | 141 | class LBWIFRocketConfig extends Config( 142 | new testchipip.WithSerialTLMem(isMainMemory=true) ++ // set lbwif memory base to DRAM_BASE, use as main memory 143 | new freechips.rocketchip.subsystem.WithNoMemPort ++ // remove AXI4 backing memory 144 | new freechips.rocketchip.subsystem.WithNBigCores(1) ++ 145 | new chipyard.config.AbstractConfig) 146 | 147 | // DOC include start: MulticlockAXIOverSerialConfig 148 | class MulticlockAXIOverSerialConfig extends Config( 149 | new chipyard.config.WithSystemBusFrequencyAsDefault ++ 150 | new chipyard.config.WithSystemBusFrequency(250) ++ 151 | new chipyard.config.WithPeripheryBusFrequency(250) ++ 152 | new chipyard.config.WithMemoryBusFrequency(250) ++ 153 | new chipyard.config.WithFrontBusFrequency(50) ++ 154 | new chipyard.config.WithTileFrequency(500, Some(1)) ++ 155 | new chipyard.config.WithTileFrequency(250, Some(0)) ++ 156 | 157 | new chipyard.config.WithFbusToSbusCrossingType(AsynchronousCrossing()) ++ 158 | new testchipip.WithAsynchronousSerialSlaveCrossing ++ 159 | new freechips.rocketchip.subsystem.WithAsynchronousRocketTiles( 160 | AsynchronousCrossing().depth, 161 | AsynchronousCrossing().sourceSync) ++ 162 | 163 | new chipyard.harness.WithSimAXIMemOverSerialTL ++ // add SimDRAM DRAM model for axi4 backing memory over the SerDes link, if axi4 mem is enabled 164 | new chipyard.config.WithSerialTLBackingMemory ++ // remove axi4 mem port in favor of SerialTL memory 165 | 166 | new freechips.rocketchip.subsystem.WithNBigCores(2) ++ 167 | new chipyard.config.AbstractConfig) 168 | // DOC include end: MulticlockAXIOverSerialConfig 169 | -------------------------------------------------------------------------------- /LICENSE.SiFive: -------------------------------------------------------------------------------- 1 | 2 | Apache License 3 | Version 2.0, January 2004 4 | http://www.apache.org/licenses/ 5 | 6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 7 | 8 | 1. Definitions. 9 | 10 | "License" shall mean the terms and conditions for use, reproduction, 11 | and distribution as defined by Sections 1 through 9 of this document. 12 | 13 | "Licensor" shall mean the copyright owner or entity authorized by 14 | the copyright owner that is granting the License. 15 | 16 | "Legal Entity" shall mean the union of the acting entity and all 17 | other entities that control, are controlled by, or are under common 18 | control with that entity. For the purposes of this definition, 19 | "control" means (i) the power, direct or indirect, to cause the 20 | direction or management of such entity, whether by contract or 21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 22 | outstanding shares, or (iii) beneficial ownership of such entity. 23 | 24 | "You" (or "Your") shall mean an individual or Legal Entity 25 | exercising permissions granted by this License. 26 | 27 | "Source" form shall mean the preferred form for making modifications, 28 | including but not limited to software source code, documentation 29 | source, and configuration files. 30 | 31 | "Object" form shall mean any form resulting from mechanical 32 | transformation or translation of a Source form, including but 33 | not limited to compiled object code, generated documentation, 34 | and conversions to other media types. 35 | 36 | "Work" shall mean the work of authorship, whether in Source or 37 | Object form, made available under the License, as indicated by a 38 | copyright notice that is included in or attached to the work 39 | (an example is provided in the Appendix below). 40 | 41 | "Derivative Works" shall mean any work, whether in Source or Object 42 | form, that is based on (or derived from) the Work and for which the 43 | editorial revisions, annotations, elaborations, or other modifications 44 | represent, as a whole, an original work of authorship. For the purposes 45 | of this License, Derivative Works shall not include works that remain 46 | separable from, or merely link (or bind by name) to the interfaces of, 47 | the Work and Derivative Works thereof. 48 | 49 | "Contribution" shall mean any work of authorship, including 50 | the original version of the Work and any modifications or additions 51 | to that Work or Derivative Works thereof, that is intentionally 52 | submitted to Licensor for inclusion in the Work by the copyright owner 53 | or by an individual or Legal Entity authorized to submit on behalf of 54 | the copyright owner. For the purposes of this definition, "submitted" 55 | means any form of electronic, verbal, or written communication sent 56 | to the Licensor or its representatives, including but not limited to 57 | communication on electronic mailing lists, source code control systems, 58 | and issue tracking systems that are managed by, or on behalf of, the 59 | Licensor for the purpose of discussing and improving the Work, but 60 | excluding communication that is conspicuously marked or otherwise 61 | designated in writing by the copyright owner as "Not a Contribution." 62 | 63 | "Contributor" shall mean Licensor and any individual or Legal Entity 64 | on behalf of whom a Contribution has been received by Licensor and 65 | subsequently incorporated within the Work. 66 | 67 | 2. Grant of Copyright License. Subject to the terms and conditions of 68 | this License, each Contributor hereby grants to You a perpetual, 69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 70 | copyright license to reproduce, prepare Derivative Works of, 71 | publicly display, publicly perform, sublicense, and distribute the 72 | Work and such Derivative Works in Source or Object form. 73 | 74 | 3. Grant of Patent License. Subject to the terms and conditions of 75 | this License, each Contributor hereby grants to You a perpetual, 76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 77 | (except as stated in this section) patent license to make, have made, 78 | use, offer to sell, sell, import, and otherwise transfer the Work, 79 | where such license applies only to those patent claims licensable 80 | by such Contributor that are necessarily infringed by their 81 | Contribution(s) alone or by combination of their Contribution(s) 82 | with the Work to which such Contribution(s) was submitted. If You 83 | institute patent litigation against any entity (including a 84 | cross-claim or counterclaim in a lawsuit) alleging that the Work 85 | or a Contribution incorporated within the Work constitutes direct 86 | or contributory patent infringement, then any patent licenses 87 | granted to You under this License for that Work shall terminate 88 | as of the date such litigation is filed. 89 | 90 | 4. Redistribution. You may reproduce and distribute copies of the 91 | Work or Derivative Works thereof in any medium, with or without 92 | modifications, and in Source or Object form, provided that You 93 | meet the following conditions: 94 | 95 | (a) You must give any other recipients of the Work or 96 | Derivative Works a copy of this License; and 97 | 98 | (b) You must cause any modified files to carry prominent notices 99 | stating that You changed the files; and 100 | 101 | (c) You must retain, in the Source form of any Derivative Works 102 | that You distribute, all copyright, patent, trademark, and 103 | attribution notices from the Source form of the Work, 104 | excluding those notices that do not pertain to any part of 105 | the Derivative Works; and 106 | 107 | (d) If the Work includes a "NOTICE" text file as part of its 108 | distribution, then any Derivative Works that You distribute must 109 | include a readable copy of the attribution notices contained 110 | within such NOTICE file, excluding those notices that do not 111 | pertain to any part of the Derivative Works, in at least one 112 | of the following places: within a NOTICE text file distributed 113 | as part of the Derivative Works; within the Source form or 114 | documentation, if provided along with the Derivative Works; or, 115 | within a display generated by the Derivative Works, if and 116 | wherever such third-party notices normally appear. The contents 117 | of the NOTICE file are for informational purposes only and 118 | do not modify the License. You may add Your own attribution 119 | notices within Derivative Works that You distribute, alongside 120 | or as an addendum to the NOTICE text from the Work, provided 121 | that such additional attribution notices cannot be construed 122 | as modifying the License. 123 | 124 | You may add Your own copyright statement to Your modifications and 125 | may provide additional or different license terms and conditions 126 | for use, reproduction, or distribution of Your modifications, or 127 | for any such Derivative Works as a whole, provided Your use, 128 | reproduction, and distribution of the Work otherwise complies with 129 | the conditions stated in this License. 130 | 131 | 5. Submission of Contributions. Unless You explicitly state otherwise, 132 | any Contribution intentionally submitted for inclusion in the Work 133 | by You to the Licensor shall be under the terms and conditions of 134 | this License, without any additional terms or conditions. 135 | Notwithstanding the above, nothing herein shall supersede or modify 136 | the terms of any separate license agreement you may have executed 137 | with Licensor regarding such Contributions. 138 | 139 | 6. Trademarks. This License does not grant permission to use the trade 140 | names, trademarks, service marks, or product names of the Licensor, 141 | except as required for reasonable and customary use in describing the 142 | origin of the Work and reproducing the content of the NOTICE file. 143 | 144 | 7. Disclaimer of Warranty. Unless required by applicable law or 145 | agreed to in writing, Licensor provides the Work (and each 146 | Contributor provides its Contributions) on an "AS IS" BASIS, 147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 148 | implied, including, without limitation, any warranties or conditions 149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 150 | PARTICULAR PURPOSE. You are solely responsible for determining the 151 | appropriateness of using or redistributing the Work and assume any 152 | risks associated with Your exercise of permissions under this License. 153 | 154 | 8. Limitation of Liability. In no event and under no legal theory, 155 | whether in tort (including negligence), contract, or otherwise, 156 | unless required by applicable law (such as deliberate and grossly 157 | negligent acts) or agreed to in writing, shall any Contributor be 158 | liable to You for damages, including any direct, indirect, special, 159 | incidental, or consequential damages of any character arising as a 160 | result of this License or out of the use or inability to use the 161 | Work (including but not limited to damages for loss of goodwill, 162 | work stoppage, computer failure or malfunction, or any and all 163 | other commercial damages or losses), even if such Contributor 164 | has been advised of the possibility of such damages. 165 | 166 | 9. Accepting Warranty or Additional Liability. While redistributing 167 | the Work or Derivative Works thereof, You may choose to offer, 168 | and charge a fee for, acceptance of support, warranty, indemnity, 169 | or other liability obligations and/or rights consistent with this 170 | License. However, in accepting such obligations, You may act only 171 | on Your own behalf and on Your sole responsibility, not on behalf 172 | of any other Contributor, and only if You agree to indemnify, 173 | defend, and hold each Contributor harmless for any liability 174 | incurred by, or claims asserted against, such Contributor by reason 175 | of your accepting any such warranty or additional liability. 176 | 177 | END OF TERMS AND CONDITIONS 178 | 179 | APPENDIX: How to apply the Apache License to your work. 180 | 181 | To apply the Apache License to your work, attach the following 182 | boilerplate notice, with the fields enclosed by brackets "[]" 183 | replaced with your own identifying information. (Don't include 184 | the brackets!) The text should be enclosed in the appropriate 185 | comment syntax for the file format. We also recommend that a 186 | file or class name and description of purpose be included on the 187 | same "printed page" as the copyright notice for easier 188 | identification within third-party archives. 189 | 190 | Copyright 2016-2017 SiFive, Inc. 191 | 192 | Licensed under the Apache License, Version 2.0 (the "License"); 193 | you may not use this file except in compliance with the License. 194 | You may obtain a copy of the License at 195 | 196 | http://www.apache.org/licenses/LICENSE-2.0 197 | 198 | Unless required by applicable law or agreed to in writing, software 199 | distributed under the License is distributed on an "AS IS" BASIS, 200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 201 | See the License for the specific language governing permissions and 202 | limitations under the License. 203 | -------------------------------------------------------------------------------- /generators/chipyard/src/main/scala/ConfigFragments.scala: -------------------------------------------------------------------------------- 1 | package chipyard.config 2 | 3 | import scala.util.matching.Regex 4 | import chisel3._ 5 | import chisel3.util.{log2Up} 6 | 7 | import freechips.rocketchip.config.{Field, Parameters, Config} 8 | import freechips.rocketchip.subsystem._ 9 | import freechips.rocketchip.diplomacy._ 10 | import freechips.rocketchip.devices.tilelink.{BootROMLocated} 11 | import freechips.rocketchip.devices.debug.{Debug, ExportDebug, DebugModuleKey, DMI} 12 | import freechips.rocketchip.groundtest.{GroundTestSubsystem} 13 | import freechips.rocketchip.tile._ 14 | import freechips.rocketchip.rocket.{RocketCoreParams, MulDivParams, DCacheParams, ICacheParams} 15 | import freechips.rocketchip.tilelink.{HasTLBusParams} 16 | import freechips.rocketchip.util.{AsyncResetReg, Symmetric} 17 | import freechips.rocketchip.prci._ 18 | import freechips.rocketchip.stage.phases.TargetDirKey 19 | 20 | import testchipip._ 21 | 22 | import boom.common.{BoomTileAttachParams} 23 | 24 | import sifive.blocks.devices.gpio._ 25 | import sifive.blocks.devices.uart._ 26 | import sifive.blocks.devices.spi._ 27 | 28 | import chipyard._ 29 | 30 | // ----------------------- 31 | // Common Config Fragments 32 | // ----------------------- 33 | 34 | class WithBootROM extends Config((site, here, up) => { 35 | case BootROMLocated(x) => up(BootROMLocated(x), site).map(_.copy(contentFileName = s"${site(TargetDirKey)}/bootrom.rv${site(XLen)}.img")) 36 | }) 37 | 38 | // DOC include start: gpio config fragment 39 | class WithGPIO extends Config((site, here, up) => { 40 | case PeripheryGPIOKey => Seq( 41 | GPIOParams(address = 0x10012000, width = 4, includeIOF = false)) 42 | }) 43 | // DOC include end: gpio config fragment 44 | 45 | class WithUART(baudrate: BigInt = 115200) extends Config((site, here, up) => { 46 | case PeripheryUARTKey => Seq( 47 | UARTParams(address = 0x54000000L, nTxEntries = 256, nRxEntries = 256, initBaudRate = baudrate)) 48 | }) 49 | 50 | class WithSPIFlash(size: BigInt = 0x10000000) extends Config((site, here, up) => { 51 | // Note: the default size matches freedom with the addresses below 52 | case PeripherySPIFlashKey => Seq( 53 | SPIFlashParams(rAddress = 0x10040000, fAddress = 0x20000000, fSize = size)) 54 | }) 55 | 56 | class WithL2TLBs(entries: Int) extends Config((site, here, up) => { 57 | case TilesLocated(InSubsystem) => up(TilesLocated(InSubsystem), site) map { 58 | case tp: RocketTileAttachParams => tp.copy(tileParams = tp.tileParams.copy( 59 | core = tp.tileParams.core.copy(nL2TLBEntries = entries))) 60 | case tp: BoomTileAttachParams => tp.copy(tileParams = tp.tileParams.copy( 61 | core = tp.tileParams.core.copy(nL2TLBEntries = entries))) 62 | case other => other 63 | } 64 | }) 65 | 66 | /** 67 | * Map from a hartId to a particular RoCC accelerator 68 | */ 69 | case object MultiRoCCKey extends Field[Map[Int, Seq[Parameters => LazyRoCC]]](Map.empty[Int, Seq[Parameters => LazyRoCC]]) 70 | 71 | /** 72 | * Config fragment to enable different RoCCs based on the hartId 73 | */ 74 | class WithMultiRoCC extends Config((site, here, up) => { 75 | case BuildRoCC => site(MultiRoCCKey).getOrElse(site(TileKey).hartId, Nil) 76 | }) 77 | 78 | /** 79 | * Assigns what was previously in the BuildRoCC key to specific harts with MultiRoCCKey 80 | * Must be paired with WithMultiRoCC 81 | */ 82 | class WithMultiRoCCFromBuildRoCC(harts: Int*) extends Config((site, here, up) => { 83 | case BuildRoCC => Nil 84 | case MultiRoCCKey => up(MultiRoCCKey, site) ++ harts.distinct.map { i => 85 | (i -> up(BuildRoCC, site)) 86 | } 87 | }) 88 | 89 | class WithTraceIO extends Config((site, here, up) => { 90 | case TilesLocated(InSubsystem) => up(TilesLocated(InSubsystem), site) map { 91 | case tp: BoomTileAttachParams => tp.copy(tileParams = tp.tileParams.copy( 92 | trace = true)) 93 | case other => other 94 | } 95 | case TracePortKey => Some(TracePortParams()) 96 | }) 97 | 98 | class WithNPerfCounters(n: Int = 29) extends Config((site, here, up) => { 99 | case TilesLocated(InSubsystem) => up(TilesLocated(InSubsystem), site) map { 100 | case tp: RocketTileAttachParams => tp.copy(tileParams = tp.tileParams.copy( 101 | core = tp.tileParams.core.copy(nPerfCounters = n))) 102 | case tp: BoomTileAttachParams => tp.copy(tileParams = tp.tileParams.copy( 103 | core = tp.tileParams.core.copy(nPerfCounters = n))) 104 | case other => other 105 | } 106 | }) 107 | 108 | class WithNPMPs(n: Int = 8) extends Config((site, here, up) => { 109 | case TilesLocated(InSubsystem) => up(TilesLocated(InSubsystem), site) map { 110 | case tp: RocketTileAttachParams => tp.copy(tileParams = tp.tileParams.copy( 111 | core = tp.tileParams.core.copy(nPMPs = n))) 112 | case tp: BoomTileAttachParams => tp.copy(tileParams = tp.tileParams.copy( 113 | core = tp.tileParams.core.copy(nPMPs = n))) 114 | case other => other 115 | } 116 | }) 117 | 118 | class WithRocketICacheScratchpad extends Config((site, here, up) => { 119 | case RocketTilesKey => up(RocketTilesKey, site) map { r => 120 | r.copy(icache = r.icache.map(_.copy(itimAddr = Some(0x300000 + r.hartId * 0x10000)))) 121 | } 122 | }) 123 | 124 | class WithRocketDCacheScratchpad extends Config((site, here, up) => { 125 | case RocketTilesKey => up(RocketTilesKey, site) map { r => 126 | r.copy(dcache = r.dcache.map(_.copy(nSets = 32, nWays = 1, scratch = Some(0x200000 + r.hartId * 0x10000)))) 127 | } 128 | }) 129 | 130 | // Replaces the L2 with a broadcast manager for maintaining coherence 131 | class WithBroadcastManager extends Config((site, here, up) => { 132 | case BankedL2Key => up(BankedL2Key, site).copy(coherenceManager = CoherenceManagerWrapper.broadcastManager) 133 | }) 134 | 135 | // The default RocketChip BaseSubsystem drives its diplomatic clock graph 136 | // with the implicit clocks of Subsystem. Don't do that, instead we extend 137 | // the diplomacy graph upwards into the ChipTop, where we connect it to 138 | // our clock drivers 139 | class WithNoSubsystemDrivenClocks extends Config((site, here, up) => { 140 | case SubsystemDriveAsyncClockGroupsKey => None 141 | }) 142 | 143 | class WithDMIDTM extends Config((site, here, up) => { 144 | case ExportDebug => up(ExportDebug, site).copy(protocols = Set(DMI)) 145 | }) 146 | 147 | class WithNoDebug extends Config((site, here, up) => { 148 | case DebugModuleKey => None 149 | }) 150 | 151 | class WithTLSerialLocation(masterWhere: TLBusWrapperLocation, slaveWhere: TLBusWrapperLocation) extends Config((site, here, up) => { 152 | case SerialTLAttachKey => up(SerialTLAttachKey, site).copy(masterWhere = masterWhere, slaveWhere = slaveWhere) 153 | }) 154 | 155 | class WithTLBackingMemory extends Config((site, here, up) => { 156 | case ExtMem => None // disable AXI backing memory 157 | case ExtTLMem => up(ExtMem, site) // enable TL backing memory 158 | }) 159 | 160 | class WithSerialTLBackingMemory extends Config((site, here, up) => { 161 | case ExtMem => None 162 | case SerialTLKey => up(SerialTLKey, site).map { k => k.copy( 163 | memParams = { 164 | val memPortParams = up(ExtMem, site).get 165 | require(memPortParams.nMemoryChannels == 1) 166 | memPortParams.master 167 | }, 168 | isMemoryDevice = true 169 | )} 170 | }) 171 | 172 | /** 173 | * Mixins to define either a specific tile frequency for a single hart or all harts 174 | * 175 | * @param fMHz Frequency in MHz of the tile or all tiles 176 | * @param hartId Optional hartid to assign the frequency to (if unspecified default to all harts) 177 | */ 178 | class WithTileFrequency(fMHz: Double, hartId: Option[Int] = None) extends ClockNameContainsAssignment({ 179 | hartId match { 180 | case Some(id) => s"tile_$id" 181 | case None => "tile" 182 | } 183 | }, 184 | fMHz) 185 | 186 | class WithPeripheryBusFrequencyAsDefault extends Config((site, here, up) => { 187 | case DefaultClockFrequencyKey => (site(PeripheryBusKey).dtsFrequency.get / (1000 * 1000)).toDouble 188 | }) 189 | 190 | class WithSystemBusFrequencyAsDefault extends Config((site, here, up) => { 191 | case DefaultClockFrequencyKey => (site(SystemBusKey).dtsFrequency.get / (1000 * 1000)).toDouble 192 | }) 193 | 194 | class BusFrequencyAssignment[T <: HasTLBusParams](re: Regex, key: Field[T]) extends Config((site, here, up) => { 195 | case ClockFrequencyAssignersKey => up(ClockFrequencyAssignersKey, site) ++ 196 | Seq((cName: String) => site(key).dtsFrequency.flatMap { f => 197 | re.findFirstIn(cName).map {_ => (f / (1000 * 1000)).toDouble } 198 | }) 199 | }) 200 | 201 | /** 202 | * Provides a diplomatic frequency for all clock sinks with an unspecified 203 | * frequency bound to each bus. 204 | * 205 | * For example, the L2 cache, when bound to the sbus, receives a separate 206 | * clock that appears as "subsystem_sbus_". This fragment ensures that 207 | * clock requests the same frequency as the sbus itself. 208 | */ 209 | 210 | class WithInheritBusFrequencyAssignments extends Config( 211 | new BusFrequencyAssignment("subsystem_sbus_\\d+".r, SystemBusKey) ++ 212 | new BusFrequencyAssignment("subsystem_pbus_\\d+".r, PeripheryBusKey) ++ 213 | new BusFrequencyAssignment("subsystem_cbus_\\d+".r, ControlBusKey) ++ 214 | new BusFrequencyAssignment("subsystem_fbus_\\d+".r, FrontBusKey) ++ 215 | new BusFrequencyAssignment("subsystem_mbus_\\d+".r, MemoryBusKey) 216 | ) 217 | 218 | /** 219 | * Mixins to specify crossing types between the 5 traditional TL buses 220 | * 221 | * Note: these presuppose the legacy connections between buses and set 222 | * parameters in SubsystemCrossingParams; they may not be resuable in custom 223 | * topologies (but you can specify the desired crossings in your topology). 224 | * 225 | * @param xType The clock crossing type 226 | * 227 | */ 228 | 229 | class WithSbusToMbusCrossingType(xType: ClockCrossingType) extends Config((site, here, up) => { 230 | case SbusToMbusXTypeKey => xType 231 | }) 232 | class WithSbusToCbusCrossingType(xType: ClockCrossingType) extends Config((site, here, up) => { 233 | case SbusToCbusXTypeKey => xType 234 | }) 235 | class WithCbusToPbusCrossingType(xType: ClockCrossingType) extends Config((site, here, up) => { 236 | case CbusToPbusXTypeKey => xType 237 | }) 238 | class WithFbusToSbusCrossingType(xType: ClockCrossingType) extends Config((site, here, up) => { 239 | case FbusToSbusXTypeKey => xType 240 | }) 241 | 242 | /** 243 | * Mixins to set the dtsFrequency field of BusParams -- these will percolate its way 244 | * up the diplomatic graph to the clock sources. 245 | */ 246 | class WithPeripheryBusFrequency(freqMHz: Double) extends Config((site, here, up) => { 247 | case PeripheryBusKey => up(PeripheryBusKey, site).copy(dtsFrequency = Some(BigInt((freqMHz * 1e6).toLong))) 248 | }) 249 | class WithMemoryBusFrequency(freqMHz: Double) extends Config((site, here, up) => { 250 | case MemoryBusKey => up(MemoryBusKey, site).copy(dtsFrequency = Some(BigInt((freqMHz * 1e6).toLong))) 251 | }) 252 | class WithSystemBusFrequency(freqMHz: Double) extends Config((site, here, up) => { 253 | case SystemBusKey => up(SystemBusKey, site).copy(dtsFrequency = Some(BigInt((freqMHz * 1e6).toLong))) 254 | }) 255 | class WithFrontBusFrequency(freqMHz: Double) extends Config((site, here, up) => { 256 | case FrontBusKey => up(FrontBusKey, site).copy(dtsFrequency = Some(BigInt((freqMHz * 1e6).toLong))) 257 | }) 258 | class WithControlBusFrequency(freqMHz: Double) extends Config((site, here, up) => { 259 | case ControlBusKey => up(ControlBusKey, site).copy(dtsFrequency = Some(BigInt((freqMHz * 1e6).toLong))) 260 | }) 261 | 262 | class WithRationalMemoryBusCrossing extends WithSbusToMbusCrossingType(RationalCrossing(Symmetric)) 263 | class WithAsynchrousMemoryBusCrossing extends WithSbusToMbusCrossingType(AsynchronousCrossing()) 264 | 265 | class WithTestChipBusFreqs extends Config( 266 | // Frequency specifications 267 | new chipyard.config.WithTileFrequency(1600.0) ++ // Matches the maximum frequency of U540 268 | new chipyard.config.WithSystemBusFrequency(800.0) ++ // Put the system bus at a lower freq, representative of ncore working at a lower frequency than the tiles. Same freq as U540 269 | new chipyard.config.WithMemoryBusFrequency(1000.0) ++ // 2x the U540 freq (appropriate for a 128b Mbus) 270 | new chipyard.config.WithPeripheryBusFrequency(800.0) ++ // Match the sbus and pbus frequency 271 | new chipyard.config.WithSystemBusFrequencyAsDefault ++ // All unspecified clock frequencies, notably the implicit clock, will use the sbus freq (800 MHz) 272 | // Crossing specifications 273 | new chipyard.config.WithCbusToPbusCrossingType(AsynchronousCrossing()) ++ // Add Async crossing between PBUS and CBUS 274 | new chipyard.config.WithSbusToMbusCrossingType(AsynchronousCrossing()) ++ // Add Async crossings between backside of L2 and MBUS 275 | new freechips.rocketchip.subsystem.WithRationalRocketTiles ++ // Add rational crossings between RocketTile and uncore 276 | new boom.common.WithRationalBoomTiles ++ // Add rational crossings between BoomTile and uncore 277 | new testchipip.WithAsynchronousSerialSlaveCrossing // Add Async crossing between serial and MBUS. Its master-side is tied to the FBUS 278 | ) 279 | -------------------------------------------------------------------------------- /generators/chipyard/src/main/resources/csrc/emulator.cc: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | // See LICENSE.Berkeley for license details. 3 | 4 | #if VM_TRACE 5 | #include 6 | #if CY_FST_TRACE 7 | #include "verilated_fst_c.h" 8 | #else 9 | #include "verilated.h" 10 | #include "verilated_vcd_c.h" 11 | #endif // CY_FST_TRACE 12 | #endif // VM_TRACE 13 | #include 14 | #include 15 | #include "remote_bitbang.h" 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | 24 | // For option parsing, which is split across this file, Verilog, and 25 | // FESVR's HTIF, a few external files must be pulled in. The list of 26 | // files and what they provide is enumerated: 27 | // 28 | // $RISCV/include/fesvr/htif.h: 29 | // defines: 30 | // - HTIF_USAGE_OPTIONS 31 | // - HTIF_LONG_OPTIONS_OPTIND 32 | // - HTIF_LONG_OPTIONS 33 | // $(ROCKETCHIP_DIR)/generated-src(-debug)?/$(CONFIG).plusArgs: 34 | // defines: 35 | // - PLUSARG_USAGE_OPTIONS 36 | // variables: 37 | // - static const char * verilog_plusargs 38 | 39 | extern tsi_t* tsi; 40 | extern dtm_t* dtm; 41 | extern remote_bitbang_t * jtag; 42 | 43 | static uint64_t trace_count = 0; 44 | bool verbose = false; 45 | bool done_reset = false; 46 | 47 | void handle_sigterm(int sig) 48 | { 49 | dtm->stop(); 50 | } 51 | 52 | double sc_time_stamp() 53 | { 54 | return trace_count; 55 | } 56 | 57 | static void usage(const char * program_name) 58 | { 59 | printf("Usage: %s [EMULATOR OPTION]... [VERILOG PLUSARG]... [HOST OPTION]... BINARY [TARGET OPTION]...\n", 60 | program_name); 61 | fputs("\ 62 | Run a BINARY on the Rocket Chip emulator.\n\ 63 | \n\ 64 | Mandatory arguments to long options are mandatory for short options too.\n\ 65 | \n\ 66 | EMULATOR OPTIONS\n\ 67 | -c, --cycle-count Print the cycle count before exiting\n\ 68 | +cycle-count\n\ 69 | -h, --help Display this help and exit\n\ 70 | -m, --max-cycles=CYCLES Kill the emulation after CYCLES\n\ 71 | +max-cycles=CYCLES\n\ 72 | -s, --seed=SEED Use random number seed SEED\n\ 73 | -r, --rbb-port=PORT Use PORT for remote bit bang (with OpenOCD and GDB) \n\ 74 | If not specified, a random port will be chosen\n\ 75 | automatically.\n\ 76 | -V, --verbose Enable all Chisel printfs (cycle-by-cycle info)\n\ 77 | +verbose\n\ 78 | ", stdout); 79 | #if VM_TRACE == 0 80 | fputs("\ 81 | \n\ 82 | EMULATOR DEBUG OPTIONS (only supported in debug build -- try `make debug`)\n", 83 | stdout); 84 | #endif 85 | fputs("\ 86 | -v, --vcd=FILE, Write vcd trace to FILE (or '-' for stdout)\n\ 87 | -x, --dump-start=CYCLE Start VCD tracing at CYCLE\n\ 88 | +dump-start\n\ 89 | ", stdout); 90 | fputs("\n" PLUSARG_USAGE_OPTIONS, stdout); 91 | fputs("\n" HTIF_USAGE_OPTIONS, stdout); 92 | printf("\n" 93 | "EXAMPLES\n" 94 | " - run a bare metal test:\n" 95 | " %s $RISCV/riscv64-unknown-elf/share/riscv-tests/isa/rv64ui-p-add\n" 96 | " - run a bare metal test showing cycle-by-cycle information:\n" 97 | " %s +verbose $RISCV/riscv64-unknown-elf/share/riscv-tests/isa/rv64ui-p-add 2>&1 | spike-dasm\n" 98 | #if VM_TRACE 99 | " - run a bare metal test to generate a VCD waveform:\n" 100 | " %s -v rv64ui-p-add.vcd $RISCV/riscv64-unknown-elf/share/riscv-tests/isa/rv64ui-p-add\n" 101 | #endif 102 | " - run an ELF (you wrote, called 'hello') using the proxy kernel:\n" 103 | " %s pk hello\n", 104 | program_name, program_name, program_name 105 | #if VM_TRACE 106 | , program_name 107 | #endif 108 | ); 109 | } 110 | 111 | int main(int argc, char** argv) 112 | { 113 | unsigned random_seed = (unsigned)time(NULL) ^ (unsigned)getpid(); 114 | uint64_t max_cycles = -1; 115 | int ret = 0; 116 | bool print_cycles = false; 117 | // Port numbers are 16 bit unsigned integers. 118 | uint16_t rbb_port = 0; 119 | #if VM_TRACE 120 | const char* vcdfile_name = NULL; 121 | FILE * vcdfile = NULL; 122 | uint64_t start = 0; 123 | #endif 124 | int verilog_plusargs_legal = 1; 125 | 126 | int verilated_argc = 1; 127 | char** verilated_argv = new char*[argc]; 128 | verilated_argv[0] = argv[0]; 129 | 130 | opterr = 1; 131 | 132 | while (1) { 133 | static struct option long_options[] = { 134 | {"cycle-count", no_argument, 0, 'c' }, 135 | {"help", no_argument, 0, 'h' }, 136 | {"max-cycles", required_argument, 0, 'm' }, 137 | {"seed", required_argument, 0, 's' }, 138 | {"rbb-port", required_argument, 0, 'r' }, 139 | {"verbose", no_argument, 0, 'V' }, 140 | {"permissive", no_argument, 0, 'p' }, 141 | {"permissive-off", no_argument, 0, 'o' }, 142 | #if VM_TRACE 143 | {"vcd", required_argument, 0, 'v' }, 144 | {"dump-start", required_argument, 0, 'x' }, 145 | #endif 146 | HTIF_LONG_OPTIONS 147 | }; 148 | int option_index = 0; 149 | #if VM_TRACE 150 | int c = getopt_long(argc, argv, "-chm:s:r:v:Vx:po", long_options, &option_index); 151 | #else 152 | int c = getopt_long(argc, argv, "-chm:s:r:Vpo", long_options, &option_index); 153 | #endif 154 | if (c == -1) break; 155 | retry: 156 | switch (c) { 157 | // Process long and short EMULATOR options 158 | case '?': usage(argv[0]); return 1; 159 | case 'c': print_cycles = true; break; 160 | case 'h': usage(argv[0]); return 0; 161 | case 'm': max_cycles = atoll(optarg); break; 162 | case 's': random_seed = atoi(optarg); break; 163 | case 'r': rbb_port = atoi(optarg); break; 164 | case 'V': verbose = true; break; 165 | case 'p': opterr = 0; break; 166 | case 'o': opterr = 1; break; 167 | #if VM_TRACE 168 | case 'v': { 169 | vcdfile_name = optarg; 170 | vcdfile = strcmp(optarg, "-") == 0 ? stdout : fopen(optarg, "w"); 171 | if (!vcdfile) { 172 | std::cerr << "Unable to open " << optarg << " for VCD write\n"; 173 | return 1; 174 | } 175 | break; 176 | } 177 | case 'x': start = atoll(optarg); break; 178 | #endif 179 | // Process legacy '+' EMULATOR arguments by replacing them with 180 | // their getopt equivalents 181 | case 1: { 182 | std::string arg = optarg; 183 | if (arg.substr(0, 1) != "+") { 184 | optind--; 185 | goto done_processing; 186 | } 187 | if (arg == "+verbose") 188 | c = 'V'; 189 | else if (arg.substr(0, 12) == "+max-cycles=") { 190 | c = 'm'; 191 | optarg = optarg+12; 192 | } 193 | #if VM_TRACE 194 | else if (arg.substr(0, 12) == "+dump-start=") { 195 | c = 'x'; 196 | optarg = optarg+12; 197 | } 198 | #endif 199 | else if (arg.substr(0, 12) == "+cycle-count") 200 | c = 'c'; 201 | else if (arg == "+permissive") 202 | { 203 | c = 'p'; 204 | verilated_argv[verilated_argc++] = optarg; 205 | } 206 | else if (arg == "+permissive-off") 207 | { 208 | c = 'o'; 209 | verilated_argv[verilated_argc++] = optarg; 210 | } 211 | // If we don't find a legacy '+' EMULATOR argument, it still could be 212 | // a VERILOG_PLUSARG and not an error. 213 | else if (verilog_plusargs_legal) { 214 | const char ** plusarg = &verilog_plusargs[0]; 215 | int legal_verilog_plusarg = 0; 216 | while (*plusarg && (legal_verilog_plusarg == 0)){ 217 | if (arg.substr(1, strlen(*plusarg)) == *plusarg) { 218 | legal_verilog_plusarg = 1; 219 | } 220 | plusarg ++; 221 | } 222 | if (!legal_verilog_plusarg) { 223 | verilog_plusargs_legal = 0; 224 | } else { 225 | c = 'P'; 226 | } 227 | goto retry; 228 | } 229 | // If we STILL don't find a legacy '+' argument, it still could be 230 | // an HTIF (HOST) argument and not an error. If this is the case, then 231 | // we're done processing EMULATOR and VERILOG arguments. 232 | else { 233 | static struct option htif_long_options [] = { HTIF_LONG_OPTIONS }; 234 | struct option * htif_option = &htif_long_options[0]; 235 | while (htif_option->name) { 236 | if (arg.substr(1, strlen(htif_option->name)) == htif_option->name) { 237 | optind--; 238 | goto done_processing; 239 | } 240 | htif_option++; 241 | } 242 | if(opterr) { 243 | std::cerr << argv[0] << ": invalid plus-arg (Verilog or HTIF) \"" 244 | << arg << "\"\n"; 245 | c = '?'; 246 | } else { 247 | c = 'P'; 248 | } 249 | } 250 | goto retry; 251 | } 252 | case 'P': // Verilog PlusArg, add to the argument list for verilator environment 253 | verilated_argv[verilated_argc++] = optarg; 254 | break; 255 | // Realize that we've hit HTIF (HOST) arguments or error out 256 | default: 257 | if (c >= HTIF_LONG_OPTIONS_OPTIND) { 258 | optind--; 259 | goto done_processing; 260 | } 261 | c = '?'; 262 | goto retry; 263 | } 264 | } 265 | 266 | done_processing: 267 | if (optind == argc) { 268 | std::cerr << "No binary specified for emulator\n"; 269 | usage(argv[0]); 270 | return 1; 271 | } 272 | 273 | // Copy remaining HTIF arguments (if any) and the binary file name into the verilator argument stack 274 | while (optind < argc) verilated_argv[verilated_argc++] = argv[optind++]; 275 | 276 | if (verbose) 277 | fprintf(stderr, "using random seed %u\n", random_seed); 278 | 279 | srand(random_seed); 280 | srand48(random_seed); 281 | 282 | Verilated::randReset(2); 283 | Verilated::commandArgs(verilated_argc, verilated_argv); 284 | TEST_HARNESS *tile = new TEST_HARNESS; 285 | 286 | #if VM_TRACE 287 | Verilated::traceEverOn(true); // Verilator must compute traced signals 288 | #if CY_FST_TRACE 289 | std::unique_ptr tfp(new VerilatedFstC); 290 | #else 291 | std::unique_ptr vcdfd(new VerilatedVcdFILE(vcdfile)); 292 | std::unique_ptr tfp(new VerilatedVcdC(vcdfd.get())); 293 | #endif // CY_FST_TRACE 294 | if (vcdfile_name) { 295 | tile->trace(tfp.get(), 99); // Trace 99 levels of hierarchy 296 | tfp->open(vcdfile_name); 297 | } 298 | #endif // VM_TRACE 299 | 300 | // RocketChip currently only supports RBB port 0, so this needs to stay here 301 | jtag = new remote_bitbang_t(rbb_port); 302 | 303 | signal(SIGTERM, handle_sigterm); 304 | 305 | bool dump; 306 | // start reset off low so a rising edge triggers async reset 307 | tile->reset = 0; 308 | tile->clock = 0; 309 | tile->eval(); 310 | // reset for several cycles to handle pipelined reset 311 | for (int i = 0; i < 100; i++) { 312 | tile->reset = 1; 313 | tile->clock = 0; 314 | tile->eval(); 315 | #if VM_TRACE 316 | dump = tfp && trace_count >= start; 317 | if (dump) 318 | tfp->dump(static_cast(trace_count * 2)); 319 | #endif 320 | tile->clock = 1; 321 | tile->eval(); 322 | #if VM_TRACE 323 | if (dump) 324 | tfp->dump(static_cast(trace_count * 2 + 1)); 325 | #endif 326 | trace_count ++; 327 | } 328 | tile->reset = 0; 329 | done_reset = true; 330 | 331 | do { 332 | tile->clock = 0; 333 | tile->eval(); 334 | #if VM_TRACE 335 | dump = tfp && trace_count >= start; 336 | if (dump) 337 | tfp->dump(static_cast(trace_count * 2)); 338 | #endif 339 | 340 | tile->clock = 1; 341 | tile->eval(); 342 | #if VM_TRACE 343 | if (dump) 344 | tfp->dump(static_cast(trace_count * 2 + 1)); 345 | #endif 346 | trace_count++; 347 | } 348 | // for verilator multithreading. need to do 1 loop before checking if 349 | // tsi exists, since tsi is created by verilated thread on the first 350 | // serial_tick. 351 | while ((!dtm || !dtm->done()) && 352 | (!jtag || !jtag->done()) && 353 | (!tsi || !tsi->done()) && 354 | !tile->io_success && trace_count < max_cycles); 355 | 356 | #if VM_TRACE 357 | if (tfp) 358 | tfp->close(); 359 | if (vcdfile) 360 | fclose(vcdfile); 361 | #endif 362 | 363 | if (dtm && dtm->exit_code()) 364 | { 365 | fprintf(stderr, "*** FAILED *** via dtm (code = %d, seed %d) after %ld cycles\n", dtm->exit_code(), random_seed, trace_count); 366 | ret = dtm->exit_code(); 367 | } 368 | else if (tsi && tsi->exit_code()) 369 | { 370 | fprintf(stderr, "*** FAILED *** (code = %d, seed %d) after %ld cycles\n", tsi->exit_code(), random_seed, trace_count); 371 | ret = tsi->exit_code(); 372 | } 373 | else if (jtag && jtag->exit_code()) 374 | { 375 | fprintf(stderr, "*** FAILED *** via jtag (code = %d, seed %d) after %ld cycles\n", jtag->exit_code(), random_seed, trace_count); 376 | ret = jtag->exit_code(); 377 | } 378 | else if (trace_count == max_cycles) 379 | { 380 | fprintf(stderr, "*** FAILED *** via trace_count (timeout, seed %d) after %ld cycles\n", random_seed, trace_count); 381 | ret = 2; 382 | } 383 | else if (verbose || print_cycles) 384 | { 385 | fprintf(stderr, "*** PASSED *** Completed after %ld cycles\n", trace_count); 386 | } 387 | 388 | if (dtm) delete dtm; 389 | if (tsi) delete tsi; 390 | if (jtag) delete jtag; 391 | if (tile) delete tile; 392 | if (verilated_argv) delete[] verilated_argv; 393 | return ret; 394 | } 395 | -------------------------------------------------------------------------------- /generators/chipyard/src/main/scala/HarnessBinders.scala: -------------------------------------------------------------------------------- 1 | package chipyard.harness 2 | 3 | import chisel3._ 4 | import chisel3.util._ 5 | import chisel3.experimental.{Analog, BaseModule, DataMirror, Direction} 6 | 7 | import freechips.rocketchip.config.{Field, Config, Parameters} 8 | import freechips.rocketchip.diplomacy.{LazyModule, LazyModuleImpLike} 9 | import freechips.rocketchip.amba.axi4.{AXI4Bundle, AXI4SlaveNode, AXI4MasterNode, AXI4EdgeParameters} 10 | import freechips.rocketchip.devices.debug._ 11 | import freechips.rocketchip.jtag.{JTAGIO} 12 | import freechips.rocketchip.system.{SimAXIMem} 13 | import freechips.rocketchip.subsystem._ 14 | import freechips.rocketchip.util._ 15 | 16 | import sifive.blocks.devices.gpio._ 17 | import sifive.blocks.devices.uart._ 18 | import sifive.blocks.devices.spi._ 19 | 20 | import barstools.iocell.chisel._ 21 | 22 | import testchipip._ 23 | 24 | import chipyard.{HasHarnessSignalReferences, HarnessClockInstantiatorKey} 25 | import chipyard.iobinders.{GetSystemParameters, JTAGChipIO} 26 | 27 | import scala.reflect.{ClassTag} 28 | 29 | case object HarnessBinders extends Field[Map[String, (Any, HasHarnessSignalReferences, Seq[Data]) => Unit]]( 30 | Map[String, (Any, HasHarnessSignalReferences, Seq[Data]) => Unit]().withDefaultValue((t: Any, th: HasHarnessSignalReferences, d: Seq[Data]) => ()) 31 | ) 32 | 33 | object ApplyHarnessBinders { 34 | def apply(th: HasHarnessSignalReferences, sys: LazyModule, portMap: Map[String, Seq[Data]])(implicit p: Parameters): Unit = { 35 | val pm = portMap.withDefaultValue(Nil) 36 | p(HarnessBinders).foreach { case (s, f) => 37 | f(sys, th, pm(s)) 38 | f(sys.module, th, pm(s)) 39 | } 40 | } 41 | } 42 | 43 | // The ClassTags here are necessary to overcome issues arising from type erasure 44 | class HarnessBinder[T, S <: HasHarnessSignalReferences, U <: Data](composer: ((T, S, Seq[U]) => Unit) => (T, S, Seq[U]) => Unit)(implicit systemTag: ClassTag[T], harnessTag: ClassTag[S], portTag: ClassTag[U]) extends Config((site, here, up) => { 45 | case HarnessBinders => up(HarnessBinders, site) + (systemTag.runtimeClass.toString -> 46 | ((t: Any, th: HasHarnessSignalReferences, ports: Seq[Data]) => { 47 | val pts = ports.collect({case p: U => p}) 48 | require (pts.length == ports.length, s"Port type mismatch between IOBinder and HarnessBinder: ${portTag}") 49 | val upfn = up(HarnessBinders, site)(systemTag.runtimeClass.toString) 50 | th match { 51 | case th: S => 52 | t match { 53 | case system: T => composer(upfn)(system, th, pts) 54 | case _ => 55 | } 56 | case _ => 57 | } 58 | }) 59 | ) 60 | }) 61 | 62 | class OverrideHarnessBinder[T, S <: HasHarnessSignalReferences, U <: Data](fn: => (T, S, Seq[U]) => Unit) 63 | (implicit tag: ClassTag[T], thtag: ClassTag[S], ptag: ClassTag[U]) 64 | extends HarnessBinder[T, S, U]((upfn: (T, S, Seq[U]) => Unit) => fn) 65 | 66 | class ComposeHarnessBinder[T, S <: HasHarnessSignalReferences, U <: Data](fn: => (T, S, Seq[U]) => Unit) 67 | (implicit tag: ClassTag[T], thtag: ClassTag[S], ptag: ClassTag[U]) 68 | extends HarnessBinder[T, S, U]((upfn: (T, S, Seq[U]) => Unit) => (t, th, p) => { 69 | upfn(t, th, p) 70 | fn(t, th, p) 71 | }) 72 | 73 | 74 | class WithGPIOTiedOff extends OverrideHarnessBinder({ 75 | (system: HasPeripheryGPIOModuleImp, th: HasHarnessSignalReferences, ports: Seq[Analog]) => { 76 | ports.foreach { _ <> AnalogConst(0) } 77 | } 78 | }) 79 | 80 | // DOC include start: WithUARTAdapter 81 | class WithUARTAdapter extends OverrideHarnessBinder({ 82 | (system: HasPeripheryUARTModuleImp, th: HasHarnessSignalReferences, ports: Seq[UARTPortIO]) => { 83 | UARTAdapter.connect(ports)(system.p) 84 | } 85 | }) 86 | // DOC include end: WithUARTAdapter 87 | 88 | class WithSimSPIFlashModel(rdOnly: Boolean = true) extends OverrideHarnessBinder({ 89 | (system: HasPeripherySPIFlashModuleImp, th: HasHarnessSignalReferences, ports: Seq[SPIChipIO]) => { 90 | SimSPIFlashModel.connect(ports, th.buildtopReset, rdOnly)(system.p) 91 | } 92 | }) 93 | 94 | class WithSimBlockDevice extends OverrideHarnessBinder({ 95 | (system: CanHavePeripheryBlockDevice, th: HasHarnessSignalReferences, ports: Seq[ClockedIO[BlockDeviceIO]]) => { 96 | implicit val p: Parameters = GetSystemParameters(system) 97 | ports.map { b => SimBlockDevice.connect(b.clock, th.buildtopReset.asBool, Some(b.bits)) } 98 | } 99 | }) 100 | 101 | class WithBlockDeviceModel extends OverrideHarnessBinder({ 102 | (system: CanHavePeripheryBlockDevice, th: HasHarnessSignalReferences, ports: Seq[ClockedIO[BlockDeviceIO]]) => { 103 | implicit val p: Parameters = GetSystemParameters(system) 104 | ports.map { b => withClockAndReset(b.clock, th.buildtopReset) { BlockDeviceModel.connect(Some(b.bits)) } } 105 | } 106 | }) 107 | 108 | class WithSimAXIMem extends OverrideHarnessBinder({ 109 | (system: CanHaveMasterAXI4MemPort, th: HasHarnessSignalReferences, ports: Seq[ClockedAndResetIO[AXI4Bundle]]) => { 110 | val p: Parameters = chipyard.iobinders.GetSystemParameters(system) 111 | (ports zip system.memAXI4Node.edges.in).map { case (port, edge) => 112 | val mem = LazyModule(new SimAXIMem(edge, size=p(ExtMem).get.master.size)(p)) 113 | withClockAndReset(port.clock, port.reset) { 114 | Module(mem.module).suggestName("mem") 115 | } 116 | mem.io_axi4.head <> port.bits 117 | } 118 | } 119 | }) 120 | 121 | class WithSimAXIMemOverSerialTL extends OverrideHarnessBinder({ 122 | (system: CanHavePeripheryTLSerial, th: HasHarnessSignalReferences, ports: Seq[ClockedIO[SerialIO]]) => { 123 | implicit val p = chipyard.iobinders.GetSystemParameters(system) 124 | 125 | p(SerialTLKey).map({ sVal => 126 | require(sVal.axiMemOverSerialTLParams.isDefined) 127 | val axiDomainParams = sVal.axiMemOverSerialTLParams.get 128 | require(sVal.isMemoryDevice) 129 | 130 | val memFreq = axiDomainParams.getMemFrequency(system.asInstanceOf[HasTileLinkLocations]) 131 | 132 | ports.map({ port => 133 | // DOC include start: HarnessClockInstantiatorEx 134 | withClockAndReset(th.buildtopClock, th.buildtopReset) { 135 | val memOverSerialTLClockBundle = p(HarnessClockInstantiatorKey).requestClockBundle("mem_over_serial_tl_clock", memFreq) 136 | val serial_bits = SerialAdapter.asyncQueue(port, th.buildtopClock, th.buildtopReset) 137 | val harnessMultiClockAXIRAM = SerialAdapter.connectHarnessMultiClockAXIRAM( 138 | system.serdesser.get, 139 | serial_bits, 140 | memOverSerialTLClockBundle, 141 | th.buildtopReset) 142 | // DOC include end: HarnessClockInstantiatorEx 143 | val success = SerialAdapter.connectSimSerial(harnessMultiClockAXIRAM.module.io.tsi_ser, th.buildtopClock, th.buildtopReset.asBool) 144 | when (success) { th.success := true.B } 145 | 146 | // connect SimDRAM from the AXI port coming from the harness multi clock axi ram 147 | (harnessMultiClockAXIRAM.mem_axi4 zip harnessMultiClockAXIRAM.memNode.edges.in).map { case (axi_port, edge) => 148 | val memSize = sVal.memParams.size 149 | val lineSize = p(CacheBlockBytes) 150 | val mem = Module(new SimDRAM(memSize, lineSize, BigInt(memFreq.toLong), edge.bundle)).suggestName("simdram") 151 | mem.io.axi <> axi_port.bits 152 | mem.io.clock := axi_port.clock 153 | mem.io.reset := axi_port.reset 154 | } 155 | } 156 | }) 157 | }) 158 | } 159 | }) 160 | 161 | class WithBlackBoxSimMem(additionalLatency: Int = 0) extends OverrideHarnessBinder({ 162 | (system: CanHaveMasterAXI4MemPort, th: HasHarnessSignalReferences, ports: Seq[ClockedAndResetIO[AXI4Bundle]]) => { 163 | val p: Parameters = chipyard.iobinders.GetSystemParameters(system) 164 | (ports zip system.memAXI4Node.edges.in).map { case (port, edge) => 165 | val memSize = p(ExtMem).get.master.size 166 | val lineSize = p(CacheBlockBytes) 167 | val clockFreq = p(MemoryBusKey).dtsFrequency.get 168 | val mem = Module(new SimDRAM(memSize, lineSize, clockFreq, edge.bundle)).suggestName("simdram") 169 | mem.io.axi <> port.bits 170 | // Bug in Chisel implementation. See https://github.com/chipsalliance/chisel3/pull/1781 171 | def Decoupled[T <: Data](irr: IrrevocableIO[T]): DecoupledIO[T] = { 172 | require(DataMirror.directionOf(irr.bits) == Direction.Output, "Only safe to cast produced Irrevocable bits to Decoupled.") 173 | val d = Wire(new DecoupledIO(chiselTypeOf(irr.bits))) 174 | d.bits := irr.bits 175 | d.valid := irr.valid 176 | irr.ready := d.ready 177 | d 178 | } 179 | if (additionalLatency > 0) { 180 | withClockAndReset (port.clock, port.reset) { 181 | mem.io.axi.aw <> (0 until additionalLatency).foldLeft(Decoupled(port.bits.aw))((t, _) => Queue(t, 1, pipe=true)) 182 | mem.io.axi.w <> (0 until additionalLatency).foldLeft(Decoupled(port.bits.w ))((t, _) => Queue(t, 1, pipe=true)) 183 | port.bits.b <> (0 until additionalLatency).foldLeft(Decoupled(mem.io.axi.b))((t, _) => Queue(t, 1, pipe=true)) 184 | mem.io.axi.ar <> (0 until additionalLatency).foldLeft(Decoupled(port.bits.ar))((t, _) => Queue(t, 1, pipe=true)) 185 | port.bits.r <> (0 until additionalLatency).foldLeft(Decoupled(mem.io.axi.r))((t, _) => Queue(t, 1, pipe=true)) 186 | } 187 | } 188 | mem.io.clock := port.clock 189 | mem.io.reset := port.reset 190 | } 191 | } 192 | }) 193 | 194 | class WithSimAXIMMIO extends OverrideHarnessBinder({ 195 | (system: CanHaveMasterAXI4MMIOPort, th: HasHarnessSignalReferences, ports: Seq[ClockedAndResetIO[AXI4Bundle]]) => { 196 | val p: Parameters = chipyard.iobinders.GetSystemParameters(system) 197 | (ports zip system.mmioAXI4Node.edges.in).map { case (port, edge) => 198 | val mmio_mem = LazyModule(new SimAXIMem(edge, size = p(ExtBus).get.size)(p)) 199 | withClockAndReset(port.clock, port.reset) { 200 | Module(mmio_mem.module).suggestName("mmio_mem") 201 | } 202 | mmio_mem.io_axi4.head <> port.bits 203 | } 204 | } 205 | }) 206 | 207 | class WithTieOffInterrupts extends OverrideHarnessBinder({ 208 | (system: HasExtInterruptsModuleImp, th: HasHarnessSignalReferences, ports: Seq[UInt]) => { 209 | ports.foreach { _ := 0.U } 210 | } 211 | }) 212 | 213 | class WithTieOffL2FBusAXI extends OverrideHarnessBinder({ 214 | (system: CanHaveSlaveAXI4Port, th: HasHarnessSignalReferences, ports: Seq[ClockedIO[AXI4Bundle]]) => { 215 | ports.foreach({ p => p := DontCare; p.bits.tieoff() }) 216 | } 217 | }) 218 | 219 | class WithSimDebug extends OverrideHarnessBinder({ 220 | (system: HasPeripheryDebug, th: HasHarnessSignalReferences, ports: Seq[Data]) => { 221 | implicit val p: Parameters = GetSystemParameters(system) 222 | ports.map { 223 | case d: ClockedDMIIO => 224 | val dtm_success = WireInit(false.B) 225 | when (dtm_success) { th.success := true.B } 226 | val dtm = Module(new SimDTM).connect(th.buildtopClock, th.buildtopReset.asBool, d, dtm_success) 227 | case j: JTAGChipIO => 228 | val dtm_success = WireInit(false.B) 229 | when (dtm_success) { th.success := true.B } 230 | val jtag_wire = Wire(new JTAGIO) 231 | jtag_wire.TDO.data := j.TDO 232 | jtag_wire.TDO.driven := true.B 233 | j.TCK := jtag_wire.TCK 234 | j.TMS := jtag_wire.TMS 235 | j.TDI := jtag_wire.TDI 236 | val jtag = Module(new SimJTAG(tickDelay=3)).connect(jtag_wire, th.buildtopClock, th.buildtopReset.asBool, ~(th.buildtopReset.asBool), dtm_success) 237 | } 238 | } 239 | }) 240 | 241 | class WithTiedOffDebug extends OverrideHarnessBinder({ 242 | (system: HasPeripheryDebug, th: HasHarnessSignalReferences, ports: Seq[Data]) => { 243 | ports.map { 244 | case j: JTAGChipIO => 245 | j.TCK := true.B.asClock 246 | j.TMS := true.B 247 | j.TDI := true.B 248 | case d: ClockedDMIIO => 249 | d.dmi.req.valid := false.B 250 | d.dmi.req.bits := DontCare 251 | d.dmi.resp.ready := true.B 252 | d.dmiClock := false.B.asClock 253 | d.dmiReset := true.B 254 | case a: ClockedAPBBundle => 255 | a.tieoff() 256 | a.clock := false.B.asClock 257 | a.reset := true.B.asAsyncReset 258 | a.psel := false.B 259 | a.penable := false.B 260 | } 261 | } 262 | }) 263 | 264 | 265 | class WithSerialAdapterTiedOff extends OverrideHarnessBinder({ 266 | (system: CanHavePeripheryTLSerial, th: HasHarnessSignalReferences, ports: Seq[ClockedIO[SerialIO]]) => { 267 | implicit val p = chipyard.iobinders.GetSystemParameters(system) 268 | ports.map({ port => 269 | val bits = SerialAdapter.asyncQueue(port, th.buildtopClock, th.buildtopReset) 270 | withClockAndReset(th.buildtopClock, th.buildtopReset) { 271 | val ram = SerialAdapter.connectHarnessRAM(system.serdesser.get, bits, th.buildtopReset) 272 | SerialAdapter.tieoff(ram.module.io.tsi_ser) 273 | } 274 | }) 275 | } 276 | }) 277 | 278 | class WithSimSerial extends OverrideHarnessBinder({ 279 | (system: CanHavePeripheryTLSerial, th: HasHarnessSignalReferences, ports: Seq[ClockedIO[SerialIO]]) => { 280 | implicit val p = chipyard.iobinders.GetSystemParameters(system) 281 | ports.map({ port => 282 | val bits = SerialAdapter.asyncQueue(port, th.buildtopClock, th.buildtopReset) 283 | withClockAndReset(th.buildtopClock, th.buildtopReset) { 284 | val ram = SerialAdapter.connectHarnessRAM(system.serdesser.get, bits, th.buildtopReset) 285 | val success = SerialAdapter.connectSimSerial(ram.module.io.tsi_ser, th.buildtopClock, th.buildtopReset.asBool) 286 | when (success) { th.success := true.B } 287 | } 288 | }) 289 | } 290 | }) 291 | 292 | class WithTieOffCustomBootPin extends OverrideHarnessBinder({ 293 | (system: CanHavePeripheryCustomBootPin, th: HasHarnessSignalReferences, ports: Seq[Bool]) => { 294 | ports.foreach(_ := false.B) 295 | } 296 | }) 297 | -------------------------------------------------------------------------------- /generators/chipyard/src/main/scala/IOBinders.scala: -------------------------------------------------------------------------------- 1 | package chipyard.iobinders 2 | 3 | import chisel3._ 4 | import chisel3.experimental.{Analog, IO, DataMirror} 5 | 6 | import freechips.rocketchip.config._ 7 | import freechips.rocketchip.diplomacy._ 8 | import freechips.rocketchip.devices.debug._ 9 | import freechips.rocketchip.jtag.{JTAGIO} 10 | import freechips.rocketchip.subsystem._ 11 | import freechips.rocketchip.system.{SimAXIMem} 12 | import freechips.rocketchip.amba.axi4.{AXI4Bundle, AXI4SlaveNode, AXI4MasterNode, AXI4EdgeParameters} 13 | import freechips.rocketchip.util._ 14 | import freechips.rocketchip.prci.{ClockSinkNode, ClockSinkParameters} 15 | import freechips.rocketchip.groundtest.{GroundTestSubsystemModuleImp, GroundTestSubsystem} 16 | 17 | import sifive.blocks.devices.gpio._ 18 | import sifive.blocks.devices.uart._ 19 | import sifive.blocks.devices.spi._ 20 | 21 | import barstools.iocell.chisel._ 22 | 23 | import testchipip._ 24 | 25 | import scala.reflect.{ClassTag} 26 | 27 | object IOBinderTypes { 28 | type IOBinderTuple = (Seq[Data], Seq[IOCell]) 29 | type IOBinderFunction = (Boolean, => Any) => ModuleValue[IOBinderTuple] 30 | } 31 | import IOBinderTypes._ 32 | 33 | // System for instantiating binders based 34 | // on the scala type of the Target (_not_ its IO). This avoids needing to 35 | // duplicate harnesses (essentially test harnesses) for each target. 36 | 37 | // IOBinders is map between string representations of traits to the desired 38 | // IO connection behavior for tops matching that trait. We use strings to enable 39 | // composition and overriding of IOBinders, much like how normal Keys in the config 40 | // system are used/ At elaboration, the testharness traverses this set of functions, 41 | // and functions which match the type of the DigitalTop are evaluated. 42 | 43 | // You can add your own binder by adding a new (key, fn) pair, typically by using 44 | // the OverrideIOBinder or ComposeIOBinder macros 45 | case object IOBinders extends Field[Map[String, Seq[IOBinderFunction]]]( 46 | Map[String, Seq[IOBinderFunction]]().withDefaultValue(Nil) 47 | ) 48 | 49 | abstract trait HasIOBinders { this: LazyModule => 50 | val lazySystem: LazyModule 51 | private val iobinders = p(IOBinders) 52 | // Note: IOBinders cannot rely on the implicit clock/reset, as they may be called from the 53 | // context of a LazyRawModuleImp 54 | private val lzy = iobinders.map({ case (s,fns) => s -> fns.map(f => f(true, lazySystem)) }) 55 | private val imp = iobinders.map({ case (s,fns) => s -> fns.map(f => f(false, lazySystem.module)) }) 56 | 57 | private lazy val lzyFlattened: Map[String, IOBinderTuple] = lzy.map({ 58 | case (s,ms) => s -> (ms.map(_._1).flatten, ms.map(_._2).flatten) 59 | }) 60 | private lazy val impFlattened: Map[String, IOBinderTuple] = imp.map({ 61 | case (s,ms) => s -> (ms.map(_._1).flatten, ms.map(_._2).flatten) 62 | }) 63 | 64 | // A publicly accessible list of IO cells (useful for a floorplanning tool, for example) 65 | lazy val iocells = (lzyFlattened.values ++ impFlattened.values).unzip._2.flatten.toBuffer 66 | 67 | // A mapping between stringified DigitalSystem traits and their corresponding ChipTop ports 68 | lazy val portMap = iobinders.keys.map(k => k -> (lzyFlattened(k)._1 ++ impFlattened(k)._1)).toMap 69 | } 70 | 71 | // Note: The parameters instance is accessible only through LazyModule 72 | // or LazyModuleImpLike. The self-type requirement in traits like 73 | // CanHaveMasterAXI4MemPort is insufficient to make it accessible to the IOBinder 74 | // As a result, IOBinders only work on Modules which inherit LazyModule or 75 | // or LazyModuleImpLike 76 | object GetSystemParameters { 77 | def apply(s: Any): Parameters = { 78 | s match { 79 | case s: LazyModule => s.p 80 | case s: LazyModuleImpLike => s.p 81 | case _ => throw new Exception(s"Trying to get Parameters from a system that is not LazyModule or LazyModuleImpLike") 82 | } 83 | } 84 | } 85 | 86 | class IOBinder[T](composer: Seq[IOBinderFunction] => Seq[IOBinderFunction])(implicit tag: ClassTag[T]) extends Config((site, here, up) => { 87 | case IOBinders => up(IOBinders, site) + (tag.runtimeClass.toString -> composer(up(IOBinders, site)(tag.runtimeClass.toString))) 88 | }) 89 | 90 | class ConcreteIOBinder[T](composes: Boolean, fn: T => IOBinderTuple)(implicit tag: ClassTag[T]) extends IOBinder[T]( 91 | up => (if (composes) up else Nil) ++ Seq(((_, t) => { InModuleBody { 92 | t match { 93 | case system: T => fn(system) 94 | case _ => (Nil, Nil) 95 | } 96 | }}): IOBinderFunction) 97 | ) 98 | 99 | class LazyIOBinder[T](composes: Boolean, fn: T => ModuleValue[IOBinderTuple])(implicit tag: ClassTag[T]) extends IOBinder[T]( 100 | up => (if (composes) up else Nil) ++ Seq(((isLazy, t) => { 101 | val empty = new ModuleValue[IOBinderTuple] { 102 | def getWrappedValue: IOBinderTuple = (Nil, Nil) 103 | } 104 | if (isLazy) { 105 | t match { 106 | case system: T => fn(system) 107 | case _ => empty 108 | } 109 | } else { 110 | empty 111 | } 112 | }): IOBinderFunction) 113 | ) 114 | 115 | // The "Override" binders override any previous IOBinders (lazy or concrete) defined on the same trait. 116 | // The "Compose" binders do not override previously defined IOBinders on the same trait 117 | // The default IOBinders evaluate only in the concrete "ModuleImp" phase of elaboration 118 | // The "Lazy" IOBinders evaluate in the LazyModule phase, but can also generate hardware through InModuleBody 119 | 120 | class OverrideIOBinder[T](fn: T => IOBinderTuple)(implicit tag: ClassTag[T]) extends ConcreteIOBinder[T](false, fn) 121 | class ComposeIOBinder[T](fn: T => IOBinderTuple)(implicit tag: ClassTag[T]) extends ConcreteIOBinder[T](true, fn) 122 | 123 | class OverrideLazyIOBinder[T](fn: T => ModuleValue[IOBinderTuple])(implicit tag: ClassTag[T]) extends LazyIOBinder[T](false, fn) 124 | class ComposeLazyIOBinder[T](fn: T => ModuleValue[IOBinderTuple])(implicit tag: ClassTag[T]) extends LazyIOBinder[T](true, fn) 125 | 126 | 127 | case object IOCellKey extends Field[IOCellTypeParams](GenericIOCellParams()) 128 | 129 | 130 | class WithGPIOCells extends OverrideIOBinder({ 131 | (system: HasPeripheryGPIOModuleImp) => { 132 | val (ports2d, cells2d) = system.gpio.zipWithIndex.map({ case (gpio, i) => 133 | gpio.pins.zipWithIndex.map({ case (pin, j) => 134 | val g = IO(Analog(1.W)).suggestName(s"gpio_${i}_${j}") 135 | val iocell = system.p(IOCellKey).gpio().suggestName(s"iocell_gpio_${i}_${j}") 136 | iocell.io.o := pin.o.oval 137 | iocell.io.oe := pin.o.oe 138 | iocell.io.ie := pin.o.ie 139 | pin.i.ival := iocell.io.i 140 | iocell.io.pad <> g 141 | (g, iocell) 142 | }).unzip 143 | }).unzip 144 | val ports: Seq[Analog] = ports2d.flatten 145 | (ports, cells2d.flatten) 146 | } 147 | }) 148 | 149 | // DOC include start: WithUARTIOCells 150 | class WithUARTIOCells extends OverrideIOBinder({ 151 | (system: HasPeripheryUARTModuleImp) => { 152 | val (ports: Seq[UARTPortIO], cells2d) = system.uart.zipWithIndex.map({ case (u, i) => 153 | val (port, ios) = IOCell.generateIOFromSignal(u, s"uart_${i}", system.p(IOCellKey), abstractResetAsAsync = true) 154 | (port, ios) 155 | }).unzip 156 | (ports, cells2d.flatten) 157 | } 158 | }) 159 | // DOC include end: WithUARTIOCells 160 | 161 | class WithSPIIOCells extends OverrideIOBinder({ 162 | (system: HasPeripherySPIFlashModuleImp) => { 163 | val (ports: Seq[SPIChipIO], cells2d) = system.qspi.zipWithIndex.map({ case (s, i) => 164 | val name = s"spi_${i}" 165 | val port = IO(new SPIChipIO(s.c.csWidth)).suggestName(name) 166 | val iocellBase = s"iocell_${name}" 167 | 168 | // SCK and CS are unidirectional outputs 169 | val sckIOs = IOCell.generateFromSignal(s.sck, port.sck, Some(s"${iocellBase}_sck"), system.p(IOCellKey), IOCell.toAsyncReset) 170 | val csIOs = IOCell.generateFromSignal(s.cs, port.cs, Some(s"${iocellBase}_cs"), system.p(IOCellKey), IOCell.toAsyncReset) 171 | 172 | // DQ are bidirectional, so then need special treatment 173 | val dqIOs = s.dq.zip(port.dq).zipWithIndex.map { case ((pin, ana), j) => 174 | val iocell = system.p(IOCellKey).gpio().suggestName(s"${iocellBase}_dq_${j}") 175 | iocell.io.o := pin.o 176 | iocell.io.oe := pin.oe 177 | iocell.io.ie := true.B 178 | pin.i := iocell.io.i 179 | iocell.io.pad <> ana 180 | iocell 181 | } 182 | 183 | (port, dqIOs ++ csIOs ++ sckIOs) 184 | }).unzip 185 | (ports, cells2d.flatten) 186 | } 187 | }) 188 | 189 | class WithExtInterruptIOCells extends OverrideIOBinder({ 190 | (system: HasExtInterruptsModuleImp) => { 191 | if (system.outer.nExtInterrupts > 0) { 192 | val (port: UInt, cells) = IOCell.generateIOFromSignal(system.interrupts, "ext_interrupts", system.p(IOCellKey), abstractResetAsAsync = true) 193 | (Seq(port), cells) 194 | } else { 195 | (Nil, Nil) 196 | } 197 | } 198 | }) 199 | 200 | // Rocketchip's JTAGIO exposes the oe signal, which doesn't go off-chip 201 | class JTAGChipIO extends Bundle { 202 | val TCK = Input(Clock()) 203 | val TMS = Input(Bool()) 204 | val TDI = Input(Bool()) 205 | val TDO = Output(Bool()) 206 | } 207 | 208 | class WithDebugIOCells extends OverrideLazyIOBinder({ 209 | (system: HasPeripheryDebug) => { 210 | implicit val p = GetSystemParameters(system) 211 | val tlbus = system.asInstanceOf[BaseSubsystem].locateTLBusWrapper(p(ExportDebug).slaveWhere) 212 | val clockSinkNode = system.debugOpt.map(_ => ClockSinkNode(Seq(ClockSinkParameters()))) 213 | clockSinkNode.map(_ := tlbus.fixedClockNode) 214 | def clockBundle = clockSinkNode.get.in.head._1 215 | 216 | 217 | InModuleBody { system.asInstanceOf[BaseSubsystem].module match { case system: HasPeripheryDebugModuleImp => { 218 | system.debug.map({ debug => 219 | // We never use the PSDIO, so tie it off on-chip 220 | system.psd.psd.foreach { _ <> 0.U.asTypeOf(new PSDTestMode) } 221 | system.resetctrl.map { rcio => rcio.hartIsInReset.map { _ := clockBundle.reset.asBool } } 222 | system.debug.map { d => 223 | // Tie off extTrigger 224 | d.extTrigger.foreach { t => 225 | t.in.req := false.B 226 | t.out.ack := t.out.req 227 | } 228 | // Tie off disableDebug 229 | d.disableDebug.foreach { d => d := false.B } 230 | // Drive JTAG on-chip IOs 231 | d.systemjtag.map { j => 232 | j.reset := ResetCatchAndSync(j.jtag.TCK, clockBundle.reset.asBool) 233 | j.mfr_id := p(JtagDTMKey).idcodeManufId.U(11.W) 234 | j.part_number := p(JtagDTMKey).idcodePartNum.U(16.W) 235 | j.version := p(JtagDTMKey).idcodeVersion.U(4.W) 236 | } 237 | } 238 | Debug.connectDebugClockAndReset(Some(debug), clockBundle.clock) 239 | 240 | // Add IOCells for the DMI/JTAG/APB ports 241 | val dmiTuple = debug.clockeddmi.map { d => 242 | IOCell.generateIOFromSignal(d, "dmi", p(IOCellKey), abstractResetAsAsync = true) 243 | } 244 | 245 | val jtagTuple = debug.systemjtag.map { j => 246 | val jtag_wire = Wire(new JTAGChipIO) 247 | j.jtag.TCK := jtag_wire.TCK 248 | j.jtag.TMS := jtag_wire.TMS 249 | j.jtag.TDI := jtag_wire.TDI 250 | jtag_wire.TDO := j.jtag.TDO.data 251 | IOCell.generateIOFromSignal(jtag_wire, "jtag", p(IOCellKey), abstractResetAsAsync = true) 252 | } 253 | 254 | val apbTuple = debug.apb.map { a => 255 | IOCell.generateIOFromSignal(a, "apb", p(IOCellKey), abstractResetAsAsync = true) 256 | } 257 | 258 | val allTuples = (dmiTuple ++ jtagTuple ++ apbTuple).toSeq 259 | (allTuples.map(_._1).toSeq, allTuples.flatMap(_._2).toSeq) 260 | }).getOrElse((Nil, Nil)) 261 | }}} 262 | } 263 | }) 264 | 265 | class WithSerialTLIOCells extends OverrideIOBinder({ 266 | (system: CanHavePeripheryTLSerial) => system.serial_tl.map({ s => 267 | val sys = system.asInstanceOf[BaseSubsystem] 268 | val (port, cells) = IOCell.generateIOFromSignal(s.getWrappedValue, "serial_tl", sys.p(IOCellKey), abstractResetAsAsync = true) 269 | (Seq(port), cells) 270 | }).getOrElse((Nil, Nil)) 271 | }) 272 | 273 | class WithAXI4MemPunchthrough extends OverrideLazyIOBinder({ 274 | (system: CanHaveMasterAXI4MemPort) => { 275 | implicit val p: Parameters = GetSystemParameters(system) 276 | val clockSinkNode = p(ExtMem).map(_ => ClockSinkNode(Seq(ClockSinkParameters()))) 277 | clockSinkNode.map(_ := system.asInstanceOf[HasTileLinkLocations].locateTLBusWrapper(MBUS).fixedClockNode) 278 | def clockBundle = clockSinkNode.get.in.head._1 279 | 280 | InModuleBody { 281 | val ports: Seq[ClockedAndResetIO[AXI4Bundle]] = system.mem_axi4.zipWithIndex.map({ case (m, i) => 282 | val p = IO(new ClockedAndResetIO(DataMirror.internal.chiselTypeClone[AXI4Bundle](m))).suggestName(s"axi4_mem_${i}") 283 | p.bits <> m 284 | p.clock := clockBundle.clock 285 | p.reset := clockBundle.reset 286 | p 287 | }) 288 | (ports, Nil) 289 | } 290 | } 291 | }) 292 | 293 | class WithAXI4MMIOPunchthrough extends OverrideLazyIOBinder({ 294 | (system: CanHaveMasterAXI4MMIOPort) => { 295 | implicit val p: Parameters = GetSystemParameters(system) 296 | val clockSinkNode = p(ExtBus).map(_ => ClockSinkNode(Seq(ClockSinkParameters()))) 297 | clockSinkNode.map(_ := system.asInstanceOf[HasTileLinkLocations].locateTLBusWrapper(MBUS).fixedClockNode) 298 | def clockBundle = clockSinkNode.get.in.head._1 299 | 300 | InModuleBody { 301 | val ports: Seq[ClockedAndResetIO[AXI4Bundle]] = system.mmio_axi4.zipWithIndex.map({ case (m, i) => 302 | val p = IO(new ClockedAndResetIO(DataMirror.internal.chiselTypeClone[AXI4Bundle](m))).suggestName(s"axi4_mmio_${i}") 303 | p.bits <> m 304 | p.clock := clockBundle.clock 305 | p.reset := clockBundle.reset 306 | p 307 | }) 308 | (ports, Nil) 309 | } 310 | } 311 | }) 312 | 313 | class WithL2FBusAXI4Punchthrough extends OverrideLazyIOBinder({ 314 | (system: CanHaveSlaveAXI4Port) => { 315 | implicit val p: Parameters = GetSystemParameters(system) 316 | val clockSinkNode = p(ExtIn).map(_ => ClockSinkNode(Seq(ClockSinkParameters()))) 317 | clockSinkNode.map(_ := system.asInstanceOf[BaseSubsystem].fbus.fixedClockNode) 318 | def clockBundle = clockSinkNode.get.in.head._1 319 | 320 | InModuleBody { 321 | val ports: Seq[ClockedIO[AXI4Bundle]] = system.l2_frontend_bus_axi4.zipWithIndex.map({ case (m, i) => 322 | val p = IO(new ClockedIO(Flipped(DataMirror.internal.chiselTypeClone[AXI4Bundle](m)))).suggestName(s"axi4_fbus_${i}") 323 | m <> p.bits 324 | p.clock := clockBundle.clock 325 | p 326 | }) 327 | (ports, Nil) 328 | } 329 | } 330 | }) 331 | 332 | class WithBlockDeviceIOPunchthrough extends OverrideIOBinder({ 333 | (system: CanHavePeripheryBlockDevice) => { 334 | val ports: Seq[ClockedIO[BlockDeviceIO]] = system.bdev.map({ bdev => 335 | val p = IO(new ClockedIO(new BlockDeviceIO()(GetSystemParameters(system)))).suggestName("blockdev") 336 | p <> bdev 337 | p 338 | }).toSeq 339 | (ports, Nil) 340 | } 341 | }) 342 | 343 | class WithTraceIOPunchthrough extends OverrideIOBinder({ 344 | (system: CanHaveTraceIOModuleImp) => { 345 | val ports: Option[TraceOutputTop] = system.traceIO.map { t => 346 | val trace = IO(DataMirror.internal.chiselTypeClone[TraceOutputTop](t)).suggestName("trace") 347 | trace <> t 348 | trace 349 | } 350 | (ports.toSeq, Nil) 351 | } 352 | }) 353 | 354 | class WithCustomBootPin extends OverrideIOBinder({ 355 | (system: CanHavePeripheryCustomBootPin) => system.custom_boot_pin.map({ p => 356 | val sys = system.asInstanceOf[BaseSubsystem] 357 | val (port, cells) = IOCell.generateIOFromSignal(p.getWrappedValue, "custom_boot", sys.p(IOCellKey), abstractResetAsAsync = true) 358 | (Seq(port), cells) 359 | }).getOrElse((Nil, Nil)) 360 | }) 361 | 362 | class WithDontTouchPorts extends OverrideIOBinder({ 363 | (system: DontTouch) => system.dontTouchPorts(); (Nil, Nil) 364 | }) 365 | 366 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | Preamble 9 | 10 | The GNU General Public License is a free, copyleft license for 11 | software and other kinds of works. 12 | 13 | The licenses for most software and other practical works are designed 14 | to take away your freedom to share and change the works. By contrast, 15 | the GNU General Public License is intended to guarantee your freedom to 16 | share and change all versions of a program--to make sure it remains free 17 | software for all its users. We, the Free Software Foundation, use the 18 | GNU General Public License for most of our software; it applies also to 19 | any other work released this way by its authors. You can apply it to 20 | your programs, too. 21 | 22 | When we speak of free software, we are referring to freedom, not 23 | price. Our General Public Licenses are designed to make sure that you 24 | have the freedom to distribute copies of free software (and charge for 25 | them if you wish), that you receive source code or can get it if you 26 | want it, that you can change the software or use pieces of it in new 27 | free programs, and that you know you can do these things. 28 | 29 | To protect your rights, we need to prevent others from denying you 30 | these rights or asking you to surrender the rights. Therefore, you have 31 | certain responsibilities if you distribute copies of the software, or if 32 | you modify it: responsibilities to respect the freedom of others. 33 | 34 | For example, if you distribute copies of such a program, whether 35 | gratis or for a fee, you must pass on to the recipients the same 36 | freedoms that you received. You must make sure that they, too, receive 37 | or can get the source code. And you must show them these terms so they 38 | know their rights. 39 | 40 | Developers that use the GNU GPL protect your rights with two steps: 41 | (1) assert copyright on the software, and (2) offer you this License 42 | giving you legal permission to copy, distribute and/or modify it. 43 | 44 | For the developers' and authors' protection, the GPL clearly explains 45 | that there is no warranty for this free software. For both users' and 46 | authors' sake, the GPL requires that modified versions be marked as 47 | changed, so that their problems will not be attributed erroneously to 48 | authors of previous versions. 49 | 50 | Some devices are designed to deny users access to install or run 51 | modified versions of the software inside them, although the manufacturer 52 | can do so. This is fundamentally incompatible with the aim of 53 | protecting users' freedom to change the software. The systematic 54 | pattern of such abuse occurs in the area of products for individuals to 55 | use, which is precisely where it is most unacceptable. Therefore, we 56 | have designed this version of the GPL to prohibit the practice for those 57 | products. If such problems arise substantially in other domains, we 58 | stand ready to extend this provision to those domains in future versions 59 | of the GPL, as needed to protect the freedom of users. 60 | 61 | Finally, every program is threatened constantly by software patents. 62 | States should not allow patents to restrict development and use of 63 | software on general-purpose computers, but in those that do, we wish to 64 | avoid the special danger that patents applied to a free program could 65 | make it effectively proprietary. To prevent this, the GPL assures that 66 | patents cannot be used to render the program non-free. 67 | 68 | The precise terms and conditions for copying, distribution and 69 | modification follow. 70 | 71 | TERMS AND CONDITIONS 72 | 73 | 0. Definitions. 74 | 75 | "This License" refers to version 3 of the GNU General Public License. 76 | 77 | "Copyright" also means copyright-like laws that apply to other kinds of 78 | works, such as semiconductor masks. 79 | 80 | "The Program" refers to any copyrightable work licensed under this 81 | License. Each licensee is addressed as "you". "Licensees" and 82 | "recipients" may be individuals or organizations. 83 | 84 | To "modify" a work means to copy from or adapt all or part of the work 85 | in a fashion requiring copyright permission, other than the making of an 86 | exact copy. The resulting work is called a "modified version" of the 87 | earlier work or a work "based on" the earlier work. 88 | 89 | A "covered work" means either the unmodified Program or a work based 90 | on the Program. 91 | 92 | To "propagate" a work means to do anything with it that, without 93 | permission, would make you directly or secondarily liable for 94 | infringement under applicable copyright law, except executing it on a 95 | computer or modifying a private copy. Propagation includes copying, 96 | distribution (with or without modification), making available to the 97 | public, and in some countries other activities as well. 98 | 99 | To "convey" a work means any kind of propagation that enables other 100 | parties to make or receive copies. Mere interaction with a user through 101 | a computer network, with no transfer of a copy, is not conveying. 102 | 103 | An interactive user interface displays "Appropriate Legal Notices" 104 | to the extent that it includes a convenient and prominently visible 105 | feature that (1) displays an appropriate copyright notice, and (2) 106 | tells the user that there is no warranty for the work (except to the 107 | extent that warranties are provided), that licensees may convey the 108 | work under this License, and how to view a copy of this License. If 109 | the interface presents a list of user commands or options, such as a 110 | menu, a prominent item in the list meets this criterion. 111 | 112 | 1. Source Code. 113 | 114 | The "source code" for a work means the preferred form of the work 115 | for making modifications to it. "Object code" means any non-source 116 | form of a work. 117 | 118 | A "Standard Interface" means an interface that either is an official 119 | standard defined by a recognized standards body, or, in the case of 120 | interfaces specified for a particular programming language, one that 121 | is widely used among developers working in that language. 122 | 123 | The "System Libraries" of an executable work include anything, other 124 | than the work as a whole, that (a) is included in the normal form of 125 | packaging a Major Component, but which is not part of that Major 126 | Component, and (b) serves only to enable use of the work with that 127 | Major Component, or to implement a Standard Interface for which an 128 | implementation is available to the public in source code form. A 129 | "Major Component", in this context, means a major essential component 130 | (kernel, window system, and so on) of the specific operating system 131 | (if any) on which the executable work runs, or a compiler used to 132 | produce the work, or an object code interpreter used to run it. 133 | 134 | The "Corresponding Source" for a work in object code form means all 135 | the source code needed to generate, install, and (for an executable 136 | work) run the object code and to modify the work, including scripts to 137 | control those activities. However, it does not include the work's 138 | System Libraries, or general-purpose tools or generally available free 139 | programs which are used unmodified in performing those activities but 140 | which are not part of the work. For example, Corresponding Source 141 | includes interface definition files associated with source files for 142 | the work, and the source code for shared libraries and dynamically 143 | linked subprograms that the work is specifically designed to require, 144 | such as by intimate data communication or control flow between those 145 | subprograms and other parts of the work. 146 | 147 | The Corresponding Source need not include anything that users 148 | can regenerate automatically from other parts of the Corresponding 149 | Source. 150 | 151 | The Corresponding Source for a work in source code form is that 152 | same work. 153 | 154 | 2. Basic Permissions. 155 | 156 | All rights granted under this License are granted for the term of 157 | copyright on the Program, and are irrevocable provided the stated 158 | conditions are met. This License explicitly affirms your unlimited 159 | permission to run the unmodified Program. The output from running a 160 | covered work is covered by this License only if the output, given its 161 | content, constitutes a covered work. This License acknowledges your 162 | rights of fair use or other equivalent, as provided by copyright law. 163 | 164 | You may make, run and propagate covered works that you do not 165 | convey, without conditions so long as your license otherwise remains 166 | in force. You may convey covered works to others for the sole purpose 167 | of having them make modifications exclusively for you, or provide you 168 | with facilities for running those works, provided that you comply with 169 | the terms of this License in conveying all material for which you do 170 | not control copyright. Those thus making or running the covered works 171 | for you must do so exclusively on your behalf, under your direction 172 | and control, on terms that prohibit them from making any copies of 173 | your copyrighted material outside their relationship with you. 174 | 175 | Conveying under any other circumstances is permitted solely under 176 | the conditions stated below. Sublicensing is not allowed; section 10 177 | makes it unnecessary. 178 | 179 | 3. Protecting Users' Legal Rights From Anti-Circumvention Law. 180 | 181 | No covered work shall be deemed part of an effective technological 182 | measure under any applicable law fulfilling obligations under article 183 | 11 of the WIPO copyright treaty adopted on 20 December 1996, or 184 | similar laws prohibiting or restricting circumvention of such 185 | measures. 186 | 187 | When you convey a covered work, you waive any legal power to forbid 188 | circumvention of technological measures to the extent such circumvention 189 | is effected by exercising rights under this License with respect to 190 | the covered work, and you disclaim any intention to limit operation or 191 | modification of the work as a means of enforcing, against the work's 192 | users, your or third parties' legal rights to forbid circumvention of 193 | technological measures. 194 | 195 | 4. Conveying Verbatim Copies. 196 | 197 | You may convey verbatim copies of the Program's source code as you 198 | receive it, in any medium, provided that you conspicuously and 199 | appropriately publish on each copy an appropriate copyright notice; 200 | keep intact all notices stating that this License and any 201 | non-permissive terms added in accord with section 7 apply to the code; 202 | keep intact all notices of the absence of any warranty; and give all 203 | recipients a copy of this License along with the Program. 204 | 205 | You may charge any price or no price for each copy that you convey, 206 | and you may offer support or warranty protection for a fee. 207 | 208 | 5. Conveying Modified Source Versions. 209 | 210 | You may convey a work based on the Program, or the modifications to 211 | produce it from the Program, in the form of source code under the 212 | terms of section 4, provided that you also meet all of these conditions: 213 | 214 | a) The work must carry prominent notices stating that you modified 215 | it, and giving a relevant date. 216 | 217 | b) The work must carry prominent notices stating that it is 218 | released under this License and any conditions added under section 219 | 7. This requirement modifies the requirement in section 4 to 220 | "keep intact all notices". 221 | 222 | c) You must license the entire work, as a whole, under this 223 | License to anyone who comes into possession of a copy. This 224 | License will therefore apply, along with any applicable section 7 225 | additional terms, to the whole of the work, and all its parts, 226 | regardless of how they are packaged. This License gives no 227 | permission to license the work in any other way, but it does not 228 | invalidate such permission if you have separately received it. 229 | 230 | d) If the work has interactive user interfaces, each must display 231 | Appropriate Legal Notices; however, if the Program has interactive 232 | interfaces that do not display Appropriate Legal Notices, your 233 | work need not make them do so. 234 | 235 | A compilation of a covered work with other separate and independent 236 | works, which are not by their nature extensions of the covered work, 237 | and which are not combined with it such as to form a larger program, 238 | in or on a volume of a storage or distribution medium, is called an 239 | "aggregate" if the compilation and its resulting copyright are not 240 | used to limit the access or legal rights of the compilation's users 241 | beyond what the individual works permit. Inclusion of a covered work 242 | in an aggregate does not cause this License to apply to the other 243 | parts of the aggregate. 244 | 245 | 6. Conveying Non-Source Forms. 246 | 247 | You may convey a covered work in object code form under the terms 248 | of sections 4 and 5, provided that you also convey the 249 | machine-readable Corresponding Source under the terms of this License, 250 | in one of these ways: 251 | 252 | a) Convey the object code in, or embodied in, a physical product 253 | (including a physical distribution medium), accompanied by the 254 | Corresponding Source fixed on a durable physical medium 255 | customarily used for software interchange. 256 | 257 | b) Convey the object code in, or embodied in, a physical product 258 | (including a physical distribution medium), accompanied by a 259 | written offer, valid for at least three years and valid for as 260 | long as you offer spare parts or customer support for that product 261 | model, to give anyone who possesses the object code either (1) a 262 | copy of the Corresponding Source for all the software in the 263 | product that is covered by this License, on a durable physical 264 | medium customarily used for software interchange, for a price no 265 | more than your reasonable cost of physically performing this 266 | conveying of source, or (2) access to copy the 267 | Corresponding Source from a network server at no charge. 268 | 269 | c) Convey individual copies of the object code with a copy of the 270 | written offer to provide the Corresponding Source. This 271 | alternative is allowed only occasionally and noncommercially, and 272 | only if you received the object code with such an offer, in accord 273 | with subsection 6b. 274 | 275 | d) Convey the object code by offering access from a designated 276 | place (gratis or for a charge), and offer equivalent access to the 277 | Corresponding Source in the same way through the same place at no 278 | further charge. You need not require recipients to copy the 279 | Corresponding Source along with the object code. If the place to 280 | copy the object code is a network server, the Corresponding Source 281 | may be on a different server (operated by you or a third party) 282 | that supports equivalent copying facilities, provided you maintain 283 | clear directions next to the object code saying where to find the 284 | Corresponding Source. Regardless of what server hosts the 285 | Corresponding Source, you remain obligated to ensure that it is 286 | available for as long as needed to satisfy these requirements. 287 | 288 | e) Convey the object code using peer-to-peer transmission, provided 289 | you inform other peers where the object code and Corresponding 290 | Source of the work are being offered to the general public at no 291 | charge under subsection 6d. 292 | 293 | A separable portion of the object code, whose source code is excluded 294 | from the Corresponding Source as a System Library, need not be 295 | included in conveying the object code work. 296 | 297 | A "User Product" is either (1) a "consumer product", which means any 298 | tangible personal property which is normally used for personal, family, 299 | or household purposes, or (2) anything designed or sold for incorporation 300 | into a dwelling. In determining whether a product is a consumer product, 301 | doubtful cases shall be resolved in favor of coverage. For a particular 302 | product received by a particular user, "normally used" refers to a 303 | typical or common use of that class of product, regardless of the status 304 | of the particular user or of the way in which the particular user 305 | actually uses, or expects or is expected to use, the product. A product 306 | is a consumer product regardless of whether the product has substantial 307 | commercial, industrial or non-consumer uses, unless such uses represent 308 | the only significant mode of use of the product. 309 | 310 | "Installation Information" for a User Product means any methods, 311 | procedures, authorization keys, or other information required to install 312 | and execute modified versions of a covered work in that User Product from 313 | a modified version of its Corresponding Source. The information must 314 | suffice to ensure that the continued functioning of the modified object 315 | code is in no case prevented or interfered with solely because 316 | modification has been made. 317 | 318 | If you convey an object code work under this section in, or with, or 319 | specifically for use in, a User Product, and the conveying occurs as 320 | part of a transaction in which the right of possession and use of the 321 | User Product is transferred to the recipient in perpetuity or for a 322 | fixed term (regardless of how the transaction is characterized), the 323 | Corresponding Source conveyed under this section must be accompanied 324 | by the Installation Information. But this requirement does not apply 325 | if neither you nor any third party retains the ability to install 326 | modified object code on the User Product (for example, the work has 327 | been installed in ROM). 328 | 329 | The requirement to provide Installation Information does not include a 330 | requirement to continue to provide support service, warranty, or updates 331 | for a work that has been modified or installed by the recipient, or for 332 | the User Product in which it has been modified or installed. Access to a 333 | network may be denied when the modification itself materially and 334 | adversely affects the operation of the network or violates the rules and 335 | protocols for communication across the network. 336 | 337 | Corresponding Source conveyed, and Installation Information provided, 338 | in accord with this section must be in a format that is publicly 339 | documented (and with an implementation available to the public in 340 | source code form), and must require no special password or key for 341 | unpacking, reading or copying. 342 | 343 | 7. Additional Terms. 344 | 345 | "Additional permissions" are terms that supplement the terms of this 346 | License by making exceptions from one or more of its conditions. 347 | Additional permissions that are applicable to the entire Program shall 348 | be treated as though they were included in this License, to the extent 349 | that they are valid under applicable law. If additional permissions 350 | apply only to part of the Program, that part may be used separately 351 | under those permissions, but the entire Program remains governed by 352 | this License without regard to the additional permissions. 353 | 354 | When you convey a copy of a covered work, you may at your option 355 | remove any additional permissions from that copy, or from any part of 356 | it. (Additional permissions may be written to require their own 357 | removal in certain cases when you modify the work.) You may place 358 | additional permissions on material, added by you to a covered work, 359 | for which you have or can give appropriate copyright permission. 360 | 361 | Notwithstanding any other provision of this License, for material you 362 | add to a covered work, you may (if authorized by the copyright holders of 363 | that material) supplement the terms of this License with terms: 364 | 365 | a) Disclaiming warranty or limiting liability differently from the 366 | terms of sections 15 and 16 of this License; or 367 | 368 | b) Requiring preservation of specified reasonable legal notices or 369 | author attributions in that material or in the Appropriate Legal 370 | Notices displayed by works containing it; or 371 | 372 | c) Prohibiting misrepresentation of the origin of that material, or 373 | requiring that modified versions of such material be marked in 374 | reasonable ways as different from the original version; or 375 | 376 | d) Limiting the use for publicity purposes of names of licensors or 377 | authors of the material; or 378 | 379 | e) Declining to grant rights under trademark law for use of some 380 | trade names, trademarks, or service marks; or 381 | 382 | f) Requiring indemnification of licensors and authors of that 383 | material by anyone who conveys the material (or modified versions of 384 | it) with contractual assumptions of liability to the recipient, for 385 | any liability that these contractual assumptions directly impose on 386 | those licensors and authors. 387 | 388 | All other non-permissive additional terms are considered "further 389 | restrictions" within the meaning of section 10. If the Program as you 390 | received it, or any part of it, contains a notice stating that it is 391 | governed by this License along with a term that is a further 392 | restriction, you may remove that term. If a license document contains 393 | a further restriction but permits relicensing or conveying under this 394 | License, you may add to a covered work material governed by the terms 395 | of that license document, provided that the further restriction does 396 | not survive such relicensing or conveying. 397 | 398 | If you add terms to a covered work in accord with this section, you 399 | must place, in the relevant source files, a statement of the 400 | additional terms that apply to those files, or a notice indicating 401 | where to find the applicable terms. 402 | 403 | Additional terms, permissive or non-permissive, may be stated in the 404 | form of a separately written license, or stated as exceptions; 405 | the above requirements apply either way. 406 | 407 | 8. Termination. 408 | 409 | You may not propagate or modify a covered work except as expressly 410 | provided under this License. Any attempt otherwise to propagate or 411 | modify it is void, and will automatically terminate your rights under 412 | this License (including any patent licenses granted under the third 413 | paragraph of section 11). 414 | 415 | However, if you cease all violation of this License, then your 416 | license from a particular copyright holder is reinstated (a) 417 | provisionally, unless and until the copyright holder explicitly and 418 | finally terminates your license, and (b) permanently, if the copyright 419 | holder fails to notify you of the violation by some reasonable means 420 | prior to 60 days after the cessation. 421 | 422 | Moreover, your license from a particular copyright holder is 423 | reinstated permanently if the copyright holder notifies you of the 424 | violation by some reasonable means, this is the first time you have 425 | received notice of violation of this License (for any work) from that 426 | copyright holder, and you cure the violation prior to 30 days after 427 | your receipt of the notice. 428 | 429 | Termination of your rights under this section does not terminate the 430 | licenses of parties who have received copies or rights from you under 431 | this License. If your rights have been terminated and not permanently 432 | reinstated, you do not qualify to receive new licenses for the same 433 | material under section 10. 434 | 435 | 9. Acceptance Not Required for Having Copies. 436 | 437 | You are not required to accept this License in order to receive or 438 | run a copy of the Program. Ancillary propagation of a covered work 439 | occurring solely as a consequence of using peer-to-peer transmission 440 | to receive a copy likewise does not require acceptance. However, 441 | nothing other than this License grants you permission to propagate or 442 | modify any covered work. These actions infringe copyright if you do 443 | not accept this License. Therefore, by modifying or propagating a 444 | covered work, you indicate your acceptance of this License to do so. 445 | 446 | 10. Automatic Licensing of Downstream Recipients. 447 | 448 | Each time you convey a covered work, the recipient automatically 449 | receives a license from the original licensors, to run, modify and 450 | propagate that work, subject to this License. You are not responsible 451 | for enforcing compliance by third parties with this License. 452 | 453 | An "entity transaction" is a transaction transferring control of an 454 | organization, or substantially all assets of one, or subdividing an 455 | organization, or merging organizations. If propagation of a covered 456 | work results from an entity transaction, each party to that 457 | transaction who receives a copy of the work also receives whatever 458 | licenses to the work the party's predecessor in interest had or could 459 | give under the previous paragraph, plus a right to possession of the 460 | Corresponding Source of the work from the predecessor in interest, if 461 | the predecessor has it or can get it with reasonable efforts. 462 | 463 | You may not impose any further restrictions on the exercise of the 464 | rights granted or affirmed under this License. For example, you may 465 | not impose a license fee, royalty, or other charge for exercise of 466 | rights granted under this License, and you may not initiate litigation 467 | (including a cross-claim or counterclaim in a lawsuit) alleging that 468 | any patent claim is infringed by making, using, selling, offering for 469 | sale, or importing the Program or any portion of it. 470 | 471 | 11. Patents. 472 | 473 | A "contributor" is a copyright holder who authorizes use under this 474 | License of the Program or a work on which the Program is based. The 475 | work thus licensed is called the contributor's "contributor version". 476 | 477 | A contributor's "essential patent claims" are all patent claims 478 | owned or controlled by the contributor, whether already acquired or 479 | hereafter acquired, that would be infringed by some manner, permitted 480 | by this License, of making, using, or selling its contributor version, 481 | but do not include claims that would be infringed only as a 482 | consequence of further modification of the contributor version. For 483 | purposes of this definition, "control" includes the right to grant 484 | patent sublicenses in a manner consistent with the requirements of 485 | this License. 486 | 487 | Each contributor grants you a non-exclusive, worldwide, royalty-free 488 | patent license under the contributor's essential patent claims, to 489 | make, use, sell, offer for sale, import and otherwise run, modify and 490 | propagate the contents of its contributor version. 491 | 492 | In the following three paragraphs, a "patent license" is any express 493 | agreement or commitment, however denominated, not to enforce a patent 494 | (such as an express permission to practice a patent or covenant not to 495 | sue for patent infringement). To "grant" such a patent license to a 496 | party means to make such an agreement or commitment not to enforce a 497 | patent against the party. 498 | 499 | If you convey a covered work, knowingly relying on a patent license, 500 | and the Corresponding Source of the work is not available for anyone 501 | to copy, free of charge and under the terms of this License, through a 502 | publicly available network server or other readily accessible means, 503 | then you must either (1) cause the Corresponding Source to be so 504 | available, or (2) arrange to deprive yourself of the benefit of the 505 | patent license for this particular work, or (3) arrange, in a manner 506 | consistent with the requirements of this License, to extend the patent 507 | license to downstream recipients. "Knowingly relying" means you have 508 | actual knowledge that, but for the patent license, your conveying the 509 | covered work in a country, or your recipient's use of the covered work 510 | in a country, would infringe one or more identifiable patents in that 511 | country that you have reason to believe are valid. 512 | 513 | If, pursuant to or in connection with a single transaction or 514 | arrangement, you convey, or propagate by procuring conveyance of, a 515 | covered work, and grant a patent license to some of the parties 516 | receiving the covered work authorizing them to use, propagate, modify 517 | or convey a specific copy of the covered work, then the patent license 518 | you grant is automatically extended to all recipients of the covered 519 | work and works based on it. 520 | 521 | A patent license is "discriminatory" if it does not include within 522 | the scope of its coverage, prohibits the exercise of, or is 523 | conditioned on the non-exercise of one or more of the rights that are 524 | specifically granted under this License. You may not convey a covered 525 | work if you are a party to an arrangement with a third party that is 526 | in the business of distributing software, under which you make payment 527 | to the third party based on the extent of your activity of conveying 528 | the work, and under which the third party grants, to any of the 529 | parties who would receive the covered work from you, a discriminatory 530 | patent license (a) in connection with copies of the covered work 531 | conveyed by you (or copies made from those copies), or (b) primarily 532 | for and in connection with specific products or compilations that 533 | contain the covered work, unless you entered into that arrangement, 534 | or that patent license was granted, prior to 28 March 2007. 535 | 536 | Nothing in this License shall be construed as excluding or limiting 537 | any implied license or other defenses to infringement that may 538 | otherwise be available to you under applicable patent law. 539 | 540 | 12. No Surrender of Others' Freedom. 541 | 542 | If conditions are imposed on you (whether by court order, agreement or 543 | otherwise) that contradict the conditions of this License, they do not 544 | excuse you from the conditions of this License. If you cannot convey a 545 | covered work so as to satisfy simultaneously your obligations under this 546 | License and any other pertinent obligations, then as a consequence you may 547 | not convey it at all. For example, if you agree to terms that obligate you 548 | to collect a royalty for further conveying from those to whom you convey 549 | the Program, the only way you could satisfy both those terms and this 550 | License would be to refrain entirely from conveying the Program. 551 | 552 | 13. Use with the GNU Affero General Public License. 553 | 554 | Notwithstanding any other provision of this License, you have 555 | permission to link or combine any covered work with a work licensed 556 | under version 3 of the GNU Affero General Public License into a single 557 | combined work, and to convey the resulting work. The terms of this 558 | License will continue to apply to the part which is the covered work, 559 | but the special requirements of the GNU Affero General Public License, 560 | section 13, concerning interaction through a network will apply to the 561 | combination as such. 562 | 563 | 14. Revised Versions of this License. 564 | 565 | The Free Software Foundation may publish revised and/or new versions of 566 | the GNU General Public License from time to time. Such new versions will 567 | be similar in spirit to the present version, but may differ in detail to 568 | address new problems or concerns. 569 | 570 | Each version is given a distinguishing version number. If the 571 | Program specifies that a certain numbered version of the GNU General 572 | Public License "or any later version" applies to it, you have the 573 | option of following the terms and conditions either of that numbered 574 | version or of any later version published by the Free Software 575 | Foundation. If the Program does not specify a version number of the 576 | GNU General Public License, you may choose any version ever published 577 | by the Free Software Foundation. 578 | 579 | If the Program specifies that a proxy can decide which future 580 | versions of the GNU General Public License can be used, that proxy's 581 | public statement of acceptance of a version permanently authorizes you 582 | to choose that version for the Program. 583 | 584 | Later license versions may give you additional or different 585 | permissions. However, no additional obligations are imposed on any 586 | author or copyright holder as a result of your choosing to follow a 587 | later version. 588 | 589 | 15. Disclaimer of Warranty. 590 | 591 | THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY 592 | APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT 593 | HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY 594 | OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, 595 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 596 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM 597 | IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF 598 | ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 599 | 600 | 16. Limitation of Liability. 601 | 602 | IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 603 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS 604 | THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY 605 | GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE 606 | USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF 607 | DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD 608 | PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), 609 | EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF 610 | SUCH DAMAGES. 611 | 612 | 17. Interpretation of Sections 15 and 16. 613 | 614 | If the disclaimer of warranty and limitation of liability provided 615 | above cannot be given local legal effect according to their terms, 616 | reviewing courts shall apply local law that most closely approximates 617 | an absolute waiver of all civil liability in connection with the 618 | Program, unless a warranty or assumption of liability accompanies a 619 | copy of the Program in return for a fee. 620 | 621 | END OF TERMS AND CONDITIONS 622 | 623 | How to Apply These Terms to Your New Programs 624 | 625 | If you develop a new program, and you want it to be of the greatest 626 | possible use to the public, the best way to achieve this is to make it 627 | free software which everyone can redistribute and change under these terms. 628 | 629 | To do so, attach the following notices to the program. It is safest 630 | to attach them to the start of each source file to most effectively 631 | state the exclusion of warranty; and each file should have at least 632 | the "copyright" line and a pointer to where the full notice is found. 633 | 634 | CoolPepper 635 | Copyright (C) 2018 ustb-nscscc-team 636 | 637 | This program is free software: you can redistribute it and/or modify 638 | it under the terms of the GNU General Public License as published by 639 | the Free Software Foundation, either version 3 of the License, or 640 | (at your option) any later version. 641 | 642 | This program is distributed in the hope that it will be useful, 643 | but WITHOUT ANY WARRANTY; without even the implied warranty of 644 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 645 | GNU General Public License for more details. 646 | 647 | You should have received a copy of the GNU General Public License 648 | along with this program. If not, see . 649 | 650 | Also add information on how to contact you by electronic and paper mail. 651 | 652 | If the program does terminal interaction, make it output a short 653 | notice like this when it starts in an interactive mode: 654 | 655 | CoolPepper Copyright (C) 2018 ustb-nscscc-team 656 | This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 657 | This is free software, and you are welcome to redistribute it 658 | under certain conditions; type `show c' for details. 659 | 660 | The hypothetical commands `show w' and `show c' should show the appropriate 661 | parts of the General Public License. Of course, your program's commands 662 | might be different; for a GUI interface, you would use an "about box". 663 | 664 | You should also get your employer (if you work as a programmer) or school, 665 | if any, to sign a "copyright disclaimer" for the program, if necessary. 666 | For more information on this, and how to apply and follow the GNU GPL, see 667 | . 668 | 669 | The GNU General Public License does not permit incorporating your program 670 | into proprietary programs. If your program is a subroutine library, you 671 | may consider it more useful to permit linking proprietary applications with 672 | the library. If this is what you want to do, use the GNU Lesser General 673 | Public License instead of this License. But first, please read 674 | . 675 | --------------------------------------------------------------------------------