├── .github ├── ISSUE_TEMPLATE.md ├── PULL_REQUEST_TEMPLATE.md └── workflows │ ├── apt-packages.txt │ └── mill-ci.yml ├── .gitignore ├── .gitmodules ├── .mergify.yml ├── .scalafix.conf ├── CHANGELOG.md ├── CONTRIBUTING.md ├── LICENSE.Berkeley ├── LICENSE.SiFive ├── LICENSE.jtag ├── Makefile ├── README.md ├── README_GITHUB_ACTIONS.md ├── RocketChip_Technical_Charter_8-23-2024.pdf ├── bootrom ├── .gitignore ├── Makefile ├── bootrom.S ├── bootrom.img └── linker.ld ├── build.sc ├── common.sc ├── docs ├── README.md └── src │ └── diplomacy │ ├── adder_tutorial.md │ ├── diagrams │ ├── adder_modules.pdf │ ├── adder_nodes.pdf │ └── edge_inout.pdf │ └── select_tutorial.md ├── flake.lock ├── flake.nix ├── macros └── src │ └── main │ └── scala │ └── ValName.scala ├── overlay.nix ├── regression ├── .gitignore ├── Makefile └── run-test-bucket ├── riscv-tools.hash ├── scripts ├── .gitignore ├── Makefile ├── RocketSim.cfg ├── RocketSim.py ├── RocketSim32.py ├── RocketSim64.py ├── arch-test │ ├── emulator │ │ ├── env │ │ │ ├── link.ld │ │ │ └── model_test.h │ │ └── riscof_emulator.py │ └── spike │ │ ├── env │ │ ├── link.ld │ │ └── model_test.h │ │ └── riscof_spike.py ├── authors ├── check_cache_trace.py ├── check_comparator_trace.py ├── copyright-file ├── debug_rom │ ├── .gitignore │ ├── Makefile │ ├── debug_rom.S │ ├── debug_rom_nonzero.S │ └── link.ld ├── modify-copyright ├── toaxe.py ├── tracegen+check.sh ├── tracegen.py ├── tracestats.py ├── vlsi_mem_gen └── vlsi_rom_gen ├── src └── main │ ├── resources │ ├── csrc │ │ ├── SimDTM.cc │ │ ├── SimJTAG.cc │ │ ├── comlog.cc │ │ ├── debug_rob.cc │ │ ├── emulator.cc │ │ ├── float_fix.cc │ │ ├── remote_bitbang.cc │ │ ├── remote_bitbang.h │ │ └── verilator.h │ └── vsrc │ │ ├── AsyncResetReg.v │ │ ├── ClockDivider2.v │ │ ├── ClockDivider3.v │ │ ├── EICG_wrapper.v │ │ ├── RoccBlackBox.v │ │ ├── SimDTM.v │ │ ├── SimJTAG.v │ │ ├── TestDriver.v │ │ ├── TraceSinkMonitor.v │ │ ├── debug_rob.v │ │ └── plusarg_reader.v │ └── scala │ ├── amba │ ├── ahb │ │ ├── AHBLite.scala │ │ ├── Bundles.scala │ │ ├── Monitor.scala │ │ ├── Nodes.scala │ │ ├── Parameters.scala │ │ ├── Protocol.scala │ │ ├── RegisterRouter.scala │ │ ├── SRAM.scala │ │ ├── Test.scala │ │ ├── ToTL.scala │ │ ├── Xbar.scala │ │ └── package.scala │ ├── apb │ │ ├── Bundles.scala │ │ ├── Monitor.scala │ │ ├── Nodes.scala │ │ ├── Parameters.scala │ │ ├── Protocol.scala │ │ ├── RegisterRouter.scala │ │ ├── SRAM.scala │ │ ├── Test.scala │ │ ├── ToTL.scala │ │ ├── Xbar.scala │ │ └── package.scala │ ├── axi4 │ │ ├── AsyncCrossing.scala │ │ ├── Buffer.scala │ │ ├── Bundles.scala │ │ ├── Credited.scala │ │ ├── CrossingHelper.scala │ │ ├── Deinterleaver.scala │ │ ├── Delayer.scala │ │ ├── Filter.scala │ │ ├── Fragmenter.scala │ │ ├── IdIndexer.scala │ │ ├── Monitor.scala │ │ ├── Nodes.scala │ │ ├── Parameters.scala │ │ ├── Protocol.scala │ │ ├── RegisterRouter.scala │ │ ├── SRAM.scala │ │ ├── Test.scala │ │ ├── ToTL.scala │ │ ├── UserYanker.scala │ │ ├── Xbar.scala │ │ └── package.scala │ ├── axis │ │ ├── Buffer.scala │ │ ├── Bundles.scala │ │ ├── Nodes.scala │ │ ├── Parameters.scala │ │ ├── Xbar.scala │ │ └── package.scala │ └── package.scala │ ├── aop │ └── package.scala │ ├── devices │ ├── debug │ │ ├── APB.scala │ │ ├── Custom.scala │ │ ├── DMI.scala │ │ ├── Debug.scala │ │ ├── DebugRomContents.scala │ │ ├── DebugRomNonzeroContents.scala │ │ ├── DebugTransport.scala │ │ ├── Periphery.scala │ │ ├── SBA.scala │ │ ├── abstract_commands.scala │ │ └── dm_registers.scala │ └── tilelink │ │ ├── BootROM.scala │ │ ├── BusBlocker.scala │ │ ├── BusBypass.scala │ │ ├── CLINT.scala │ │ ├── CanHaveBuiltInDevices.scala │ │ ├── ClockBlocker.scala │ │ ├── Deadlock.scala │ │ ├── DevNull.scala │ │ ├── Error.scala │ │ ├── MaskROM.scala │ │ ├── MasterMux.scala │ │ ├── PhysicalFilter.scala │ │ ├── Plic.scala │ │ ├── TestRAM.scala │ │ └── Zero.scala │ ├── diplomacy │ ├── AddressDecoder.scala │ ├── AddressRange.scala │ ├── CloneModule.scala │ ├── Main.scala │ ├── Parameters.scala │ ├── Unreachable.scala │ └── package.scala │ ├── examples │ └── ExampleDevice.scala │ ├── formal │ └── FormalUtils.scala │ ├── groundtest │ ├── Configs.scala │ ├── DummyPTW.scala │ ├── GroundTestSubsystem.scala │ ├── Package.scala │ ├── Status.scala │ ├── TestHarness.scala │ ├── Tile.scala │ └── TraceGen.scala │ ├── interrupts │ ├── BlockDuringReset.scala │ ├── Bundles.scala │ ├── Crossing.scala │ ├── CrossingHelper.scala │ ├── Nodes.scala │ ├── NullIntSource.scala │ ├── Parameters.scala │ ├── RegisterRouter.scala │ ├── Xbar.scala │ └── package.scala │ ├── jtag │ ├── JtagShifter.scala │ ├── JtagStateMachine.scala │ ├── JtagTap.scala │ ├── JtagUtils.scala │ ├── Utils.scala │ └── package.scala │ ├── prci │ ├── BundleBridgeBlockDuringReset.scala │ ├── ClockBundles.scala │ ├── ClockCrossingType.scala │ ├── ClockDivider.scala │ ├── ClockDomain.scala │ ├── ClockGroup.scala │ ├── ClockNodes.scala │ ├── ClockParameters.scala │ ├── IOHelper.scala │ ├── ResetCrossingType.scala │ ├── ResetStretcher.scala │ ├── ResetSynchronizer.scala │ ├── ResetWrangler.scala │ ├── TestClockSource.scala │ └── package.scala │ ├── regmapper │ ├── Annotation.scala │ ├── DescribedReg.scala │ ├── RegField.scala │ ├── RegFieldDesc.scala │ ├── RegMapper.scala │ ├── RegisterCrossing.scala │ ├── RegisterRouter.scala │ └── Test.scala │ ├── resources │ ├── AddressMapEntry.scala │ ├── DeviceTree.scala │ ├── FixedClockResource.scala │ ├── JSON.scala │ ├── Resources.scala │ ├── SRAM.scala │ └── package.scala │ ├── rocket │ ├── ALU.scala │ ├── AMOALU.scala │ ├── BTB.scala │ ├── Breakpoint.scala │ ├── CSR.scala │ ├── Configs.scala │ ├── Consts.scala │ ├── CustomInstructions.scala │ ├── DCache.scala │ ├── DebugROB.scala │ ├── Decode.scala │ ├── Events.scala │ ├── Frontend.scala │ ├── HellaCache.scala │ ├── HellaCacheArbiter.scala │ ├── IBuf.scala │ ├── ICache.scala │ ├── IDecode.scala │ ├── Instructions.scala │ ├── Instructions32.scala │ ├── Multiplier.scala │ ├── NBDcache.scala │ ├── PMA.scala │ ├── PMP.scala │ ├── PTW.scala │ ├── RVC.scala │ ├── RocketCore.scala │ ├── ScratchpadSlavePort.scala │ ├── SimpleHellaCacheIF.scala │ ├── TLB.scala │ ├── TLBPermissions.scala │ ├── VectorUnit.scala │ └── package.scala │ ├── subsystem │ ├── Attachable.scala │ ├── BankedCoherenceParams.scala │ ├── BaseSubsystem.scala │ ├── BusTopology.scala │ ├── Cluster.scala │ ├── Configs.scala │ ├── CrossingWrapper.scala │ ├── FrontBus.scala │ ├── HasHierarchicalElements.scala │ ├── HasTiles.scala │ ├── HierarchicalElement.scala │ ├── HierarchicalElementPRCIDomain.scala │ ├── InterruptBus.scala │ ├── Litex.scala │ ├── LookupByClusterId.scala │ ├── MemoryBus.scala │ ├── PeripheryBus.scala │ ├── Ports.scala │ ├── RTC.scala │ ├── RocketSubsystem.scala │ └── SystemBus.scala │ ├── system │ ├── Configs.scala │ ├── ExampleRocketSystem.scala │ ├── Litex.scala │ ├── RocketTestSuite.scala │ ├── SimAXIMem.scala │ └── TestHarness.scala │ ├── tile │ ├── BaseTile.scala │ ├── BusErrorUnit.scala │ ├── Core.scala │ ├── CustomCSRs.scala │ ├── FPU.scala │ ├── Interrupts.scala │ ├── L1Cache.scala │ ├── LazyRoCC.scala │ ├── LookupByHartId.scala │ ├── RocketTile.scala │ └── TilePRCIDomain.scala │ ├── tilelink │ ├── AddressAdjuster.scala │ ├── Arbiter.scala │ ├── AsyncCrossing.scala │ ├── AtomicAutomata.scala │ ├── Atomics.scala │ ├── BankBinder.scala │ ├── BlockDuringReset.scala │ ├── Broadcast.scala │ ├── Buffer.scala │ ├── Bundles.scala │ ├── BusWrapper.scala │ ├── CacheCork.scala │ ├── Credited.scala │ ├── CrossingHelper.scala │ ├── Delayer.scala │ ├── Edges.scala │ ├── ErrorEvaluator.scala │ ├── FIFOFixer.scala │ ├── Filter.scala │ ├── Fragmenter.scala │ ├── Fuzzer.scala │ ├── HintHandler.scala │ ├── Isolation.scala │ ├── Jbar.scala │ ├── Map.scala │ ├── Metadata.scala │ ├── Monitor.scala │ ├── Nodes.scala │ ├── Parameters.scala │ ├── PatternPusher.scala │ ├── ProbePicker.scala │ ├── RAMModel.scala │ ├── RationalCrossing.scala │ ├── RegionReplication.scala │ ├── RegisterRouter.scala │ ├── RegisterRouterTest.scala │ ├── SRAM.scala │ ├── SourceShrinker.scala │ ├── ToAHB.scala │ ├── ToAPB.scala │ ├── ToAXI4.scala │ ├── WidthWidget.scala │ ├── Xbar.scala │ └── package.scala │ ├── trace │ ├── TraceCoreIngress.scala │ ├── TraceCoreInterface.scala │ ├── TraceEncoder.scala │ ├── TraceEncoderController.scala │ ├── TraceSink.scala │ ├── TraceSinkArbiter.scala │ └── TraceSinkMonitor.scala │ ├── unittest │ ├── Configs.scala │ ├── TestGenerator.scala │ ├── TestHarness.scala │ ├── UnitTest.scala │ └── package.scala │ └── util │ ├── Annotations.scala │ ├── Arbiters.scala │ ├── AsyncQueue.scala │ ├── AsyncResetReg.scala │ ├── BarrelShifter.scala │ ├── BlockDuringReset.scala │ ├── Blockable.scala │ ├── Broadcaster.scala │ ├── BundleMap.scala │ ├── CRC.scala │ ├── ClockDivider.scala │ ├── ClockGate.scala │ ├── CoreMonitor.scala │ ├── Counters.scala │ ├── CreditedIO.scala │ ├── Crossing.scala │ ├── DelayQueue.scala │ ├── DescribedSRAM.scala │ ├── ECC.scala │ ├── ElaborationArtefactAnnotation.scala │ ├── Frequency.scala │ ├── GeneratorUtils.scala │ ├── GenericParameterizedBundle.scala │ ├── HellaQueue.scala │ ├── IDPool.scala │ ├── IdentityModule.scala │ ├── LCG.scala │ ├── LanePositionedQueue.scala │ ├── LatencyPipe.scala │ ├── Location.scala │ ├── Misc.scala │ ├── MultiLaneQueue.scala │ ├── MultiPortQueue.scala │ ├── MultiWidthFifo.scala │ ├── MuxLiteral.scala │ ├── PSDTestMode.scala │ ├── PlusArg.scala │ ├── PrefixSum.scala │ ├── Property.scala │ ├── ROMGenerator.scala │ ├── RationalCrossing.scala │ ├── RecordMap.scala │ ├── ReduceOthers.scala │ ├── ReorderQueue.scala │ ├── Repeater.scala │ ├── Replacement.scala │ ├── ResetCatchAndSync.scala │ ├── ScatterGather.scala │ ├── SeededRandom.scala │ ├── ShiftQueue.scala │ ├── ShiftReg.scala │ ├── SimpleProduct.scala │ ├── SynchronizerReg.scala │ ├── Timer.scala │ └── package.scala └── verilator.hash /.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | **Type of issue**: bug report | feature request | other enhancement 8 | 9 | 10 | **Impact**: no functional change | API addition (no impact on existing code) | API modification | unknown 11 | 12 | 13 | **Development Phase**: request | proposal 14 | 15 | **Other information** 16 | 17 | 18 | **If the current behavior is a bug, please provide the steps to reproduce the problem:** 19 | 20 | **What is the current behavior?** 21 | 22 | **What is the expected behavior?** 23 | 24 | **Please tell us about your environment:** 25 | 29 | **What is the use case for changing the behavior?** 30 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 4 | **Related issue**: 5 | 6 | 7 | **Type of change**: bug report | feature request | other enhancement 8 | 9 | 10 | **Impact**: no functional change | API addition (no impact on existing code) | API modification 11 | 12 | 13 | **Development Phase**: proposal | implementation 14 | 15 | **Release Notes** 16 | 19 | -------------------------------------------------------------------------------- /.github/workflows/apt-packages.txt: -------------------------------------------------------------------------------- 1 | autoconf 2 | automake 3 | autotools-dev 4 | bison 5 | build-essential 6 | device-tree-compiler 7 | flex 8 | gawk 9 | gperf 10 | libfl-dev 11 | libgmp-dev 12 | libmpc-dev 13 | libmpfr-dev 14 | libusb-1.0-0-dev 15 | texinfo 16 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | out/ 2 | target/ 3 | project/target 4 | docs/generated 5 | docs-target/ 6 | *.fir 7 | *.v 8 | *.anno.json 9 | *.swp 10 | *~ 11 | .addons-dont-touch 12 | /lib/ 13 | /test_lib/ 14 | /testbuild/ 15 | rocketchip.jar 16 | *# 17 | .#* -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "dependencies/hardfloat"] 2 | path = dependencies/hardfloat 3 | url = https://github.com/ucb-bar/berkeley-hardfloat.git 4 | [submodule "dependencies/cde"] 5 | path = dependencies/cde 6 | url = https://github.com/chipsalliance/cde.git 7 | [submodule "dependencies/chisel"] 8 | path = dependencies/chisel 9 | url = https://github.com/chipsalliance/chisel.git 10 | [submodule "dependencies/diplomacy"] 11 | path = dependencies/diplomacy 12 | url = https://github.com/chipsalliance/diplomacy.git 13 | branch = master 14 | -------------------------------------------------------------------------------- /.mergify.yml: -------------------------------------------------------------------------------- 1 | pull_request_rules: 2 | - name: backport to master 3 | conditions: 4 | - merged 5 | - base=dev 6 | - label=backport 7 | actions: 8 | backport: 9 | branches: 10 | - master 11 | labels: 12 | - backporting 13 | ignore_conflicts: true 14 | -------------------------------------------------------------------------------- /.scalafix.conf: -------------------------------------------------------------------------------- 1 | rules = [ 2 | // RemoveUnused, 3 | DisableSyntax, 4 | LeakingImplicitClassVal, 5 | NoAutoTupling, 6 | NoValInForComprehension, 7 | ProcedureSyntax, 8 | ] 9 | -------------------------------------------------------------------------------- /LICENSE.Berkeley: -------------------------------------------------------------------------------- 1 | Copyright (c) 2012-2014, The Regents of the University of California 2 | (Regents). All Rights Reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 1. Redistributions of source code must retain the above copyright 7 | notice, this list of conditions and the following disclaimer. 8 | 2. Redistributions in binary form must reproduce the above copyright 9 | notice, this list of conditions and the following disclaimer in the 10 | documentation and/or other materials provided with the distribution. 11 | 3. Neither the name of the Regents nor the 12 | names of its contributors may be used to endorse or promote products 13 | derived from this software without specific prior written permission. 14 | 15 | IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, 16 | SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING 17 | OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF REGENTS HAS 18 | BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 19 | 20 | REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 21 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 | PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED 23 | HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION TO PROVIDE 24 | MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. 25 | -------------------------------------------------------------------------------- /LICENSE.jtag: -------------------------------------------------------------------------------- 1 | chisel-jtag license terms 2 | 3 | Copyright (c) 2016 The Regents of the University of 4 | California (Regents). All Rights Reserved. Redistribution and use in 5 | source and binary forms, with or without modification, are permitted 6 | provided that the following conditions are met: 7 | * Redistributions of source code must retain the above 8 | copyright notice, this list of conditions and the following 9 | two paragraphs of disclaimer. 10 | * Redistributions in binary form must reproduce the above 11 | copyright notice, this list of conditions and the following 12 | two paragraphs of disclaimer in the documentation and/or other materials 13 | provided with the distribution. 14 | * Neither the name of the Regents nor the names of its contributors 15 | may be used to endorse or promote products derived from this 16 | software without specific prior written permission. 17 | IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, 18 | SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, 19 | ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF 20 | REGENTS HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 21 | REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT 22 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 23 | A PARTICULAR PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF 24 | ANY, PROVIDED HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION 25 | TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR 26 | MODIFICATIONS. 27 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | base_dir=$(abspath ./) 2 | 3 | CHISEL_VERSION=3.6.0 4 | MODEL ?= TestHarness 5 | PROJECT ?= freechips.rocketchip.system 6 | CFG_PROJECT ?= $(PROJECT) 7 | CONFIG ?= $(CFG_PROJECT).DefaultConfig 8 | MILL ?= mill 9 | 10 | verilog: 11 | cd $(base_dir) && $(MILL) emulator[freechips.rocketchip.system.TestHarness,$(CONFIG)].mfccompiler.compile 12 | 13 | clean: 14 | rm -rf out/ 15 | -------------------------------------------------------------------------------- /RocketChip_Technical_Charter_8-23-2024.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chipsalliance/rocket-chip/f517abbf41abb65cea37421d3559f9739efd00a9/RocketChip_Technical_Charter_8-23-2024.pdf -------------------------------------------------------------------------------- /bootrom/.gitignore: -------------------------------------------------------------------------------- 1 | *.elf 2 | -------------------------------------------------------------------------------- /bootrom/Makefile: -------------------------------------------------------------------------------- 1 | bootrom_img = bootrom.img 2 | 3 | GCC=riscv64-unknown-elf-gcc 4 | OBJCOPY=riscv64-unknown-elf-objcopy 5 | 6 | all: $(bootrom_img) 7 | 8 | %.img: %.bin 9 | dd if=$< of=$@ bs=128 count=1 10 | 11 | %.bin: %.elf 12 | $(OBJCOPY) -O binary $< $@ 13 | 14 | %.elf: %.S linker.ld 15 | $(GCC) -Tlinker.ld $< -nostdlib -static -Wl,--no-gc-sections -o $@ 16 | -------------------------------------------------------------------------------- /bootrom/bootrom.S: -------------------------------------------------------------------------------- 1 | #define DRAM_BASE 0x80000000 2 | 3 | .section .text.start, "ax", @progbits 4 | .globl _start 5 | _start: 6 | csrwi 0x7c1, 0 // disable chicken bits 7 | li s0, DRAM_BASE 8 | csrr a0, mhartid 9 | la a1, _dtb 10 | jr s0 11 | 12 | .section .text.hang, "ax", @progbits 13 | .globl _hang 14 | _hang: 15 | csrwi 0x7c1, 0 // disable chicken bits 16 | csrr a0, mhartid 17 | la a1, _dtb 18 | csrwi mie, 0 19 | 1: 20 | wfi 21 | j 1b 22 | 23 | .section .rodata.dtb, "a", @progbits 24 | .globl _dtb 25 | .align 5, 0 26 | _dtb: 27 | .ascii "DTB goes here" 28 | -------------------------------------------------------------------------------- /bootrom/bootrom.img: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chipsalliance/rocket-chip/f517abbf41abb65cea37421d3559f9739efd00a9/bootrom/bootrom.img -------------------------------------------------------------------------------- /bootrom/linker.ld: -------------------------------------------------------------------------------- 1 | SECTIONS 2 | { 3 | ROM_BASE = 0x10000; /* ... but actually position independent */ 4 | 5 | . = ROM_BASE; 6 | .text.start : { *(.text.start) } 7 | . = ROM_BASE + 0x40; 8 | .text.hang : { *(.text.hang) } 9 | . = ROM_BASE + 0x80; 10 | .rodata.dtb : { *(.rodata.dtb) } 11 | } 12 | -------------------------------------------------------------------------------- /common.sc: -------------------------------------------------------------------------------- 1 | import mill._ 2 | import mill.scalalib._ 3 | 4 | trait HasChisel 5 | extends ScalaModule { 6 | // Define these for building chisel from source 7 | def chiselModule: Option[ScalaModule] 8 | 9 | override def moduleDeps = super.moduleDeps ++ chiselModule 10 | 11 | def chiselPluginJar: T[Option[PathRef]] 12 | 13 | override def scalacOptions = T(super.scalacOptions() ++ chiselPluginJar().map(path => s"-Xplugin:${path.path}")) 14 | 15 | override def scalacPluginClasspath: T[Agg[PathRef]] = T(super.scalacPluginClasspath() ++ chiselPluginJar()) 16 | 17 | // Define these for building chisel from ivy 18 | def chiselIvy: Option[Dep] 19 | 20 | override def ivyDeps = T(super.ivyDeps() ++ chiselIvy) 21 | 22 | def chiselPluginIvy: Option[Dep] 23 | 24 | override def scalacPluginIvyDeps: T[Agg[Dep]] = T(super.scalacPluginIvyDeps() ++ chiselPluginIvy.map(Agg(_)).getOrElse(Agg.empty[Dep])) 25 | } 26 | 27 | trait MacrosModule 28 | extends ScalaModule { 29 | 30 | def scalaReflectIvy: Dep 31 | 32 | override def ivyDeps = T(super.ivyDeps() ++ Some(scalaReflectIvy)) 33 | } 34 | 35 | 36 | trait RocketChipModule 37 | extends HasChisel { 38 | override def mainClass = T(Some("freechips.rocketchip.diplomacy.Main")) 39 | 40 | def macrosModule: MacrosModule 41 | 42 | // should be hardfloat/common.sc#HardfloatModule 43 | def hardfloatModule: ScalaModule 44 | 45 | def diplomacyModule: ScalaModule 46 | 47 | def mainargsIvy: Dep 48 | 49 | def json4sJacksonIvy: Dep 50 | 51 | override def moduleDeps = super.moduleDeps ++ Seq(macrosModule, hardfloatModule, diplomacyModule) 52 | 53 | override def ivyDeps = T( 54 | super.ivyDeps() ++ Agg( 55 | mainargsIvy, 56 | json4sJacksonIvy, 57 | ) 58 | ) 59 | } 60 | -------------------------------------------------------------------------------- /docs/README.md: -------------------------------------------------------------------------------- 1 | # Generated Documentation 2 | 3 | This directory contains documentation on the code within this repository. 4 | Documents can either be written directly in markdown, or use embedded `mdoc`, 5 | which compiles against the Rocket Chip (and dependencies) codebase as part of 6 | the PR CI checks, forcing the documentation to remain current with the codebase. 7 | 8 | The `src` folder contains the source from which these are generated. To generate 9 | the documentation, run `docs/mdoc` from SBT, making sure that SBT is running 10 | from this repository's root directory. The generated documents will appear in 11 | the `generated` folder. -------------------------------------------------------------------------------- /docs/src/diplomacy/diagrams/adder_modules.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chipsalliance/rocket-chip/f517abbf41abb65cea37421d3559f9739efd00a9/docs/src/diplomacy/diagrams/adder_modules.pdf -------------------------------------------------------------------------------- /docs/src/diplomacy/diagrams/adder_nodes.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chipsalliance/rocket-chip/f517abbf41abb65cea37421d3559f9739efd00a9/docs/src/diplomacy/diagrams/adder_nodes.pdf -------------------------------------------------------------------------------- /docs/src/diplomacy/diagrams/edge_inout.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chipsalliance/rocket-chip/f517abbf41abb65cea37421d3559f9739efd00a9/docs/src/diplomacy/diagrams/edge_inout.pdf -------------------------------------------------------------------------------- /flake.lock: -------------------------------------------------------------------------------- 1 | { 2 | "nodes": { 3 | "flake-utils": { 4 | "inputs": { 5 | "systems": "systems" 6 | }, 7 | "locked": { 8 | "lastModified": 1694529238, 9 | "narHash": "sha256-zsNZZGTGnMOf9YpHKJqMSsa0dXbfmxeoJ7xHlrt+xmY=", 10 | "owner": "numtide", 11 | "repo": "flake-utils", 12 | "rev": "ff7b65b44d01cf9ba6a71320833626af21126384", 13 | "type": "github" 14 | }, 15 | "original": { 16 | "owner": "numtide", 17 | "repo": "flake-utils", 18 | "type": "github" 19 | } 20 | }, 21 | "nixpkgs": { 22 | "locked": { 23 | "lastModified": 1696019113, 24 | "narHash": "sha256-X3+DKYWJm93DRSdC5M6K5hLqzSya9BjibtBsuARoPco=", 25 | "owner": "NixOS", 26 | "repo": "nixpkgs", 27 | "rev": "f5892ddac112a1e9b3612c39af1b72987ee5783a", 28 | "type": "github" 29 | }, 30 | "original": { 31 | "owner": "NixOS", 32 | "ref": "nixos-unstable", 33 | "repo": "nixpkgs", 34 | "type": "github" 35 | } 36 | }, 37 | "root": { 38 | "inputs": { 39 | "flake-utils": "flake-utils", 40 | "nixpkgs": "nixpkgs" 41 | } 42 | }, 43 | "systems": { 44 | "locked": { 45 | "lastModified": 1681028828, 46 | "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", 47 | "owner": "nix-systems", 48 | "repo": "default", 49 | "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", 50 | "type": "github" 51 | }, 52 | "original": { 53 | "owner": "nix-systems", 54 | "repo": "default", 55 | "type": "github" 56 | } 57 | } 58 | }, 59 | "root": "root", 60 | "version": 7 61 | } 62 | -------------------------------------------------------------------------------- /flake.nix: -------------------------------------------------------------------------------- 1 | { 2 | description = "rocket-chip"; 3 | 4 | inputs = { 5 | nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; 6 | flake-utils.url = "github:numtide/flake-utils"; 7 | }; 8 | 9 | outputs = { self, nixpkgs, flake-utils }@inputs: 10 | let 11 | overlay = import ./overlay.nix; 12 | in 13 | flake-utils.lib.eachDefaultSystem 14 | (system: 15 | let 16 | pkgs = import nixpkgs { inherit system; overlays = [ overlay ]; }; 17 | deps = with pkgs; [ 18 | git 19 | gnumake autoconf automake 20 | mill 21 | dtc 22 | verilator cmake ninja 23 | python3 24 | python3Packages.pip 25 | pkgsCross.riscv64-embedded.buildPackages.gcc 26 | pkgsCross.riscv64-embedded.buildPackages.gdb 27 | openocd 28 | circt 29 | 30 | spike riscvTests 31 | ]; 32 | in 33 | { 34 | legacyPackages = pkgs; 35 | devShell = pkgs.mkShell.override { stdenv = pkgs.clangStdenv; } { 36 | buildInputs = deps; 37 | SPIKE_ROOT = "${pkgs.spike}"; 38 | RISCV_TESTS_ROOT = "${pkgs.riscvTests}"; 39 | RV64_TOOLCHAIN_ROOT = "${pkgs.pkgsCross.riscv64-embedded.buildPackages.gcc}"; 40 | shellHook = '' 41 | # Tells pip to put packages into $PIP_PREFIX instead of the usual locations. 42 | # See https://pip.pypa.io/en/stable/user_guide/#environment-variables. 43 | export PIP_PREFIX=$(pwd)/venv/pip_packages 44 | export PYTHONPATH="$PIP_PREFIX/${pkgs.python3.sitePackages}:$PYTHONPATH" 45 | export PATH="$PIP_PREFIX/bin:$PATH" 46 | unset SOURCE_DATE_EPOCH 47 | pip3 install importlib-metadata typing-extensions riscof==1.25.2 pexpect 48 | ''; 49 | }; 50 | } 51 | ) 52 | // { inherit inputs; overlays.default = overlay; }; 53 | } 54 | -------------------------------------------------------------------------------- /macros/src/main/scala/ValName.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | 3 | package freechips.rocketchip.macros 4 | 5 | import scala.language.experimental.macros 6 | import scala.reflect.macros.blackbox.Context 7 | 8 | case class ValNameImpl(name: String) 9 | 10 | object ValNameImpl 11 | { 12 | implicit def materialize: ValNameImpl = macro detail 13 | def detail(c: Context): c.Expr[ValNameImpl] = { 14 | import c.universe._ 15 | def allOwners(s: c.Symbol): Seq[c.Symbol] = 16 | if (s == `NoSymbol`) Nil else s +: allOwners(s.owner) 17 | val terms = allOwners(c.internal.enclosingOwner).filter(_.isTerm).map(_.asTerm) 18 | terms.filter(t => t.isVal || t.isLazy).map(_.name.toString).find(_(0) != '$').map { s => 19 | val trim = s.replaceAll("\\s", "") 20 | c.Expr[ValNameImpl] { q"_root_.freechips.rocketchip.macros.ValNameImpl(${trim})" } 21 | }.getOrElse(c.abort(c.enclosingPosition, "Not a valid application.")) 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /overlay.nix: -------------------------------------------------------------------------------- 1 | final: prev: { 2 | mill = prev.mill.overrideAttrs (oldAttrs: rec { 3 | version = "0.11.1"; 4 | src = prev.fetchurl { 5 | url = "https://github.com/com-lihaoyi/mill/releases/download/${version}/${version}-assembly"; 6 | hash = "sha256-qG+Ddn0BHUZX1VX5hO84exgRz8YuUgYF/fH6MmgkrXE="; 7 | }; 8 | }); 9 | riscvTests = final.pkgsCross.riscv64-embedded.stdenv.mkDerivation rec { 10 | pname = "riscv-tests"; 11 | version = "f2f748ebb9cf8ea049103f85c4cbf7e8a2927b16"; 12 | src = final.fetchgit { 13 | url = "https://github.com/riscv-software-src/riscv-tests.git"; 14 | rev = "${version}"; 15 | fetchSubmodules = true; 16 | sha256 = "sha256-E3RfrP+PFIYy9c/pY04jYPxeGpnfgWwjV8iwL5+s+9w="; 17 | }; 18 | 19 | enableParallelBuilding = true; 20 | 21 | configureFlags = [ 22 | # to match rocket-tools path 23 | "--prefix=${placeholder "out"}/riscv64-unknown-elf" 24 | ]; 25 | buildPhase = "make RISCV_PREFIX=riscv64-none-elf-"; 26 | installPhase = '' 27 | runHook preInstall 28 | make install 29 | mkdir -p $out/debug/ 30 | cp debug/*.py $out/debug/ 31 | runHook postInstall 32 | ''; 33 | }; 34 | } 35 | -------------------------------------------------------------------------------- /regression/.gitignore: -------------------------------------------------------------------------------- 1 | /install 2 | /stamps 3 | /torture-failures 4 | -------------------------------------------------------------------------------- /riscv-tools.hash: -------------------------------------------------------------------------------- 1 | 04a559f761af784a303ca8b518e52f9e732aa8f4 2 | -------------------------------------------------------------------------------- /scripts/.gitignore: -------------------------------------------------------------------------------- 1 | /comlog 2 | /float_fix 3 | -------------------------------------------------------------------------------- /scripts/Makefile: -------------------------------------------------------------------------------- 1 | base_dir = $(abspath ..) 2 | 3 | CXXSRCS := comlog float_fix 4 | CXXFLAGS := $(CXXFLAGS) -std=c++11 -Wall 5 | 6 | OBJS := $(addsuffix .o,$(CXXSRCS)) 7 | PROGRAMS := $(CXXSRCS) 8 | 9 | all: $(PROGRAMS) 10 | 11 | %: %.o 12 | $(CXX) $< $(LDFLAGS) -o $@ 13 | 14 | %.o: $(base_dir)/csrc/%.cc 15 | $(CXX) $(CXXFLAGS) -c $< -o $@ 16 | 17 | clean: 18 | rm -f $(OBJS) $(PROGRAMS) 19 | -------------------------------------------------------------------------------- /scripts/RocketSim.cfg: -------------------------------------------------------------------------------- 1 | adapter_khz 10000 2 | 3 | interface remote_bitbang 4 | remote_bitbang_host localhost 5 | #$::env(REMOTE_BITBANG_HOST) 6 | remote_bitbang_port $::env(JTAG_VPI_PORT) 7 | 8 | set _CHIPNAME riscv 9 | jtag newtap $_CHIPNAME cpu -irlen 5 10 | 11 | set _TARGETNAME $_CHIPNAME.cpu 12 | target create $_TARGETNAME riscv -chain-position $_TARGETNAME -rtos hwthread 13 | 14 | riscv set_reset_timeout_sec 120 15 | riscv set_command_timeout_sec 120 16 | 17 | riscv set_prefer_sba $::env(JTAG_DTM_ENABLE_SBA) 18 | 19 | init 20 | halt 21 | echo "Ready for Remote Connections" 22 | -------------------------------------------------------------------------------- /scripts/RocketSim.py: -------------------------------------------------------------------------------- 1 | import targets 2 | import testlib 3 | 4 | class RocketSimHart(targets.Hart): 5 | # This isn't generically true, but it's true enough for the Default*Configs in this code for now. 6 | # to get these tests to pass. 7 | ram = 0x80000000 8 | ram_size = 0x4000 9 | instruction_hardware_breakpoint_count = 2 10 | pass 11 | 12 | class RocketSim(targets.Target): 13 | harts = [RocketSimHart()] 14 | timeout_sec = 6000 15 | server_timeout_sec = 60*60 16 | openocd_config_path = "RocketSim.cfg" 17 | 18 | def create(self): 19 | printf("STARTING A SIMULATION") 20 | printf(self.sim_cmd) 21 | return testlib.VcsSim(sim_cmd=self.sim_cmd, debug=False) 22 | -------------------------------------------------------------------------------- /scripts/RocketSim32.py: -------------------------------------------------------------------------------- 1 | import targets 2 | import testlib 3 | 4 | class RocketSimHart(targets.Hart): 5 | xlen = 32 6 | # This isn't generically true, but it's true enough for the Default*Configs in this code for now. 7 | # to get these tests to pass. 8 | ram = 0x80000000 9 | ram_size = 0x4000 10 | instruction_hardware_breakpoint_count = 2 11 | pass 12 | 13 | class RocketSim(targets.Target): 14 | harts = [RocketSimHart()] 15 | timeout_sec = 6000 16 | server_timeout_sec = 60*60 17 | openocd_config_path = "RocketSim.cfg" 18 | 19 | def create(self): 20 | print("STARTING A SIMULATION") 21 | print(self.sim_cmd) 22 | return testlib.VcsSim(sim_cmd=self.sim_cmd, debug=False) 23 | -------------------------------------------------------------------------------- /scripts/RocketSim64.py: -------------------------------------------------------------------------------- 1 | import targets 2 | import testlib 3 | 4 | class RocketSimHart(targets.Hart): 5 | # This isn't generically true, but it's true enough for the Default*Configs in this code for now. 6 | # to get these tests to pass. 7 | xlen = 64 8 | ram = 0x80000000 9 | ram_size = 0x4000 10 | instruction_hardware_breakpoint_count = 2 11 | pass 12 | 13 | class RocketSim(targets.Target): 14 | harts = [RocketSimHart()] 15 | timeout_sec = 6000 16 | server_timeout_sec = 60*60 17 | openocd_config_path = "RocketSim.cfg" 18 | 19 | def create(self): 20 | print("STARTING A SIMULATION") 21 | print(self.sim_cmd) 22 | return testlib.VcsSim(sim_cmd=self.sim_cmd, debug=False) 23 | -------------------------------------------------------------------------------- /scripts/arch-test/emulator/env/link.ld: -------------------------------------------------------------------------------- 1 | OUTPUT_ARCH( "riscv" ) 2 | ENTRY(rvtest_entry_point) 3 | 4 | SECTIONS 5 | { 6 | . = 0x80000000; 7 | .text.init : { *(.text.init) } 8 | . = ALIGN(0x1000); 9 | .tohost : { *(.tohost) } 10 | . = ALIGN(0x1000); 11 | .text : { *(.text) } 12 | . = ALIGN(0x1000); 13 | .data : { *(.data) } 14 | .data.string : { *(.data.string)} 15 | .bss : { *(.bss) } 16 | _end = .; 17 | } 18 | 19 | -------------------------------------------------------------------------------- /scripts/arch-test/emulator/env/model_test.h: -------------------------------------------------------------------------------- 1 | #ifndef _COMPLIANCE_MODEL_H 2 | #define _COMPLIANCE_MODEL_H 3 | #define RVMODEL_DATA_SECTION \ 4 | .pushsection .tohost,"aw",@progbits; \ 5 | .align 8; .global tohost; tohost: .dword 0; \ 6 | .align 8; .global fromhost; fromhost: .dword 0; \ 7 | .popsection; \ 8 | .align 8; .global begin_regstate; begin_regstate: \ 9 | .word 128; \ 10 | .align 8; .global end_regstate; end_regstate: \ 11 | .word 4; 12 | 13 | //RV_COMPLIANCE_HALT 14 | #define RVMODEL_HALT \ 15 | li x1, 1; \ 16 | write_tohost: \ 17 | sw x1, tohost, t5; \ 18 | j write_tohost; 19 | 20 | #define RVMODEL_BOOT 21 | 22 | //RV_COMPLIANCE_DATA_BEGIN 23 | #define RVMODEL_DATA_BEGIN \ 24 | .align 4; .global begin_signature; begin_signature: 25 | 26 | //RV_COMPLIANCE_DATA_END 27 | #define RVMODEL_DATA_END \ 28 | .align 4; .global end_signature; end_signature: \ 29 | RVMODEL_DATA_SECTION \ 30 | 31 | //RVTEST_IO_INIT 32 | #define RVMODEL_IO_INIT 33 | //RVTEST_IO_WRITE_STR 34 | #define RVMODEL_IO_WRITE_STR(_R, _STR) 35 | //RVTEST_IO_CHECK 36 | #define RVMODEL_IO_CHECK() 37 | //RVTEST_IO_ASSERT_GPR_EQ 38 | #define RVMODEL_IO_ASSERT_GPR_EQ(_S, _R, _I) 39 | //RVTEST_IO_ASSERT_SFPR_EQ 40 | #define RVMODEL_IO_ASSERT_SFPR_EQ(_F, _R, _I) 41 | //RVTEST_IO_ASSERT_DFPR_EQ 42 | #define RVMODEL_IO_ASSERT_DFPR_EQ(_D, _R, _I) 43 | 44 | #define RVMODEL_SET_MSW_INT 45 | 46 | #define RVMODEL_CLEAR_MSW_INT 47 | 48 | #define RVMODEL_CLEAR_MTIMER_INT 49 | 50 | #define RVMODEL_CLEAR_MEXT_INT 51 | 52 | 53 | #endif // _COMPLIANCE_MODEL_H 54 | -------------------------------------------------------------------------------- /scripts/arch-test/spike/env/link.ld: -------------------------------------------------------------------------------- 1 | OUTPUT_ARCH( "riscv" ) 2 | ENTRY(rvtest_entry_point) 3 | 4 | SECTIONS 5 | { 6 | . = 0x80000000; 7 | .text.init : { *(.text.init) } 8 | . = ALIGN(0x1000); 9 | .tohost : { *(.tohost) } 10 | . = ALIGN(0x1000); 11 | .text : { *(.text) } 12 | . = ALIGN(0x1000); 13 | .data : { *(.data) } 14 | .data.string : { *(.data.string)} 15 | .bss : { *(.bss) } 16 | _end = .; 17 | } 18 | 19 | -------------------------------------------------------------------------------- /scripts/arch-test/spike/env/model_test.h: -------------------------------------------------------------------------------- 1 | #ifndef _COMPLIANCE_MODEL_H 2 | #define _COMPLIANCE_MODEL_H 3 | #define RVMODEL_DATA_SECTION \ 4 | .pushsection .tohost,"aw",@progbits; \ 5 | .align 8; .global tohost; tohost: .dword 0; \ 6 | .align 8; .global fromhost; fromhost: .dword 0; \ 7 | .popsection; \ 8 | .align 8; .global begin_regstate; begin_regstate: \ 9 | .word 128; \ 10 | .align 8; .global end_regstate; end_regstate: \ 11 | .word 4; 12 | 13 | //RV_COMPLIANCE_HALT 14 | #define RVMODEL_HALT \ 15 | li x1, 1; \ 16 | write_tohost: \ 17 | sw x1, tohost, t5; \ 18 | j write_tohost; 19 | 20 | #define RVMODEL_BOOT 21 | 22 | //RV_COMPLIANCE_DATA_BEGIN 23 | #define RVMODEL_DATA_BEGIN \ 24 | .align 4; .global begin_signature; begin_signature: 25 | 26 | //RV_COMPLIANCE_DATA_END 27 | #define RVMODEL_DATA_END \ 28 | .align 4; .global end_signature; end_signature: \ 29 | RVMODEL_DATA_SECTION \ 30 | 31 | //RVTEST_IO_INIT 32 | #define RVMODEL_IO_INIT 33 | //RVTEST_IO_WRITE_STR 34 | #define RVMODEL_IO_WRITE_STR(_R, _STR) 35 | //RVTEST_IO_CHECK 36 | #define RVMODEL_IO_CHECK() 37 | //RVTEST_IO_ASSERT_GPR_EQ 38 | #define RVMODEL_IO_ASSERT_GPR_EQ(_S, _R, _I) 39 | //RVTEST_IO_ASSERT_SFPR_EQ 40 | #define RVMODEL_IO_ASSERT_SFPR_EQ(_F, _R, _I) 41 | //RVTEST_IO_ASSERT_DFPR_EQ 42 | #define RVMODEL_IO_ASSERT_DFPR_EQ(_D, _R, _I) 43 | 44 | #define RVMODEL_SET_MSW_INT 45 | 46 | #define RVMODEL_CLEAR_MSW_INT 47 | 48 | #define RVMODEL_CLEAR_MTIMER_INT 49 | 50 | #define RVMODEL_CLEAR_MEXT_INT 51 | 52 | 53 | #endif // _COMPLIANCE_MODEL_H 54 | -------------------------------------------------------------------------------- /scripts/authors: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | 3 | while read when who; do 4 | case "$who" in 5 | "Adam Izraelevitz") echo Berkeley ;; 6 | "Albert Magyar") echo Berkeley ;; 7 | "Albert Ou") if [ $when -ge 20151101 ]; then echo SiFive; else echo Berkeley; fi ;; 8 | "Amirali Sharifian") echo Unknown ;; 9 | "Andrew Waterman") if [ $when -ge 20150901 ]; then echo SiFive; else echo Berkeley; fi ;; 10 | "Ben Keller") echo Berkeley ;; 11 | "Christopher Celio") echo Berkeley ;; 12 | "Colin Schmidt") echo Berkeley ;; 13 | "Daiwei Li") echo Berkeley ;; 14 | "David Biancolin") echo Berkeley ;; 15 | "Donggyu") echo Berkeley ;; 16 | "Donggyu Kim") echo Berkeley ;; 17 | "ducky") echo Berkeley ;; 18 | "Eric Love") echo Berkeley ;; 19 | "Gage W Eads") echo Berkeley ;; 20 | "Henry Cook") if [ $when -ge 20160501 ]; then echo SiFive; else echo Berkeley; fi ;; 21 | "Howard Mao") if [ $when -ge 20160601 -a $when -le 20160819 ]; then echo SiFive; else echo Berkeley; fi ;; 22 | "Huy Vo") echo Berkeley ;; 23 | "Iori YONEJI") echo Unknown ;; 24 | "jackkoenig") echo Berkeley ;; 25 | "Jack Koenig") echo Berkeley ;; 26 | "Jacob Chang") echo SiFive ;; 27 | "Jim Lawson") echo Berkeley ;; 28 | "John Wright") echo Berkeley ;; 29 | "Ken McMillan") echo Microsoft;; 30 | "Matthew Naylor") if [ $when -le 20161127 ]; then echo Berkeley; else echo Cambridge; fi ;; 31 | "Megan Wachs") echo SiFive ;; 32 | "Miquel Moreto") echo Berkeley ;; 33 | "mwachs5") echo SiFive ;; 34 | "Palmer Dabbelt") echo Berkeley ;; 35 | "Quan Nguyen") echo Berkeley ;; 36 | "RainerWasserfuhr") echo Unknown ;; 37 | "Richard Xia") echo SiFive ;; 38 | "Rimas Avizienis") echo Berkeley ;; 39 | "roman3017") echo Unknown ;; 40 | "Sagar Karandikar") echo Berkeley ;; 41 | "Schuyler Eldridge") echo Unknown ;; 42 | "Scott Beamer") echo Berkeley ;; 43 | "Scott Johnson") echo SiFive ;; 44 | "SeungRyeol Lee") echo LGE ;; 45 | "Stephen Twigg") echo Berkeley ;; 46 | "Wei Song") echo Cambridge;; 47 | "Wesley W. Terpstra") echo SiFive ;; 48 | "Yunsup Lee") if [ $when -gt 20150901 ]; then echo SiFive; else echo Berkeley; fi ;; 49 | *) echo NoMatch; echo "Missing scripts/authors entry for $who" >&2; exit 1 ;; 50 | esac 51 | done 52 | -------------------------------------------------------------------------------- /scripts/check_cache_trace.py: -------------------------------------------------------------------------------- 1 | import sys 2 | from collections import defaultdict 3 | 4 | # Checks a trace of cache transactions to make sure the data is correct 5 | # Note: this will only work if the L2 agent only receives cached traffic 6 | # (either caching Acquires or Releases). If there are any builtin 7 | # Put or PutBlock requests, they will not be reflected in the trace 8 | # and the data will appear to be incorrect. 9 | 10 | DATA_BEATS = 8 11 | 12 | def parse_prm(fname): 13 | mem_data_bits = 0 14 | cache_block_bytes = 0 15 | with open(fname) as f: 16 | for line in f: 17 | line = line.strip("() \t\n") 18 | parts = line.split(",") 19 | if parts[0] == "MEM_DATA_BITS": 20 | mem_data_bits = int(parts[1]) 21 | elif parts[1] == "CACHE_BLOCK_BYTES": 22 | cache_block_bytes = int(parts[1]) 23 | DATA_BEATS = (cache_block_bytes * 8) / mem_data_bits 24 | 25 | def data_block(): 26 | return [0] * DATA_BEATS 27 | 28 | blocks = defaultdict(data_block) 29 | 30 | def process_release(addr_block, addr_beat, data): 31 | blocks[addr_block][addr_beat] = data 32 | 33 | def process_get(addr_block, addr_beat, data): 34 | stored_data = blocks[addr_block][addr_beat] 35 | if stored_data != data: 36 | print("Error {:07x},{}: {:016x} != {:016x}".format( 37 | addr_block, addr_beat, stored_data, data)) 38 | 39 | def process_line(line): 40 | if not line: 41 | return 42 | pieces = line.split() 43 | if pieces[0] == "[release]": 44 | addr_block = int(pieces[1].split('=')[1], 16) 45 | addr_beat = int(pieces[2].split('=')[1]) 46 | data = int(pieces[3].split('=')[1], 16) 47 | process_release(addr_block, addr_beat, data) 48 | if pieces[0] == "[get]": 49 | addr_block = int(pieces[1].split('=')[1], 16) 50 | addr_beat = int(pieces[2].split('=')[1]) 51 | data = int(pieces[3].split('=')[1], 16) 52 | process_get(addr_block, addr_beat, data) 53 | 54 | def check_trace(fname): 55 | with open(fname) as f: 56 | for line in f: 57 | process_line(line.strip()) 58 | 59 | if __name__ == "__main__": 60 | if len(sys.argv) < 2: 61 | print("Usage: {} trace.out [params.prm]".format(sys.argv[0])) 62 | sys.exit(-1) 63 | if len(sys.argv) > 2: 64 | parse_prm(sys.argv[2]) 65 | check_trace(sys.argv[1]) 66 | -------------------------------------------------------------------------------- /scripts/copyright-file: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | d=$(dirname $0) 3 | for i in "$@"; do 4 | if [ $# -gt 1 ]; then echo "$i:"; fi 5 | git blame --date="format:%Y%m%d" -M -C -C -C "$i" | sed 's/[^(]*(\([^0-46-9]*\) \([0-9]*\).*/\2 \1/' | $d/authors | sort | uniq -c | sort -rn 6 | done 7 | -------------------------------------------------------------------------------- /scripts/debug_rom/.gitignore: -------------------------------------------------------------------------------- 1 | /debug_rom 2 | -------------------------------------------------------------------------------- /scripts/debug_rom/Makefile: -------------------------------------------------------------------------------- 1 | # See LICENSE.SiFive for license details 2 | # Recursive make is bad, but in this case we're cross compiling which is a 3 | # pretty unusual use case. 4 | 5 | CC = $(RISCV)/bin/riscv64-unknown-elf-gcc 6 | OBJCOPY = $(RISCV)/bin/riscv64-unknown-elf-objcopy 7 | 8 | COMPILE = $(CC) -nostdlib -nostartfiles -I$(RISCV)/riscv64-unknown-elf/include/ -Tlink.ld 9 | 10 | ELFS = debug_rom debug_rom_nonzero 11 | 12 | all: $(ELFS) 13 | 14 | publish: DebugRomContents.scala DebugRomNonzeroContents.scala 15 | mv $^ ../../src/main/scala/devices/debug 16 | 17 | %.scala: %.raw 18 | xxd -i $^ | sed -e "s/^unsigned char DebugRom.*/\/\/ This file was auto-generated by 'make publish' in debug\/ directory.\n\npackage freechips.rocketchip.devices.debug\n\nobject $(basename $<) {\n\n def apply() : Array[Byte] = { Array (/" \ 19 | -e "s/};/ ).map(_.toByte) }\n\n}/" \ 20 | -e "s/^unsigned int DebugRom.*//" > $@ 21 | 22 | DebugRomContents.raw: debug_rom 23 | $(OBJCOPY) -O binary --only-section .text $^ $@ 24 | 25 | DebugRomNonzeroContents.raw: debug_rom_nonzero 26 | $(OBJCOPY) -O binary --only-section .text $^ $@ 27 | 28 | %: %.S 29 | $(COMPILE) -o $@ $^ 30 | 31 | clean: 32 | rm -f $(ELFS) DebugRom*.raw 33 | -------------------------------------------------------------------------------- /scripts/debug_rom/link.ld: -------------------------------------------------------------------------------- 1 | /* See LICENSE.SiFive for license details. */ 2 | OUTPUT_ARCH( "riscv" ) 3 | ENTRY( entry ) 4 | SECTIONS 5 | { 6 | .whereto 0x300 : 7 | { 8 | *(.whereto) 9 | } 10 | . = 0x800; 11 | .text : 12 | { 13 | *(.text) 14 | } 15 | _end = .; 16 | } 17 | -------------------------------------------------------------------------------- /scripts/modify-copyright: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | d=$(dirname "$0") 3 | threshold=10 4 | 5 | for i in $(git ls-tree -r HEAD . | grep '\.\(scala\|cc\|v\)' | cut -f2); do 6 | ("$d/copyright-file" "$i" | sort -rn | awk 'NR == 1 || $1 > '$threshold' { print }' | sed 's@[^A-Z]*@// See LICENSE.@;s@$@ for license details.@;$a\\'; \ 7 | grep -v "^// See LICENSE" $i | sed '/./,$!d') > $i.tmp 8 | mv $i.tmp $i 9 | done 10 | -------------------------------------------------------------------------------- /scripts/tracegen.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | # This file was originally written by Matthew Naylor, University of 4 | # Cambridge. 5 | # 6 | # This software was partly developed by the University of Cambridge 7 | # Computer Laboratory under DARPA/AFRL contract FA8750-10-C-0237 8 | # ("CTSRD"), as part of the DARPA CRASH research programme. 9 | # 10 | # This software was partly developed by the University of Cambridge 11 | # Computer Laboratory under DARPA/AFRL contract FA8750-11-C-0249 12 | # ("MRC2"), as part of the DARPA MRC research programme. 13 | # 14 | # This software was partly developed by the University of Cambridge 15 | # Computer Laboratory as part of the Rigorous Engineering of 16 | # Mainstream Systems (REMS) project, funded by EPSRC grant 17 | # EP/K008528/1. 18 | 19 | # ------- 20 | # Outline 21 | # ------- 22 | 23 | # Usage: 24 | # 25 | # tracegen.py EMULATOR SEED 26 | # 27 | # This script generates a trace using the given emulator (built 28 | # with CONFIG=TraceGenConfig). It waits until all cores have 29 | # completed trace generation before terminating the emulator. 30 | 31 | import sys 32 | import subprocess 33 | import re 34 | 35 | def main(): 36 | if len(sys.argv) != 3: 37 | sys.stderr.write("Usage: tracegen.py EMULATOR SEED\n") 38 | sys.exit(-1) 39 | 40 | p = subprocess.Popen([sys.argv[1], 41 | "+verbose", "-s" + sys.argv[2]], 42 | stderr=subprocess.PIPE, stdout=subprocess.PIPE) 43 | if p == None: 44 | sys.stderr.write("File not found: " + sys.argv[1] + "\n") 45 | sys.exit(-1) 46 | 47 | numFinished = 0 48 | while True: 49 | line = p.stderr.readline() 50 | if line[0:9] == "FINISHED ": 51 | total = int(line[9:-1]) 52 | numFinished = numFinished + 1 53 | if numFinished == total: 54 | break 55 | elif line[0:15] == "Completed after": 56 | break 57 | elif line[0:7] == "testing": 58 | continue 59 | else: 60 | print line, 61 | 62 | p.terminate() 63 | 64 | try: 65 | main() 66 | except KeyboardInterrupt: 67 | sys.exit(-1) 68 | -------------------------------------------------------------------------------- /src/main/resources/csrc/SimDTM.cc: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | dtm_t* dtm; 8 | 9 | extern "C" int debug_tick 10 | ( 11 | unsigned char* debug_req_valid, 12 | unsigned char debug_req_ready, 13 | int* debug_req_bits_addr, 14 | int* debug_req_bits_op, 15 | int* debug_req_bits_data, 16 | unsigned char debug_resp_valid, 17 | unsigned char* debug_resp_ready, 18 | int debug_resp_bits_resp, 19 | int debug_resp_bits_data 20 | ) 21 | { 22 | if (!dtm) { 23 | s_vpi_vlog_info info; 24 | if (!vpi_get_vlog_info(&info)) 25 | abort(); 26 | dtm = new dtm_t(info.argc, info.argv); 27 | } 28 | 29 | dtm_t::resp resp_bits; 30 | resp_bits.resp = debug_resp_bits_resp; 31 | resp_bits.data = debug_resp_bits_data; 32 | 33 | dtm->tick 34 | ( 35 | debug_req_ready, 36 | debug_resp_valid, 37 | resp_bits 38 | ); 39 | 40 | *debug_resp_ready = dtm->resp_ready(); 41 | *debug_req_valid = dtm->req_valid(); 42 | *debug_req_bits_addr = dtm->req_bits().addr; 43 | *debug_req_bits_op = dtm->req_bits().op; 44 | *debug_req_bits_data = dtm->req_bits().data; 45 | 46 | return dtm->done() ? (dtm->exit_code() << 1 | 1) : 0; 47 | } 48 | -------------------------------------------------------------------------------- /src/main/resources/csrc/SimJTAG.cc: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | 3 | #include 4 | #include "remote_bitbang.h" 5 | 6 | remote_bitbang_t* jtag; 7 | extern "C" int jtag_tick 8 | ( 9 | unsigned char * jtag_TCK, 10 | unsigned char * jtag_TMS, 11 | unsigned char * jtag_TDI, 12 | unsigned char * jtag_TRSTn, 13 | unsigned char jtag_TDO 14 | ) 15 | { 16 | if (!jtag) { 17 | // TODO: Pass in real port number 18 | jtag = new remote_bitbang_t(0); 19 | } 20 | 21 | jtag->tick(jtag_TCK, jtag_TMS, jtag_TDI, jtag_TRSTn, jtag_TDO); 22 | 23 | return jtag->done() ? (jtag->exit_code() << 1 | 1) : 0; 24 | 25 | } 26 | -------------------------------------------------------------------------------- /src/main/resources/csrc/remote_bitbang.h: -------------------------------------------------------------------------------- 1 | // See LICENSE.Berkeley for license details. 2 | 3 | #ifndef REMOTE_BITBANG_H 4 | #define REMOTE_BITBANG_H 5 | 6 | #include 7 | #include 8 | 9 | class remote_bitbang_t 10 | { 11 | public: 12 | // Create a new server, listening for connections from localhost on the given 13 | // port. 14 | remote_bitbang_t(uint16_t port); 15 | 16 | // Do a bit of work. 17 | void tick(unsigned char * jtag_tck, 18 | unsigned char * jtag_tms, 19 | unsigned char * jtag_tdi, 20 | unsigned char * jtag_trstn, 21 | unsigned char jtag_tdo); 22 | 23 | unsigned char done() {return quit;} 24 | 25 | int exit_code() {return err;} 26 | 27 | private: 28 | 29 | int err; 30 | 31 | unsigned char tck; 32 | unsigned char tms; 33 | unsigned char tdi; 34 | unsigned char trstn; 35 | unsigned char tdo; 36 | unsigned char quit; 37 | 38 | int socket_fd; 39 | int client_fd; 40 | 41 | static const ssize_t buf_size = 64 * 1024; 42 | char recv_buf[buf_size]; 43 | ssize_t recv_start, recv_end; 44 | 45 | // Check for a client connecting, and accept if there is one. 46 | void accept(); 47 | // Execute any commands the client has for us. 48 | // But we only execute 1 because we need time for the 49 | // simulation to run. 50 | void execute_command(); 51 | 52 | // Reset. Currently does nothing. 53 | void reset(); 54 | 55 | void set_pins(char _tck, char _tms, char _tdi); 56 | 57 | }; 58 | 59 | #endif 60 | -------------------------------------------------------------------------------- /src/main/resources/csrc/verilator.h: -------------------------------------------------------------------------------- 1 | #ifndef _ROCKET_VERILATOR_H 2 | #define _ROCKET_VERILATOR_H 3 | 4 | #include "verilated_vcd_c.h" 5 | #include 6 | #include 7 | 8 | extern bool verbose; 9 | extern bool done_reset; 10 | 11 | class VerilatedVcdFILE : public VerilatedVcdFile { 12 | public: 13 | VerilatedVcdFILE(FILE* file) : file(file) {} 14 | ~VerilatedVcdFILE() {} 15 | bool open(const std::string& name) override { 16 | // file should already be open 17 | return file != NULL; 18 | } 19 | void close() override { 20 | // file should be closed elsewhere 21 | } 22 | ssize_t write(const char* bufp, ssize_t len) override { 23 | return fwrite(bufp, 1, len, file); 24 | } 25 | private: 26 | FILE* file; 27 | }; 28 | 29 | #endif 30 | -------------------------------------------------------------------------------- /src/main/resources/vsrc/AsyncResetReg.v: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | 3 | /** This black-boxes an Async Reset 4 | * Reg. 5 | * 6 | * Because Chisel doesn't support 7 | * parameterized black boxes, 8 | * we unfortunately have to 9 | * instantiate a number of these. 10 | * 11 | * We also have to hard-code the set/reset. 12 | * 13 | * Do not confuse an asynchronous 14 | * reset signal with an asynchronously 15 | * reset reg. You should still 16 | * properly synchronize your reset 17 | * deassertion. 18 | * 19 | * @param d Data input 20 | * @param q Data Output 21 | * @param clk Clock Input 22 | * @param rst Reset Input 23 | * @param en Write Enable Input 24 | * 25 | */ 26 | 27 | `ifdef RANDOMIZE_GARBAGE_ASSIGN 28 | `define RANDOMIZE 29 | `endif 30 | `ifdef RANDOMIZE_INVALID_ASSIGN 31 | `define RANDOMIZE 32 | `endif 33 | `ifdef RANDOMIZE_REG_INIT 34 | `define RANDOMIZE 35 | `endif 36 | `ifdef RANDOMIZE_MEM_INIT 37 | `define RANDOMIZE 38 | `endif 39 | 40 | module AsyncResetReg (d, q, en, clk, rst); 41 | parameter RESET_VALUE = 0; 42 | 43 | input wire d; 44 | output reg q; 45 | input wire en; 46 | input wire clk; 47 | input wire rst; 48 | 49 | // There is a lot of initialization 50 | // here you don't normally find in Verilog 51 | // async registers because of scenarios in which reset 52 | // is not actually asserted cleanly at time 0, 53 | // and we want to make sure to properly model 54 | // that, yet Chisel codebase is absolutely intolerant 55 | // of Xs. 56 | `ifndef SYNTHESIS 57 | initial begin:B0 58 | `ifdef RANDOMIZE 59 | integer initvar; 60 | reg [31:0] _RAND; 61 | _RAND = {1{$random}}; 62 | q = _RAND[0]; 63 | `endif // RANDOMIZE 64 | if (rst) begin 65 | q = RESET_VALUE[0]; 66 | end 67 | end 68 | `endif 69 | 70 | always @(posedge clk or posedge rst) begin 71 | 72 | if (rst) begin 73 | q <= RESET_VALUE[0]; 74 | end else if (en) begin 75 | q <= d; 76 | end 77 | end 78 | 79 | endmodule // AsyncResetReg 80 | 81 | -------------------------------------------------------------------------------- /src/main/resources/vsrc/ClockDivider2.v: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | 3 | /** This black-boxes a Clock Divider by 2. 4 | * The output clock is phase-aligned to the input clock. 5 | * If you use this in synthesis, make sure your sdc 6 | * declares that you want it to do the same. 7 | * 8 | * Because Chisel does not support 9 | * blocking assignments, it is impossible 10 | * to create a deterministic divided clock. 11 | * 12 | * @param clk_out Divided Clock 13 | * @param clk_in Clock Input 14 | * 15 | */ 16 | 17 | module ClockDivider2 (output reg clk_out, input clk_in); 18 | 19 | initial clk_out = 1'b0; 20 | always @(posedge clk_in) begin 21 | clk_out = ~clk_out; // Must use =, NOT <= 22 | end 23 | 24 | endmodule // ClockDivider2 25 | -------------------------------------------------------------------------------- /src/main/resources/vsrc/ClockDivider3.v: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | 3 | /** This black-boxes a Clock Divider by 3. 4 | * The output clock is phase-aligned to the input clock. 5 | * Do NOT use this in synthesis; the duty cycle is 2:1. 6 | * 7 | * Because Chisel does not support 8 | * blocking assignments, it is impossible 9 | * to create a deterministic divided clock. 10 | * 11 | * @param clk_out Divided Clock 12 | * @param clk_in Clock Input 13 | * 14 | */ 15 | 16 | module ClockDivider3 (output reg clk_out, input clk_in); 17 | 18 | reg delay; 19 | 20 | initial begin 21 | clk_out = 1'b0; 22 | delay = 1'b0; 23 | end 24 | 25 | always @(posedge clk_in) begin 26 | if (clk_out == 1'b0) begin 27 | clk_out = 1'b1; 28 | delay <= 1'b0; 29 | end else if (delay == 1'b1) begin 30 | clk_out = 1'b0; 31 | delay <= 1'b0; 32 | end else begin 33 | delay <= 1'b1; 34 | end 35 | end 36 | 37 | endmodule // ClockDivider3 38 | -------------------------------------------------------------------------------- /src/main/resources/vsrc/EICG_wrapper.v: -------------------------------------------------------------------------------- 1 | /* verilator lint_off UNOPTFLAT */ 2 | 3 | module EICG_wrapper( 4 | output out, 5 | input en, 6 | input test_en, 7 | input in 8 | ); 9 | 10 | reg en_latched /*verilator clock_enable*/; 11 | 12 | always @(*) begin 13 | if (!in) begin 14 | en_latched = en || test_en; 15 | end 16 | end 17 | 18 | assign out = en_latched && in; 19 | 20 | endmodule 21 | -------------------------------------------------------------------------------- /src/main/resources/vsrc/TraceSinkMonitor.v: -------------------------------------------------------------------------------- 1 | module TraceSinkMonitor 2 | #( 3 | parameter FILE_NAME = "trace_sink_monitor.txt" 4 | ) 5 | ( 6 | input clk, 7 | input reset, 8 | input in_fire, 9 | input[7:0] in_byte 10 | ); 11 | 12 | `ifndef SYNTHESIS 13 | 14 | integer file; 15 | 16 | initial begin 17 | file = $fopen(FILE_NAME, "w"); 18 | if (file == 0) begin 19 | $display("Failed to open %s", FILE_NAME); 20 | $finish; 21 | end 22 | end 23 | 24 | always @(posedge clk) begin 25 | if (in_fire & ~reset) begin 26 | $fwrite(file, "%c", in_byte); 27 | end 28 | end 29 | 30 | final begin 31 | $fclose(file); 32 | end 33 | 34 | `endif 35 | 36 | endmodule -------------------------------------------------------------------------------- /src/main/resources/vsrc/plusarg_reader.v: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | 3 | //VCS coverage exclude_file 4 | 5 | // No default parameter values are intended, nor does IEEE 1800-2012 require them (clause A.2.4 param_assignment), 6 | // but Incisive demands them. These default values should never be used. 7 | module plusarg_reader #( 8 | parameter FORMAT="borked=%d", 9 | parameter WIDTH=1, 10 | parameter [WIDTH-1:0] DEFAULT=0 11 | ) ( 12 | output [WIDTH-1:0] out 13 | ); 14 | 15 | `ifdef SYNTHESIS 16 | assign out = DEFAULT; 17 | `else 18 | reg [WIDTH-1:0] myplus; 19 | assign out = myplus; 20 | 21 | initial begin 22 | if (!$value$plusargs(FORMAT, myplus)) myplus = DEFAULT; 23 | end 24 | `endif 25 | 26 | endmodule 27 | -------------------------------------------------------------------------------- /src/main/scala/amba/ahb/AHBLite.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | 3 | package freechips.rocketchip.amba.ahb 4 | 5 | import chisel3._ 6 | import org.chipsalliance.cde.config.Parameters 7 | import org.chipsalliance.diplomacy.lazymodule.{LazyModule, LazyModuleImp} 8 | 9 | class AHBLite()(implicit p: Parameters) extends LazyModule { 10 | val node = AHBMasterAdapterNode( 11 | masterFn = { mp => mp }, 12 | slaveFn = { sp => sp.copy(lite = false) }) 13 | 14 | lazy val module = new Impl 15 | class Impl extends LazyModuleImp(this) { 16 | (node.in zip node.out) foreach { case ((in, edgeIn), (out, edgeOut)) => 17 | require (edgeOut.slave.lite) // or else this adapter is pointless 18 | 19 | out.hmastlock.get := in.hlock.get 20 | in.hgrant.get := true.B 21 | in.hresp := out.hresp // zero-extended 22 | 23 | in.hready := out.hready 24 | out.htrans := in.htrans 25 | out.hsize := in.hsize 26 | out.hburst := in.hburst 27 | out.hwrite := in.hwrite 28 | out.hprot := in.hprot 29 | out.haddr := in.haddr 30 | out.hwdata := in.hwdata 31 | out.hauser :<>= in.hauser 32 | in.hduser :<>= out.hduser 33 | in.hrdata := out.hrdata 34 | } 35 | } 36 | } 37 | 38 | object AHBLite { 39 | def apply()(implicit p: Parameters) = { 40 | val ahblite = LazyModule(new AHBLite) 41 | ahblite.node 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/main/scala/amba/ahb/Monitor.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | 3 | package freechips.rocketchip.amba.ahb 4 | 5 | import chisel3._ 6 | 7 | case class AHBSlaveMonitorArgs(edge: AHBEdgeParameters) 8 | 9 | abstract class AHBSlaveMonitorBase(args: AHBSlaveMonitorArgs) extends Module 10 | { 11 | val io = IO(new Bundle { 12 | val in = Input(new AHBSlaveBundle(args.edge.bundle)) 13 | }) 14 | 15 | def legalize(bundle: AHBSlaveBundle, edge: AHBEdgeParameters, reset: Reset): Unit 16 | legalize(io.in, args.edge, reset) 17 | } 18 | 19 | 20 | case class AHBMasterMonitorArgs(edge: AHBEdgeParameters) 21 | 22 | abstract class AHBMasterMonitorBase(args: AHBMasterMonitorArgs) extends Module 23 | { 24 | val io = IO(new Bundle { 25 | val in = Input(new AHBMasterBundle(args.edge.bundle)) 26 | }) 27 | 28 | def legalize(bundle: AHBMasterBundle, edge: AHBEdgeParameters, reset: Reset): Unit 29 | legalize(io.in, args.edge, reset) 30 | } 31 | -------------------------------------------------------------------------------- /src/main/scala/amba/ahb/Protocol.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | 3 | package freechips.rocketchip.amba.ahb 4 | 5 | import chisel3._ 6 | 7 | object AHBParameters 8 | { 9 | // These are all fixed by the AHB standard: 10 | val transBits = 2 11 | val burstBits = 3 12 | val protBits = 4 13 | val sizeBits = 3 // 8*2^s 14 | val userBits = 3 15 | val hrespBits = 2 // AHB full 16 | 17 | def TRANS_IDLE = 0.U(transBits.W) // No transfer requested, not in a burst 18 | def TRANS_BUSY = 1.U(transBits.W) // No transfer requested, in a burst 19 | def TRANS_NONSEQ = 2.U(transBits.W) // First (potentially only) request in a burst 20 | def TRANS_SEQ = 3.U(transBits.W) // Following requests in a burst 21 | 22 | def BURST_SINGLE = 0.U(burstBits.W) // Single access (no burst) 23 | def BURST_INCR = 1.U(burstBits.W) // Incrementing burst of arbitrary length, not crossing 1KB 24 | def BURST_WRAP4 = 2.U(burstBits.W) // 4-beat wrapping burst 25 | def BURST_INCR4 = 3.U(burstBits.W) // 4-beat incrementing burst 26 | def BURST_WRAP8 = 4.U(burstBits.W) // 8-beat wrapping burst 27 | def BURST_INCR8 = 5.U(burstBits.W) // 8-beat incrementing burst 28 | def BURST_WRAP16 = 6.U(burstBits.W) // 16-beat wrapping burst 29 | def BURST_INCR16 = 7.U(burstBits.W) // 16-beat incrementing burst 30 | 31 | val maxTransfer = 16 32 | 33 | def RESP_OKAY = 0.U(2.W) 34 | def RESP_ERROR = 1.U(2.W) 35 | // Only in AHB-Full: 36 | def RESP_RETRY = 2.U(2.W) 37 | def RESP_SPLIT = 3.U(2.W) 38 | 39 | def PROT_DATA = 1.U(protBits.W) 40 | def PROT_PRIVILEGED = 2.U(protBits.W) 41 | def PROT_BUFFERABLE = 4.U(protBits.W) 42 | def PROT_CACHEABLE = 8.U(protBits.W) 43 | def PROT_DEFAULT = PROT_DATA | PROT_PRIVILEGED 44 | } 45 | -------------------------------------------------------------------------------- /src/main/scala/amba/ahb/package.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | 3 | package freechips.rocketchip.amba 4 | 5 | import org.chipsalliance.diplomacy.nodes.{InwardNodeHandle, OutwardNodeHandle, SimpleNodeHandle} 6 | 7 | package object ahb 8 | { 9 | type AHBSlaveOutwardNode = OutwardNodeHandle[AHBMasterPortParameters, AHBSlavePortParameters, AHBEdgeParameters, AHBSlaveBundle] 10 | type AHBSlaveInwardNode = InwardNodeHandle[AHBMasterPortParameters, AHBSlavePortParameters, AHBEdgeParameters, AHBSlaveBundle] 11 | type AHBSlaveNode = SimpleNodeHandle[AHBMasterPortParameters, AHBSlavePortParameters, AHBEdgeParameters, AHBSlaveBundle] 12 | type AHBMasterOutwardNode = OutwardNodeHandle[AHBMasterPortParameters, AHBSlavePortParameters, AHBEdgeParameters, AHBMasterBundle] 13 | type AHBMasterInwardNode = InwardNodeHandle[AHBMasterPortParameters, AHBSlavePortParameters, AHBEdgeParameters, AHBMasterBundle] 14 | type AHBMasterNode = SimpleNodeHandle[AHBMasterPortParameters, AHBSlavePortParameters, AHBEdgeParameters, AHBMasterBundle] 15 | } 16 | -------------------------------------------------------------------------------- /src/main/scala/amba/apb/Bundles.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | 3 | package freechips.rocketchip.amba.apb 4 | 5 | import chisel3._ 6 | import freechips.rocketchip.util._ 7 | 8 | // Signal directions are from the master's point-of-view 9 | class APBBundle(val params: APBBundleParameters) extends Bundle 10 | { 11 | // Flow control signals from the master 12 | val psel = Output(Bool()) 13 | val penable = Output(Bool()) 14 | 15 | // Payload signals 16 | val pwrite = Output(Bool()) 17 | val paddr = Output(UInt(params.addrBits.W)) 18 | val pprot = Output(UInt(params.protBits.W)) 19 | val pwdata = Output(UInt(params.dataBits.W)) 20 | val pstrb = Output(UInt((params.dataBits/8).W)) 21 | val pauser = BundleMap(params.requestFields) 22 | 23 | val pready = Input(Bool()) 24 | val pslverr = Input(Bool()) 25 | val prdata = Input(UInt(params.dataBits.W)) 26 | val pduser = BundleMap(params.responseFields) 27 | } 28 | 29 | object APBBundle 30 | { 31 | def apply(params: APBBundleParameters) = new APBBundle(params) 32 | } 33 | -------------------------------------------------------------------------------- /src/main/scala/amba/apb/Monitor.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | 3 | package freechips.rocketchip.amba.apb 4 | 5 | import chisel3._ 6 | 7 | case class APBMonitorArgs(edge: APBEdgeParameters) 8 | 9 | abstract class APBMonitorBase(args: APBMonitorArgs) extends Module 10 | { 11 | val io = IO(new Bundle { 12 | val in = Input(new APBBundle(args.edge.bundle)) 13 | }) 14 | 15 | def legalize(bundle: APBBundle, edge: APBEdgeParameters, reset: Reset): Unit 16 | legalize(io.in, args.edge, reset) 17 | } 18 | -------------------------------------------------------------------------------- /src/main/scala/amba/apb/Nodes.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | 3 | package freechips.rocketchip.amba.apb 4 | 5 | import chisel3._ 6 | import chisel3.experimental.SourceInfo 7 | 8 | import org.chipsalliance.cde.config.{Parameters, Field} 9 | 10 | import org.chipsalliance.diplomacy.ValName 11 | import org.chipsalliance.diplomacy.nodes.{SimpleNodeImp,RenderedEdge, InwardNode, OutwardNode, SourceNode, SinkNode, NexusNode, IdentityNode} 12 | 13 | case object APBMonitorBuilder extends Field[APBMonitorArgs => APBMonitorBase] 14 | 15 | object APBImp extends SimpleNodeImp[APBMasterPortParameters, APBSlavePortParameters, APBEdgeParameters, APBBundle] 16 | { 17 | def edge(pd: APBMasterPortParameters, pu: APBSlavePortParameters, p: Parameters, sourceInfo: SourceInfo) = APBEdgeParameters(pd, pu, p, sourceInfo) 18 | def bundle(e: APBEdgeParameters) = APBBundle(e.bundle) 19 | def render(e: APBEdgeParameters) = RenderedEdge(colour = "#00ccff" /* bluish */, (e.slave.beatBytes * 8).toString) 20 | 21 | override def monitor(bundle: APBBundle, edge: APBEdgeParameters): Unit = { 22 | edge.params.lift(APBMonitorBuilder).foreach { builder => 23 | val monitor = Module(builder(APBMonitorArgs(edge))) 24 | monitor.io.in := bundle 25 | } 26 | } 27 | 28 | override def mixO(pd: APBMasterPortParameters, node: OutwardNode[APBMasterPortParameters, APBSlavePortParameters, APBBundle]): APBMasterPortParameters = 29 | pd.copy(masters = pd.masters.map { c => c.copy (nodePath = node +: c.nodePath) }) 30 | override def mixI(pu: APBSlavePortParameters, node: InwardNode[APBMasterPortParameters, APBSlavePortParameters, APBBundle]): APBSlavePortParameters = 31 | pu.copy(slaves = pu.slaves.map { m => m.copy (nodePath = node +: m.nodePath) }) 32 | } 33 | 34 | case class APBMasterNode(portParams: Seq[APBMasterPortParameters])(implicit valName: ValName) extends SourceNode(APBImp)(portParams) 35 | case class APBSlaveNode(portParams: Seq[APBSlavePortParameters])(implicit valName: ValName) extends SinkNode(APBImp)(portParams) 36 | case class APBNexusNode( 37 | masterFn: Seq[APBMasterPortParameters] => APBMasterPortParameters, 38 | slaveFn: Seq[APBSlavePortParameters] => APBSlavePortParameters)( 39 | implicit valName: ValName) 40 | extends NexusNode(APBImp)(masterFn, slaveFn) 41 | 42 | case class APBIdentityNode()(implicit valName: ValName) extends IdentityNode(APBImp)() 43 | -------------------------------------------------------------------------------- /src/main/scala/amba/apb/Protocol.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | 3 | package freechips.rocketchip.amba.apb 4 | 5 | import chisel3._ 6 | 7 | object APBParameters 8 | { 9 | // These are all fixed by the AHB standard: 10 | val protBits = 3 11 | 12 | def PROT_PRIVILEGED = 1.U(protBits.W) 13 | def PROT_NONSECURE = 2.U(protBits.W) 14 | def PROT_INSTRUCTION = 4.U(protBits.W) 15 | def PROT_DEFAULT = PROT_PRIVILEGED 16 | } 17 | -------------------------------------------------------------------------------- /src/main/scala/amba/apb/Test.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | 3 | package freechips.rocketchip.amba.apb 4 | 5 | import chisel3._ 6 | 7 | import org.chipsalliance.cde.config.Parameters 8 | 9 | import org.chipsalliance.diplomacy.lazymodule.{LazyModule, LazyModuleImp} 10 | 11 | import freechips.rocketchip.diplomacy.{BufferParams, AddressSet} 12 | import freechips.rocketchip.regmapper.{RRTest0, RRTest1} 13 | import freechips.rocketchip.tilelink.{TLFuzzer, TLRAMModel, TLToAPB, TLDelayer, TLBuffer, TLFragmenter} 14 | import freechips.rocketchip.unittest._ 15 | 16 | class APBRRTest0(address: BigInt)(implicit p: Parameters) 17 | extends RRTest0(address) 18 | with HasAPBControlRegMap 19 | 20 | class APBRRTest1(address: BigInt)(implicit p: Parameters) 21 | extends RRTest1(address, concurrency = 1, undefZero = false) 22 | with HasAPBControlRegMap 23 | 24 | class APBFuzzBridge(aFlow: Boolean, txns: Int)(implicit p: Parameters) extends LazyModule 25 | { 26 | val fuzz = LazyModule(new TLFuzzer(txns)) 27 | val model = LazyModule(new TLRAMModel("APBFuzzMaster")) 28 | val xbar = LazyModule(new APBFanout) 29 | val ram = LazyModule(new APBRAM(AddressSet(0x0, 0xff), fuzzReady = true, fuzzError = true)) 30 | val gpio = LazyModule(new APBRRTest0(0x100)) 31 | 32 | ram.node := xbar.node 33 | gpio.node := xbar.node 34 | (xbar.node 35 | := TLToAPB(aFlow) 36 | := TLDelayer(0.2) 37 | := TLBuffer(BufferParams.flow) 38 | := TLDelayer(0.2) 39 | := TLFragmenter(4, 8) 40 | := model.node 41 | := fuzz.node) 42 | 43 | lazy val module = new Impl 44 | class Impl extends LazyModuleImp(this) with UnitTestModule { 45 | io.finished := fuzz.module.io.finished 46 | } 47 | } 48 | 49 | class APBBridgeTest(aFlow: Boolean, txns: Int = 5000, timeout: Int = 500000)(implicit p: Parameters) extends UnitTest(timeout) { 50 | val dut = Module(LazyModule(new APBFuzzBridge(aFlow, txns)).module) 51 | io.finished := dut.io.finished 52 | dut.io.start := io.start 53 | } 54 | -------------------------------------------------------------------------------- /src/main/scala/amba/apb/Xbar.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | 3 | package freechips.rocketchip.amba.apb 4 | 5 | import chisel3._ 6 | import chisel3.util.Mux1H 7 | 8 | import org.chipsalliance.cde.config.Parameters 9 | 10 | import org.chipsalliance.diplomacy.lazymodule.{LazyModule, LazyModuleImp} 11 | 12 | import freechips.rocketchip.diplomacy.AddressDecoder 13 | import freechips.rocketchip.util.BundleField 14 | 15 | class APBFanout()(implicit p: Parameters) extends LazyModule { 16 | val node = new APBNexusNode( 17 | masterFn = { case Seq(m) => m }, 18 | slaveFn = { seq => 19 | seq(0).copy( 20 | slaves = seq.flatMap(_.slaves), 21 | requestKeys = seq.flatMap(_.requestKeys).distinct, 22 | responseFields = BundleField.union(seq.flatMap(_.responseFields))) } 23 | ){ 24 | override def circuitIdentity = outputs == 1 && inputs == 1 25 | } 26 | 27 | lazy val module = new Impl 28 | class Impl extends LazyModuleImp(this) { 29 | if (node.edges.in.size >= 1) { 30 | require (node.edges.in.size == 1, "APBFanout does not support multiple masters") 31 | require (node.edges.out.size > 0, "APBFanout requires at least one slave") 32 | 33 | val (in, _) = node.in(0) 34 | 35 | // Require consistent bus widths 36 | val (io_out, edgesOut) = node.out.unzip 37 | val port0 = edgesOut(0).slave 38 | edgesOut.foreach { edge => 39 | val port = edge.slave 40 | require (port.beatBytes == port0.beatBytes, 41 | s"${port.slaves.map(_.name)} ${port.beatBytes} vs ${port0.slaves.map(_.name)} ${port0.beatBytes}") 42 | } 43 | 44 | val port_addrs = edgesOut.map(_.slave.slaves.map(_.address).flatten) 45 | val routingMask = AddressDecoder(port_addrs) 46 | val route_addrs = port_addrs.map(_.map(_.widen(~routingMask)).distinct) 47 | 48 | val sel = VecInit(route_addrs.map(seq => seq.map(_.contains(in.paddr)).reduce(_ || _))) 49 | (sel zip io_out) foreach { case (sel, out) => 50 | out.squeezeAll :<>= in.squeezeAll 51 | out.psel := sel && in.psel 52 | out.penable := sel && in.penable 53 | } 54 | 55 | in.pready := !Mux1H(sel, io_out.map(!_.pready)) 56 | in.pslverr := Mux1H(sel, io_out.map(_.pslverr)) 57 | in.prdata := Mux1H(sel, io_out.map(_.prdata)) 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/main/scala/amba/apb/package.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | 3 | package freechips.rocketchip.amba 4 | 5 | import org.chipsalliance.diplomacy.nodes.{InwardNodeHandle, OutwardNodeHandle, SimpleNodeHandle} 6 | 7 | package object apb 8 | { 9 | type APBOutwardNode = OutwardNodeHandle[APBMasterPortParameters, APBSlavePortParameters, APBEdgeParameters, APBBundle] 10 | type APBInwardNode = InwardNodeHandle[APBMasterPortParameters, APBSlavePortParameters, APBEdgeParameters, APBBundle] 11 | type APBNode = SimpleNodeHandle[APBMasterPortParameters, APBSlavePortParameters, APBEdgeParameters, APBBundle] 12 | } 13 | -------------------------------------------------------------------------------- /src/main/scala/amba/axi4/Monitor.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | 3 | package freechips.rocketchip.amba.axi4 4 | 5 | import chisel3._ 6 | 7 | case class AXI4MonitorArgs(edge: AXI4EdgeParameters) 8 | 9 | abstract class AXI4MonitorBase(args: AXI4MonitorArgs) extends Module 10 | { 11 | val io = IO(new Bundle { 12 | val in = Input(new AXI4Bundle(args.edge.bundle)) 13 | }) 14 | 15 | def legalize(bundle: AXI4Bundle, edge: AXI4EdgeParameters, reset: Reset): Unit 16 | legalize(io.in, args.edge, reset) 17 | } 18 | -------------------------------------------------------------------------------- /src/main/scala/amba/axi4/Protocol.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | 3 | package freechips.rocketchip.amba.axi4 4 | 5 | import chisel3._ 6 | 7 | object AXI4Parameters 8 | { 9 | // These are all fixed by the AXI4 standard: 10 | val lenBits = 8 11 | val sizeBits = 3 12 | val burstBits = 2 13 | val lockBits = 1 14 | val cacheBits = 4 15 | val protBits = 3 16 | val qosBits = 4 17 | val respBits = 2 18 | 19 | def CACHE_RALLOCATE = 8.U(cacheBits.W) 20 | def CACHE_WALLOCATE = 4.U(cacheBits.W) 21 | def CACHE_MODIFIABLE = 2.U(cacheBits.W) 22 | def CACHE_BUFFERABLE = 1.U(cacheBits.W) 23 | 24 | def PROT_PRIVILEGED = 1.U(protBits.W) 25 | def PROT_INSECURE = 2.U(protBits.W) 26 | def PROT_INSTRUCTION = 4.U(protBits.W) 27 | 28 | def BURST_FIXED = 0.U(burstBits.W) 29 | def BURST_INCR = 1.U(burstBits.W) 30 | def BURST_WRAP = 2.U(burstBits.W) 31 | 32 | def RESP_OKAY = 0.U(respBits.W) 33 | def RESP_EXOKAY = 1.U(respBits.W) 34 | def RESP_SLVERR = 2.U(respBits.W) 35 | def RESP_DECERR = 3.U(respBits.W) 36 | } 37 | -------------------------------------------------------------------------------- /src/main/scala/amba/axi4/package.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | 3 | package freechips.rocketchip.amba 4 | 5 | import org.chipsalliance.diplomacy.ValName 6 | import org.chipsalliance.diplomacy.nodes.{SimpleNodeHandle, OutwardNodeHandle, InwardNodeHandle} 7 | 8 | import freechips.rocketchip.prci.{HasClockDomainCrossing, HasResetDomainCrossing} 9 | 10 | /** 11 | * Provide bundles, adapters and devices etc for AMBA AXI4 protocol. 12 | */ 13 | package object axi4 14 | { 15 | type AXI4Node = SimpleNodeHandle[AXI4MasterPortParameters, AXI4SlavePortParameters, AXI4EdgeParameters, AXI4Bundle] 16 | type AXI4OutwardNode = OutwardNodeHandle[AXI4MasterPortParameters, AXI4SlavePortParameters, AXI4EdgeParameters, AXI4Bundle] 17 | type AXI4InwardNode = InwardNodeHandle[AXI4MasterPortParameters, AXI4SlavePortParameters, AXI4EdgeParameters, AXI4Bundle] 18 | 19 | implicit class AXI4ClockDomainCrossing(private val x: HasClockDomainCrossing) extends AnyVal { 20 | def crossIn (n: AXI4InwardNode) (implicit valName: ValName) = AXI4InwardClockCrossingHelper(valName.value, x, n) 21 | def crossOut(n: AXI4OutwardNode)(implicit valName: ValName) = AXI4OutwardClockCrossingHelper(valName.value, x, n) 22 | def cross(n: AXI4InwardNode) (implicit valName: ValName) = crossIn(n) 23 | def cross(n: AXI4OutwardNode)(implicit valName: ValName) = crossOut(n) 24 | } 25 | 26 | implicit class AXI4ResetDomainCrossing(private val x: HasResetDomainCrossing) extends AnyVal { 27 | def crossIn (n: AXI4InwardNode) (implicit valName: ValName) = AXI4InwardResetCrossingHelper(valName.value, x, n) 28 | def crossOut(n: AXI4OutwardNode)(implicit valName: ValName) = AXI4OutwardResetCrossingHelper(valName.value, x, n) 29 | def cross(n: AXI4InwardNode) (implicit valName: ValName) = crossIn(n) 30 | def cross(n: AXI4OutwardNode)(implicit valName: ValName) = crossOut(n) 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/main/scala/amba/axis/Buffer.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | 3 | package freechips.rocketchip.amba.axis 4 | 5 | import org.chipsalliance.cde.config.Parameters 6 | import org.chipsalliance.diplomacy.lazymodule.{LazyModule, LazyModuleImp} 7 | 8 | import freechips.rocketchip.diplomacy.BufferParams 9 | 10 | class AXISBuffer(val params: BufferParams)(implicit p: Parameters) extends LazyModule 11 | { 12 | val node = AXISAdapterNode() 13 | lazy val module = new Impl 14 | class Impl extends LazyModuleImp(this) { 15 | (node.in zip node.out) foreach { case ((in, edgeIn), (out, edgeOut)) => 16 | out.waiveAs[chisel3.Data]() :<>= params.irrevocable(in).waiveAs[chisel3.Data]() 17 | } 18 | } 19 | } 20 | 21 | object AXISBuffer 22 | { 23 | def apply(params: BufferParams = BufferParams.default)(implicit p: Parameters) = { 24 | val buffer = LazyModule(new AXISBuffer(params)) 25 | buffer.node 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/main/scala/amba/axis/Nodes.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | 3 | package freechips.rocketchip.amba.axis 4 | 5 | import chisel3.experimental.SourceInfo 6 | 7 | import org.chipsalliance.cde.config.Parameters 8 | import org.chipsalliance.diplomacy.ValName 9 | import org.chipsalliance.diplomacy.nodes.{SimpleNodeImp, SourceNode, SinkNode, NexusNode, AdapterNode, OutwardNode, IdentityNode, RenderedEdge, InwardNode} 10 | 11 | object AXISImp extends SimpleNodeImp[AXISMasterPortParameters, AXISSlavePortParameters, AXISEdgeParameters, AXISBundle] 12 | { 13 | def edge(pd: AXISMasterPortParameters, pu: AXISSlavePortParameters, p: Parameters, sourceInfo: SourceInfo) = AXISEdgeParameters.v1(pd, pu, p, sourceInfo) 14 | def bundle(e: AXISEdgeParameters) = AXISBundle(e.bundle) 15 | def render(e: AXISEdgeParameters) = RenderedEdge(colour = "#00ccff" /* bluish */, (e.beatBytes * 8).toString) 16 | 17 | override def mixO(pd: AXISMasterPortParameters, node: OutwardNode[AXISMasterPortParameters, AXISSlavePortParameters, AXISBundle]): AXISMasterPortParameters = 18 | pd.v1copy(masters = pd.masters.map { c => c.v1copy (nodePath = node +: c.nodePath) }) 19 | override def mixI(pu: AXISSlavePortParameters, node: InwardNode[AXISMasterPortParameters, AXISSlavePortParameters, AXISBundle]): AXISSlavePortParameters = 20 | pu.v1copy(slaves = pu.slaves.map { m => m.v1copy (nodePath = node +: m.nodePath) }) 21 | } 22 | 23 | case class AXISMasterNode(portParams: Seq[AXISMasterPortParameters])(implicit valName: ValName) extends SourceNode(AXISImp)(portParams) 24 | case class AXISSlaveNode(portParams: Seq[AXISSlavePortParameters])(implicit valName: ValName) extends SinkNode(AXISImp)(portParams) 25 | case class AXISNexusNode( 26 | masterFn: Seq[AXISMasterPortParameters] => AXISMasterPortParameters, 27 | slaveFn: Seq[AXISSlavePortParameters] => AXISSlavePortParameters)( 28 | implicit valName: ValName) 29 | extends NexusNode(AXISImp)(masterFn, slaveFn) 30 | 31 | case class AXISAdapterNode( 32 | masterFn: AXISMasterPortParameters => AXISMasterPortParameters = { m => m }, 33 | slaveFn: AXISSlavePortParameters => AXISSlavePortParameters = { s => s })( 34 | implicit valName: ValName) 35 | extends AdapterNode(AXISImp)(masterFn, slaveFn) 36 | case class AXISIdentityNode()(implicit valName: ValName) extends IdentityNode(AXISImp)() 37 | -------------------------------------------------------------------------------- /src/main/scala/amba/axis/package.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | 3 | package freechips.rocketchip.amba 4 | 5 | import org.chipsalliance.diplomacy.nodes.{InwardNodeHandle, OutwardNodeHandle, NodeHandle} 6 | 7 | package object axis 8 | { 9 | type AXISInwardNode = InwardNodeHandle[AXISMasterPortParameters, AXISSlavePortParameters, AXISEdgeParameters, AXISBundle] 10 | type AXISOutwardNode = OutwardNodeHandle[AXISMasterPortParameters, AXISSlavePortParameters, AXISEdgeParameters, AXISBundle] 11 | type AXISNode = NodeHandle[AXISMasterPortParameters, AXISSlavePortParameters, AXISEdgeParameters, AXISBundle, AXISMasterPortParameters, AXISSlavePortParameters, AXISEdgeParameters, AXISBundle] 12 | } 13 | -------------------------------------------------------------------------------- /src/main/scala/amba/package.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | 3 | package freechips.rocketchip 4 | 5 | import chisel3._ 6 | 7 | import freechips.rocketchip.util.{ControlKey, DataKey, BundleField} 8 | 9 | package object amba { 10 | class AMBAProtBundle extends Bundle { 11 | val bufferable = Bool() // writeback caching ok? 12 | val modifiable = Bool() // legal to read/write-combine/expand this request? 13 | val readalloc = Bool() 14 | val writealloc = Bool() 15 | val privileged = Bool() // machine_mode=true, user_mode=false 16 | val secure = Bool() // secure_master=true, normal=false 17 | val fetch = Bool() // instruct_fetch=true, load/store=false 18 | } 19 | 20 | case object AMBAProt extends ControlKey[AMBAProtBundle]("amba_prot") 21 | 22 | case class AMBAProtField() extends BundleField[AMBAProtBundle](AMBAProt, Output(new AMBAProtBundle), x => { 23 | x.bufferable := false.B 24 | x.modifiable := false.B 25 | x.readalloc := false.B 26 | x.writealloc := false.B 27 | x.privileged := true.B 28 | x.secure := true.B 29 | x.fetch := false.B 30 | }) 31 | 32 | // Used to convert a TileLink corrupt signal into an AMBA user bit 33 | case object AMBACorrupt extends DataKey[Bool]("corrupt") 34 | case class AMBACorruptField() extends BundleField[Bool](AMBACorrupt, Output(Bool()), x => x := false.B) 35 | } 36 | -------------------------------------------------------------------------------- /src/main/scala/aop/package.scala: -------------------------------------------------------------------------------- 1 | package freechips.rocketchip 2 | 3 | object aop { 4 | @deprecated("aop has moved to the standalone diplomacy library.", "rocketchip 2.0.0") 5 | val Select = _root_.org.chipsalliance.diplomacy.aop.Select 6 | } 7 | -------------------------------------------------------------------------------- /src/main/scala/devices/debug/APB.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | 3 | package freechips.rocketchip.devices.debug 4 | 5 | import org.chipsalliance.cde.config._ 6 | import org.chipsalliance.diplomacy.lazymodule._ 7 | 8 | import freechips.rocketchip.amba.apb.APBRegisterNode 9 | import freechips.rocketchip.diplomacy.AddressSet 10 | import freechips.rocketchip.regmapper.RegField 11 | 12 | case object APBDebugRegistersKey extends Field[Map[Int, Seq[RegField]]](Map()) 13 | 14 | object APBDebugConsts { 15 | def apbDebugRegBase = 0xF00 16 | def apbDebugRegSize = 0x100 17 | } 18 | 19 | class APBDebugRegisters()(implicit p: Parameters) extends LazyModule { 20 | 21 | val node = APBRegisterNode( 22 | address = AddressSet(base=APBDebugConsts.apbDebugRegBase, mask=APBDebugConsts.apbDebugRegSize-1), 23 | beatBytes = 4, 24 | executable = false 25 | ) 26 | 27 | lazy val module = new Impl 28 | class Impl extends LazyModuleImp(this){ 29 | node.regmap(p(APBDebugRegistersKey).toList:_*) 30 | 31 | } 32 | } 33 | 34 | 35 | -------------------------------------------------------------------------------- /src/main/scala/devices/debug/DebugRomContents.scala: -------------------------------------------------------------------------------- 1 | // This file was auto-generated by 'make publish' in debug/ directory. 2 | 3 | package freechips.rocketchip.devices.debug 4 | 5 | object DebugRomContents { 6 | 7 | def apply() : Array[Byte] = { Array ( 8 | 0x6f, 0x00, 0xc0, 0x00, 0x6f, 0x00, 0x80, 0x03, 0x6f, 0x00, 0x40, 0x04, 9 | 0x0f, 0x00, 0xf0, 0x0f, 0x73, 0x10, 0x24, 0x7b, 0x73, 0x24, 0x40, 0xf1, 10 | 0x23, 0x20, 0x80, 0x10, 0x03, 0x44, 0x04, 0x40, 0x13, 0x74, 0x34, 0x00, 11 | 0xe3, 0x08, 0x04, 0xfe, 0x13, 0x74, 0x14, 0x00, 0x63, 0x08, 0x04, 0x00, 12 | 0x73, 0x24, 0x20, 0x7b, 0x23, 0x22, 0x00, 0x10, 0x67, 0x00, 0x00, 0x30, 13 | 0x73, 0x24, 0x40, 0xf1, 0x23, 0x24, 0x80, 0x10, 0x73, 0x24, 0x20, 0x7b, 14 | 0x73, 0x00, 0x20, 0x7b, 0x23, 0x26, 0x00, 0x10, 0x73, 0x00, 0x10, 0x00 15 | ).map(_.toByte) } 16 | 17 | } 18 | 19 | -------------------------------------------------------------------------------- /src/main/scala/devices/debug/DebugRomNonzeroContents.scala: -------------------------------------------------------------------------------- 1 | // This file was auto-generated by 'make publish' in debug/ directory. 2 | 3 | package freechips.rocketchip.devices.debug 4 | 5 | object DebugRomNonzeroContents { 6 | 7 | def apply() : Array[Byte] = { Array ( 8 | 0x73, 0x90, 0x34, 0x7b, 0x6f, 0x00, 0xc0, 0x00, 0xf3, 0x94, 0x34, 0x7b, 9 | 0x23, 0xa6, 0x04, 0x90, 0x0f, 0x00, 0xf0, 0x0f, 0x73, 0x10, 0x24, 0x7b, 10 | 0x97, 0x04, 0x00, 0x00, 0x93, 0x84, 0x84, 0xfe, 0x73, 0x24, 0x40, 0xf1, 11 | 0x23, 0xa0, 0x84, 0x90, 0x33, 0x04, 0x94, 0x00, 0x03, 0x44, 0x04, 0xc0, 12 | 0x13, 0x74, 0x34, 0x00, 0xe3, 0x06, 0x04, 0xfe, 0x13, 0x74, 0x14, 0x00, 13 | 0x63, 0x0c, 0x04, 0x00, 0x73, 0x24, 0x20, 0x7b, 0x67, 0x80, 0x84, 0x04, 14 | 0x23, 0xa2, 0x04, 0x90, 0xf3, 0x94, 0x34, 0x7b, 0x6f, 0xf0, 0x1f, 0xab, 15 | 0x73, 0x24, 0x40, 0xf1, 0x23, 0xa4, 0x84, 0x90, 0x73, 0x24, 0x20, 0x7b, 16 | 0xf3, 0x24, 0x30, 0x7b, 0x73, 0x00, 0x20, 0x7b 17 | ).map(_.toByte) } 18 | 19 | } 20 | 21 | -------------------------------------------------------------------------------- /src/main/scala/devices/debug/abstract_commands.scala: -------------------------------------------------------------------------------- 1 | package freechips.rocketchip.devices.debug 2 | 3 | import chisel3._ 4 | 5 | // This file was auto-generated from the repository at https://github.com/riscv/riscv-debug-spec.git, 6 | // 'make chisel' 7 | 8 | object AC_RegAddrs { 9 | } 10 | 11 | class ACCESS_REGISTERFields extends Bundle { 12 | 13 | /* This is 0 to indicate Access Register Command. 14 | */ 15 | val cmdtype = UInt(8.W) 16 | 17 | val reserved0 = UInt(1.W) 18 | 19 | /* 2: Access the lowest 32 bits of the register. 20 | 21 | 3: Access the lowest 64 bits of the register. 22 | 23 | 4: Access the lowest 128 bits of the register. 24 | 25 | If \Fsize specifies a size larger than the register's actual size, 26 | then the access must fail. If a register is accessible, then reads of \Fsize 27 | less than or equal to the register's actual size must be supported. 28 | 29 | This field controls the Argument Width as referenced in 30 | Table~\ref{tab:datareg}. 31 | */ 32 | val size = UInt(3.W) 33 | 34 | val reserved1 = UInt(1.W) 35 | 36 | /* When 1, execute the program in the Program Buffer exactly once 37 | after performing the transfer, if any. 38 | */ 39 | val postexec = Bool() 40 | 41 | /* 0: Don't do the operation specified by \Fwrite. 42 | 43 | 1: Do the operation specified by \Fwrite. 44 | 45 | This bit can be used to just execute the Program Buffer without 46 | having to worry about placing valid values into \Fsize or \Fregno. 47 | */ 48 | val transfer = Bool() 49 | 50 | /* When \Ftransfer is set: 51 | 0: Copy data from the specified register into {\tt arg0} portion 52 | of {\tt data}. 53 | 54 | 1: Copy data from {\tt arg0} portion of {\tt data} into the 55 | specified register. 56 | */ 57 | val write = Bool() 58 | 59 | /* Number of the register to access, as described in 60 | Table~\ref{tab:regno}. 61 | \Rdpc may be used as an alias for PC if this command is 62 | supported on a non-halted hart. 63 | */ 64 | val regno = UInt(16.W) 65 | 66 | } 67 | 68 | class QUICK_ACCESSFields extends Bundle { 69 | 70 | /* This is 1 to indicate Quick Access command. 71 | */ 72 | val cmdtype = UInt(8.W) 73 | 74 | val reserved0 = UInt(24.W) 75 | 76 | } 77 | 78 | -------------------------------------------------------------------------------- /src/main/scala/devices/tilelink/ClockBlocker.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | 3 | package freechips.rocketchip.devices.tilelink 4 | 5 | import chisel3._ 6 | import org.chipsalliance.cde.config._ 7 | import org.chipsalliance.diplomacy.lazymodule._ 8 | 9 | import freechips.rocketchip.diplomacy.{AddressSet} 10 | import freechips.rocketchip.resources.{SimpleDevice} 11 | import freechips.rocketchip.prci.ClockAdapterNode 12 | import freechips.rocketchip.regmapper.{RegField, RegFieldDesc} 13 | import freechips.rocketchip.tilelink.TLRegisterNode 14 | import freechips.rocketchip.util.ClockGate 15 | 16 | /** This device extends a basic bus blocker by allowing it to gate the clocks of the device 17 | * whose tilelink port is being blocked. For now it is only possible to block 18 | * a single TL port and all the clocks simultaneously. 19 | */ 20 | 21 | class TLClockBlocker(params: BasicBusBlockerParams)(implicit p: Parameters) 22 | extends TLBusBypassBase(params.blockedBeatBytes, params.deadlock) 23 | { 24 | val device = new SimpleDevice("clock-blocker", Seq("sifive,clock-blocker0")) 25 | 26 | val controlNode = TLRegisterNode( 27 | address = Seq(AddressSet(params.controlAddress, 0xFFF)), 28 | device = device, 29 | beatBytes = params.controlBeatBytes) 30 | 31 | val clockNode = ClockAdapterNode() 32 | 33 | lazy val module = new Impl 34 | class Impl extends LazyModuleImp(this) { 35 | val allow = RegInit(true.B) 36 | val pending = RegNext(bar.module.io.pending) 37 | 38 | controlNode.regmap( 39 | 0 -> Seq(RegField (32, allow, 40 | RegFieldDesc("allow", 41 | "Used to enable/disable bus transactions", reset=Some(1)))), 42 | 4 -> Seq(RegField.r(32, pending, RegFieldDesc("pending", 43 | "Indicates if bus transactions are in-flight", volatile=true))) 44 | ) 45 | 46 | bar.module.io.bypass := !allow 47 | 48 | val (clock_in, _) = clockNode.in.unzip 49 | val (clock_out, _) = clockNode.out.unzip 50 | 51 | (clock_in zip clock_out) foreach { case (i, o) => 52 | o.clock := ClockGate(i.clock, allow || pending) 53 | o.reset := i.reset 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/main/scala/devices/tilelink/Deadlock.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | 3 | package freechips.rocketchip.devices.tilelink 4 | 5 | import chisel3._ 6 | import org.chipsalliance.cde.config.Parameters 7 | import freechips.rocketchip.diplomacy._ 8 | import freechips.rocketchip.resources.{SimpleDevice} 9 | 10 | /** Adds a /dev/null slave that does not raise ready for any incoming traffic. 11 | * !!! WARNING: This device WILL cause your bus to deadlock for as long as you 12 | * continue to send traffic to it !!! 13 | */ 14 | class TLDeadlock(params: DevNullParams, beatBytes: Int = 4)(implicit p: Parameters) 15 | extends DevNullDevice(params, minLatency = 1, // technically not true but we don't want to add extra logic to handle minLatency = 0 16 | beatBytes, new SimpleDevice("deadlock-device", Seq("sifive,deadlock0"))) 17 | { 18 | lazy val module = new Impl 19 | class Impl extends LazyModuleImp(this) { 20 | val (in, _) = node.in(0) 21 | in.a.ready := false.B 22 | in.b.valid := false.B 23 | in.c.ready := false.B 24 | in.d.valid := false.B 25 | in.e.ready := false.B 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/main/scala/devices/tilelink/Zero.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | 3 | package freechips.rocketchip.devices.tilelink 4 | 5 | import chisel3._ 6 | import chisel3.util._ 7 | 8 | import org.chipsalliance.cde.config._ 9 | import org.chipsalliance.diplomacy.lazymodule._ 10 | 11 | import freechips.rocketchip.diplomacy.{AddressSet, RegionType} 12 | import freechips.rocketchip.resources.{SimpleDevice} 13 | import freechips.rocketchip.tilelink.TLMessages 14 | 15 | /** This /dev/null device accepts single beat gets/puts, as well as atomics. 16 | * Response data is always 0. Reequests to write data have no effect. 17 | */ 18 | class TLZero(address: AddressSet, beatBytes: Int = 4)(implicit p: Parameters) 19 | extends DevNullDevice( 20 | params = DevNullParams( 21 | address = List(address), 22 | maxAtomic = beatBytes, 23 | maxTransfer = beatBytes, 24 | region = RegionType.UNCACHED, 25 | executable = true, 26 | mayDenyGet = false, 27 | mayDenyPut = false), 28 | minLatency = 1, 29 | beatBytes = beatBytes, 30 | device = new SimpleDevice("rom", Seq("ucbbar,cacheable-zero0"))) 31 | { 32 | lazy val module = new Impl 33 | class Impl extends LazyModuleImp(this) { 34 | val (in, edge) = node.in(0) 35 | 36 | val a = Queue(in.a, 2) 37 | 38 | a.ready := in.d.ready 39 | in.d.valid := a.valid 40 | in.d.bits := edge.AccessAck(a.bits) 41 | in.d.bits.opcode := TLMessages.adResponse(edge.opcode(a.bits)) 42 | 43 | // Tie off unused channels 44 | in.b.valid := false.B 45 | in.c.ready := true.B 46 | in.e.ready := true.B 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/main/scala/diplomacy/AddressRange.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | 3 | package freechips.rocketchip.diplomacy 4 | 5 | 6 | // Use AddressSet instead -- this is just for pretty printing 7 | case class AddressRange(base: BigInt, size: BigInt) extends Ordered[AddressRange] 8 | { 9 | val end = base + size 10 | 11 | require (base >= 0, s"AddressRange base must be positive, got: $base") 12 | require (size > 0, s"AddressRange size must be > 0, got: $size") 13 | 14 | def compare(x: AddressRange) = { 15 | val primary = (this.base - x.base).signum 16 | val secondary = (x.size - this.size).signum 17 | if (primary != 0) primary else secondary 18 | } 19 | 20 | def contains(x: AddressRange) = base <= x.base && x.end <= end 21 | def union(x: AddressRange): Option[AddressRange] = { 22 | if (base > x.end || x.base > end) { 23 | None 24 | } else { 25 | val obase = if (base < x.base) base else x.base 26 | val oend = if (end > x.end) end else x.end 27 | Some(AddressRange(obase, oend-obase)) 28 | } 29 | } 30 | 31 | private def helper(base: BigInt, end: BigInt) = 32 | if (base < end) Seq(AddressRange(base, end-base)) else Nil 33 | def subtract(x: AddressRange) = 34 | helper(base, end min x.base) ++ helper(base max x.end, end) 35 | 36 | // We always want to see things in hex 37 | override def toString() = "AddressRange(0x%x, 0x%x)".format(base, size) 38 | 39 | // Other possible output formats 40 | def toUVM: String = f" set_addr_range(1, 32'h${base}%08x, 32'h${end}%08x);" 41 | def toJSON: String = s"""{"base": ${base}, "max": ${end}}""" 42 | } 43 | 44 | object AddressRange 45 | { 46 | def fromSets(seq: Seq[AddressSet]): Seq[AddressRange] = unify(seq.flatMap(_.toRanges)) 47 | def unify(seq: Seq[AddressRange]): Seq[AddressRange] = { 48 | if (seq.isEmpty) return Nil 49 | val ranges = seq.sorted 50 | ranges.tail.foldLeft(Seq(ranges.head)) { 51 | case (head :: tail, x) => 52 | head.union(x) match { 53 | case Some(z) => z :: tail 54 | case None => x :: head :: tail 55 | } 56 | case _ => Unreachable() 57 | }.reverse 58 | } 59 | // Set subtraction... O(n*n) b/c I am lazy 60 | def subtract(from: Seq[AddressRange], take: Seq[AddressRange]): Seq[AddressRange] = 61 | take.foldLeft(from) { case (left, r) => left.flatMap { _.subtract(r) } } 62 | } 63 | -------------------------------------------------------------------------------- /src/main/scala/diplomacy/CloneModule.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | 3 | // !!! HACK TO WORK-AROUND MISSING CHISEL FEATURE 4 | // !!! We need to be inside the chisel3 package to access Builder 5 | 6 | package chisel3.shim 7 | 8 | import chisel3._ 9 | 10 | import scala.collection.immutable.SeqMap 11 | 12 | class ClonePorts protected[shim](elts: Data*) extends Record 13 | { 14 | val elements = SeqMap(elts.map(d => d.instanceName -> chiselTypeOf(d)): _*) 15 | def apply(field: String) = elements(field) 16 | } 17 | -------------------------------------------------------------------------------- /src/main/scala/diplomacy/Main.scala: -------------------------------------------------------------------------------- 1 | package freechips.rocketchip.diplomacy 2 | 3 | import chisel3.RawModule 4 | import chisel3.stage.ChiselGeneratorAnnotation 5 | import chisel3.stage.phases.{Elaborate, Convert} 6 | import firrtl.AnnotationSeq 7 | import firrtl.options.TargetDirAnnotation 8 | import freechips.rocketchip.diplomacy.LazyModule 9 | import org.chipsalliance.cde.config.{Config, Parameters} 10 | import mainargs._ 11 | 12 | object Main { 13 | @main def elaborate( 14 | @arg(name = "dir", doc = "output directory") dir: String, 15 | @arg(name = "top", doc = "top Module or LazyModule fullpath") top: String, 16 | @arg(name = "config", doc = "CDE configs") config: Seq[String] 17 | ) = { 18 | var topName: String = null 19 | val gen = () => 20 | Class 21 | .forName(top) 22 | .getConstructor(classOf[Parameters]) 23 | .newInstance(new Config(config.foldRight(Parameters.empty) { 24 | case (currentName, config) => 25 | val currentConfig = Class.forName(currentName).newInstance.asInstanceOf[Config] 26 | currentConfig ++ config 27 | })) match { 28 | case m: RawModule => m 29 | case lm: LazyModule => LazyModule(lm).module 30 | } 31 | 32 | val annos = Seq( 33 | new Elaborate, 34 | new Convert 35 | ).foldLeft( 36 | Seq( 37 | TargetDirAnnotation(dir), 38 | ChiselGeneratorAnnotation(() => gen()) 39 | ): AnnotationSeq 40 | ) { case (annos, phase) => phase.transform(annos) } 41 | .flatMap { 42 | case firrtl.stage.FirrtlCircuitAnnotation(circuit) => 43 | topName = circuit.main 44 | os.write(os.Path(dir) / s"${circuit.main}.fir", circuit.serialize) 45 | None 46 | case _: chisel3.stage.ChiselCircuitAnnotation => None 47 | case _: chisel3.stage.DesignAnnotation[_] => None 48 | case a => Some(a) 49 | } 50 | os.write(os.Path(dir) / s"$topName.anno.json", firrtl.annotations.JsonProtocol.serialize(annos)) 51 | freechips.rocketchip.util.ElaborationArtefacts.files.foreach{ case (ext, contents) => os.write.over(os.Path(dir) / s"${config.mkString("_")}.${ext}", contents()) } 52 | } 53 | 54 | def main(args: Array[String]): Unit = ParserForMethods(this).runOrExit(args) 55 | } 56 | 57 | -------------------------------------------------------------------------------- /src/main/scala/diplomacy/Unreachable.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | 3 | package freechips.rocketchip.diplomacy 4 | 5 | case object Unreachable { 6 | def apply(): Nothing = throw new AssertionError("unreachable code") 7 | } 8 | -------------------------------------------------------------------------------- /src/main/scala/groundtest/DummyPTW.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | // See LICENSE.Berkeley for license details. 3 | 4 | package freechips.rocketchip.groundtest 5 | 6 | import chisel3._ 7 | import chisel3.util._ 8 | 9 | import org.chipsalliance.cde.config._ 10 | import freechips.rocketchip.rocket._ 11 | import freechips.rocketchip.tile.CoreModule 12 | import freechips.rocketchip.util.ParameterizedBundle 13 | 14 | class DummyPTW(n: Int)(implicit p: Parameters) extends CoreModule()(p) { 15 | val io = IO(new Bundle { 16 | val requestors = Flipped(Vec(n, new TLBPTWIO)) 17 | }) 18 | io.requestors := DontCare 19 | val req_arb = Module(new RRArbiter(Valid(new PTWReq), n)) 20 | req_arb.io.in <> io.requestors.map(_.req) 21 | req_arb.io.out.ready := true.B 22 | 23 | def vpn_to_ppn(vpn: UInt): UInt = vpn(ppnBits - 1, 0) 24 | 25 | class QueueChannel extends ParameterizedBundle()(p) { 26 | val ppn = UInt(ppnBits.W) 27 | val chosen = UInt(log2Up(n).W) 28 | } 29 | 30 | val s1_ppn = vpn_to_ppn(req_arb.io.out.bits.bits.addr) 31 | val s2_ppn = RegEnable(s1_ppn, req_arb.io.out.valid) 32 | val s2_chosen = RegEnable(req_arb.io.chosen, req_arb.io.out.valid) 33 | val s2_valid = RegNext(req_arb.io.out.valid && req_arb.io.out.bits.valid) 34 | 35 | val s2_resp = WireDefault(0.U.asTypeOf(new PTWResp)) 36 | s2_resp.pte.ppn := s2_ppn 37 | s2_resp.pte.reserved_for_software := 0.U 38 | s2_resp.level := (pgLevels-1).U 39 | s2_resp.pte.d := true.B 40 | s2_resp.pte.a := true.B 41 | s2_resp.pte.g := false.B 42 | s2_resp.pte.u := true.B 43 | s2_resp.pte.r := true.B 44 | s2_resp.pte.w := true.B 45 | s2_resp.pte.x := false.B 46 | s2_resp.pte.v := true.B 47 | 48 | io.requestors.zipWithIndex.foreach { case (requestor, i) => 49 | requestor.resp.valid := s2_valid && s2_chosen === i.U 50 | requestor.resp.bits := s2_resp 51 | requestor.status := 0.U.asTypeOf(requestor.status) 52 | requestor.ptbr.mode := requestor.ptbr.pgLevelsToMode(pgLevels).U 53 | requestor.ptbr.asid := 0.U 54 | requestor.ptbr.ppn := 0.U 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/main/scala/groundtest/GroundTestSubsystem.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | 3 | package freechips.rocketchip.groundtest 4 | 5 | import chisel3._ 6 | 7 | import org.chipsalliance.cde.config._ 8 | import org.chipsalliance.diplomacy.lazymodule._ 9 | 10 | import freechips.rocketchip.diplomacy.AddressSet 11 | 12 | import freechips.rocketchip.interrupts._ 13 | import freechips.rocketchip.tile.{NMI} 14 | import freechips.rocketchip.devices.tilelink.{CLINTConsts} 15 | import freechips.rocketchip.subsystem._ 16 | import freechips.rocketchip.tilelink.{TLRAM, TLFragmenter} 17 | import freechips.rocketchip.interrupts.{NullIntSyncSource} 18 | 19 | class GroundTestSubsystem(implicit p: Parameters) 20 | extends BaseSubsystem 21 | with InstantiatesHierarchicalElements 22 | with HasHierarchicalElementsRootContext 23 | with HasHierarchicalElements 24 | with HasTileNotificationSinks 25 | with HasTileInputConstants 26 | with CanHaveMasterAXI4MemPort 27 | { 28 | val testram = LazyModule(new TLRAM(AddressSet(0x52000000, 0xfff), beatBytes=tlBusWrapperLocationMap.get(PBUS).getOrElse(tlBusWrapperLocationMap(p(TLManagerViewpointLocated(location)))).beatBytes)) 29 | tlBusWrapperLocationMap.lift(PBUS).getOrElse(tlBusWrapperLocationMap(p(TLManagerViewpointLocated(location)))).coupleTo("TestRAM") { testram.node := TLFragmenter(tlBusWrapperLocationMap.lift(PBUS).getOrElse(tlBusWrapperLocationMap(p(TLManagerViewpointLocated(location))))) := _ } 30 | 31 | // No cores to monitor 32 | def coreMonitorBundles = Nil 33 | 34 | // No PLIC in ground test; so just sink the interrupts to nowhere 35 | IntSinkNode(IntSinkPortSimple()) :=* ibus.toPLIC 36 | 37 | val tileStatusNodes = totalTiles.values.collect { case t: GroundTestTile => t.statusNode.makeSink() } 38 | val clintOpt = None 39 | val clintDomainOpt = None 40 | val debugOpt = None 41 | val plicOpt = None 42 | val plicDomainOpt = None 43 | 44 | override lazy val module = new GroundTestSubsystemModuleImp(this) 45 | } 46 | 47 | class GroundTestSubsystemModuleImp[+L <: GroundTestSubsystem](_outer: L) extends BaseSubsystemModuleImp(_outer) { 48 | val success = IO(Output(Bool())) 49 | val status = dontTouch(DebugCombiner(_outer.tileStatusNodes.map(_.bundle).toSeq)) 50 | success := _outer.tileCeaseSinkNode.in.head._1.asUInt.andR 51 | } 52 | -------------------------------------------------------------------------------- /src/main/scala/groundtest/Package.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | 3 | package freechips.rocketchip 4 | 5 | package object groundtest { 6 | val testRamAddr = 0x10000 7 | val timeoutCodeBits = 4 8 | val errorCodeBits = 4 9 | } 10 | -------------------------------------------------------------------------------- /src/main/scala/groundtest/Status.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | 3 | package freechips.rocketchip.groundtest 4 | 5 | import chisel3._ 6 | import chisel3.util._ 7 | import freechips.rocketchip.util.ValidMux 8 | 9 | class GroundTestStatus extends Bundle { 10 | val timeout = Valid(UInt(4.W)) 11 | val error = Valid(UInt(4.W)) 12 | } 13 | 14 | object DebugCombiner { 15 | def apply(debugs: Seq[GroundTestStatus]): GroundTestStatus = { 16 | val out = Wire(new GroundTestStatus) 17 | out.timeout := ValidMux(debugs.map(_.timeout)) 18 | out.error := ValidMux(debugs.map(_.error)) 19 | out 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/main/scala/groundtest/TestHarness.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | 3 | package freechips.rocketchip.groundtest 4 | 5 | import chisel3._ 6 | 7 | import org.chipsalliance.cde.config._ 8 | import org.chipsalliance.diplomacy.lazymodule._ 9 | 10 | import freechips.rocketchip.system.SimAXIMem 11 | 12 | class TestHarness(implicit p: Parameters) extends Module { 13 | val io = IO(new Bundle { val success = Output(Bool()) }) 14 | val ldut = LazyModule(new GroundTestSubsystem) 15 | val dut = Module(ldut.module) 16 | io.success := dut.success 17 | SimAXIMem.connectMem(ldut) 18 | } 19 | -------------------------------------------------------------------------------- /src/main/scala/groundtest/Tile.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | // See LICENSE.Berkeley for license details. 3 | 4 | package freechips.rocketchip.groundtest 5 | 6 | import chisel3._ 7 | 8 | import org.chipsalliance.cde.config._ 9 | import org.chipsalliance.diplomacy.bundlebridge._ 10 | import org.chipsalliance.diplomacy.lazymodule._ 11 | 12 | import freechips.rocketchip.resources.{SimpleDevice} 13 | import freechips.rocketchip.prci.{ClockCrossingType} 14 | import freechips.rocketchip.interrupts._ 15 | import freechips.rocketchip.rocket.{BuildHellaCache, DCache, DCacheModule, ICacheParams, NonBlockingDCache, NonBlockingDCacheModule, RocketCoreParams} 16 | import freechips.rocketchip.tile._ 17 | import freechips.rocketchip.tilelink._ 18 | 19 | trait GroundTestTileParams extends TileParams { 20 | val memStart: BigInt 21 | val maxRequests: Int 22 | val numGens: Int 23 | 24 | val icache = Some(ICacheParams()) 25 | val btb = None 26 | val rocc = Nil 27 | val core = RocketCoreParams(nPMPs = 0) //TODO remove this 28 | val cached = if(dcache.isDefined) 1 else 0 29 | val dataScratchpadBytes = 0 30 | } 31 | 32 | abstract class GroundTestTile( 33 | params: GroundTestTileParams, 34 | crossing: ClockCrossingType, 35 | lookup: LookupByHartIdImpl, 36 | q: Parameters 37 | ) extends BaseTile(params, crossing, lookup, q) 38 | with SinksExternalInterrupts 39 | with SourcesExternalNotifications 40 | { 41 | val cpuDevice: SimpleDevice = new SimpleDevice("groundtest", Nil) 42 | val intOutwardNode = None 43 | val slaveNode: TLInwardNode = TLIdentityNode() 44 | val statusNode = BundleBridgeSource(() => new GroundTestStatus) 45 | 46 | val dcacheOpt = params.dcache.map { dc => LazyModule(p(BuildHellaCache)(this)(p)) } 47 | 48 | dcacheOpt.foreach { m => 49 | m.hartIdSinkNodeOpt.foreach { _ := hartIdNexusNode } 50 | InModuleBody { 51 | m.module.io.tlb_port := DontCare 52 | } 53 | } 54 | 55 | override lazy val module = new GroundTestTileModuleImp(this) 56 | } 57 | 58 | class GroundTestTileModuleImp(outer: GroundTestTile) extends BaseTileModuleImp(outer) { 59 | val status = outer.statusNode.bundle 60 | val halt_and_catch_fire = None 61 | 62 | outer.dcacheOpt foreach { dcache => 63 | val ptw = Module(new DummyPTW(1)) 64 | ptw.io.requestors := DontCare 65 | ptw.io.requestors.head <> dcache.module.io.ptw 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/main/scala/interrupts/BlockDuringReset.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | 3 | package freechips.rocketchip.interrupts 4 | 5 | import org.chipsalliance.cde.config._ 6 | import org.chipsalliance.diplomacy.lazymodule._ 7 | 8 | import freechips.rocketchip.util.BlockDuringReset 9 | 10 | /** BlockDuringReset ensures that no interrupt is raised while reset is raised. */ 11 | class IntBlockDuringReset(stretchResetCycles: Int = 0)(implicit p: Parameters) extends LazyModule 12 | { 13 | val intnode = IntAdapterNode() 14 | override def shouldBeInlined = true 15 | lazy val module = new Impl 16 | class Impl extends LazyModuleImp(this) { 17 | intnode.in.zip(intnode.out).foreach { case ((in, _), (out, _)) => 18 | in.zip(out).foreach { case (i, o) => o := BlockDuringReset(i, stretchResetCycles) } 19 | } 20 | } 21 | } 22 | 23 | object IntBlockDuringReset { 24 | def apply(stretchResetCycles: Int = 0)(implicit p: Parameters): IntNode = { 25 | val block_during_reset = LazyModule(new IntBlockDuringReset(stretchResetCycles)) 26 | block_during_reset.intnode 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/main/scala/interrupts/Bundles.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | 3 | package freechips.rocketchip.interrupts 4 | 5 | import chisel3._ 6 | import freechips.rocketchip.util._ 7 | 8 | class SyncInterrupts(val params: IntEdge) extends Bundle 9 | { 10 | val sync = Vec(params.source.num, Bool()) 11 | } 12 | -------------------------------------------------------------------------------- /src/main/scala/interrupts/NullIntSource.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | 3 | package freechips.rocketchip.interrupts 4 | 5 | import chisel3._ 6 | 7 | import org.chipsalliance.cde.config._ 8 | import org.chipsalliance.diplomacy.lazymodule._ 9 | 10 | /** Useful for stubbing out parts of an interrupt interface where certain devices might be missing */ 11 | class NullIntSource(num: Int = 1, ports: Int = 1, sources: Int = 1)(implicit p: Parameters) extends LazyModule 12 | { 13 | val intnode = IntSourceNode(IntSourcePortSimple(num, ports, sources)) 14 | 15 | lazy val module = new Impl 16 | class Impl extends LazyRawModuleImp(this) { 17 | intnode.out.foreach { case (o, _) => o.foreach { _ := false.B } } 18 | } 19 | } 20 | 21 | object NullIntSource { 22 | def apply(num: Int = 1, ports: Int = 1, sources: Int = 1)(implicit p: Parameters): IntOutwardNode = { 23 | val null_int_source = LazyModule(new NullIntSource(num, ports, sources)) 24 | null_int_source.intnode 25 | } 26 | } 27 | 28 | object NullIntSyncSource { 29 | def apply(num: Int = 1, ports: Int = 1, sources: Int = 1)(implicit p: Parameters): IntSyncOutwardNode = { 30 | IntSyncCrossingSource(alreadyRegistered = true) := NullIntSource(num, ports, sources) 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/main/scala/interrupts/Parameters.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | 3 | package freechips.rocketchip.interrupts 4 | 5 | import chisel3.experimental.SourceInfo 6 | 7 | import org.chipsalliance.cde.config._ 8 | import org.chipsalliance.diplomacy.nodes._ 9 | 10 | import freechips.rocketchip.resources.Resource 11 | 12 | // A potentially empty half-open range; [start, end) 13 | case class IntRange(start: Int, end: Int) 14 | { 15 | require (start >= 0) 16 | require (start <= end) 17 | def size = end - start 18 | def overlaps(x: IntRange) = start < x.end && x.start < end 19 | def offset(x: Int) = IntRange(x+start, x+end) 20 | } 21 | 22 | object IntRange 23 | { 24 | implicit def apply(end: Int): IntRange = apply(0, end) 25 | } 26 | 27 | case class IntSourceParameters( 28 | range: IntRange, 29 | resources: Seq[Resource] = Seq(), 30 | nodePath: Seq[BaseNode] = Seq()) 31 | { 32 | val name = nodePath.lastOption.map(_.lazyModule.name).getOrElse("disconnected") 33 | } 34 | 35 | case class IntSinkParameters( 36 | nodePath: Seq[BaseNode] = Seq()) 37 | { 38 | val name = nodePath.lastOption.map(_.lazyModule.name).getOrElse("disconnected") 39 | } 40 | 41 | case class IntSourcePortParameters(sources: Seq[IntSourceParameters]) 42 | { 43 | val num = sources.map(_.range.size).sum 44 | // The interrupts mapping must not overlap 45 | sources.map(_.range).combinations(2).foreach { case Seq(a, b) => require (!a.overlaps(b)) } 46 | // The interrupts must perfectly cover the range 47 | require (sources.isEmpty || sources.map(_.range.end).max == num) 48 | } 49 | object IntSourcePortSimple 50 | { 51 | def apply(num: Int = 1, ports: Int = 1, sources: Int = 1, resources: Seq[Resource] = Nil) = 52 | if (num == 0) Nil else 53 | Seq.fill(ports)(IntSourcePortParameters( 54 | Seq.tabulate(sources)(idx => IntSourceParameters(range = IntRange(idx*num, idx*num+num), resources = resources)))) 55 | } 56 | 57 | case class IntSinkPortParameters(sinks: Seq[IntSinkParameters]) 58 | object IntSinkPortSimple 59 | { 60 | def apply(ports: Int = 1, sinks: Int = 1) = 61 | Seq.fill(ports)(IntSinkPortParameters(Seq.fill(sinks)(IntSinkParameters()))) 62 | } 63 | 64 | case class IntEdge(source: IntSourcePortParameters, sink: IntSinkPortParameters, params: Parameters, sourceInfo: SourceInfo) 65 | -------------------------------------------------------------------------------- /src/main/scala/interrupts/RegisterRouter.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | 3 | package freechips.rocketchip.interrupts 4 | 5 | import chisel3._ 6 | 7 | import org.chipsalliance.diplomacy.lazymodule._ 8 | 9 | import freechips.rocketchip.resources.Resource 10 | 11 | import freechips.rocketchip.regmapper._ 12 | 13 | /** Mix this trait into a RegisterRouter to be able to attach its interrupt sources to an interrupt bus */ 14 | trait HasInterruptSources { this: RegisterRouter => 15 | def nInterrupts: Int 16 | protected val intnode = IntSourceNode(IntSourcePortSimple(num = nInterrupts, resources = Seq(Resource(device, "int")))) 17 | 18 | // Externally, this helper should be used to connect the interrupts to a bus 19 | val intXing: IntOutwardClockCrossingHelper = this.crossOut(intnode) 20 | 21 | // Internally, this wire should be used to drive interrupt values 22 | val interrupts: ModuleValue[Vec[Bool]] = InModuleBody { if (intnode.out.isEmpty) Vec(0, Bool()) else intnode.out(0)._1 } 23 | } 24 | -------------------------------------------------------------------------------- /src/main/scala/interrupts/Xbar.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | 3 | package freechips.rocketchip.interrupts 4 | 5 | import org.chipsalliance.cde.config._ 6 | import org.chipsalliance.diplomacy.lazymodule._ 7 | 8 | class IntXbar()(implicit p: Parameters) extends LazyModule 9 | { 10 | val intnode = new IntNexusNode( 11 | sinkFn = { _ => IntSinkPortParameters(Seq(IntSinkParameters())) }, 12 | sourceFn = { seq => 13 | IntSourcePortParameters((seq zip seq.map(_.num).scanLeft(0)(_+_).init).map { 14 | case (s, o) => s.sources.map(z => z.copy(range = z.range.offset(o))) 15 | }.flatten) 16 | }) 17 | { 18 | override def circuitIdentity = outputs == 1 && inputs == 1 19 | } 20 | 21 | lazy val module = new Impl 22 | class Impl extends LazyRawModuleImp(this) { 23 | override def desiredName = s"IntXbar_i${intnode.in.size}_o${intnode.out.size}" 24 | val cat = intnode.in.map { case (i, e) => i.take(e.source.num) }.flatten 25 | intnode.out.foreach { case (o, _) => o := cat } 26 | } 27 | } 28 | 29 | class IntSyncXbar()(implicit p: Parameters) extends LazyModule 30 | { 31 | val intnode = new IntSyncNexusNode( 32 | sinkFn = { _ => IntSinkPortParameters(Seq(IntSinkParameters())) }, 33 | sourceFn = { seq => 34 | IntSourcePortParameters((seq zip seq.map(_.num).scanLeft(0)(_+_).init).map { 35 | case (s, o) => s.sources.map(z => z.copy(range = z.range.offset(o))) 36 | }.flatten) 37 | }) 38 | { 39 | override def circuitIdentity = outputs == 1 && inputs == 1 40 | } 41 | 42 | lazy val module = new Impl 43 | class Impl extends LazyModuleImp(this) { 44 | override def desiredName = s"IntSyncXbar_i${intnode.in.size}_o${intnode.out.size}" 45 | val cat = intnode.in.map { case (i, e) => i.sync.take(e.source.num) }.flatten 46 | intnode.out.foreach { case (o, _) => o.sync := cat } 47 | } 48 | } 49 | 50 | object IntXbar { 51 | def apply()(implicit p: Parameters): IntNode = { 52 | val xbar = LazyModule(new IntXbar) 53 | xbar.intnode 54 | } 55 | } 56 | 57 | object IntSyncXbar { 58 | def apply()(implicit p: Parameters): IntSyncNode = { 59 | val xbar = LazyModule(new IntSyncXbar) 60 | xbar.intnode 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/main/scala/interrupts/package.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | 3 | package freechips.rocketchip 4 | 5 | import chisel3._ 6 | 7 | import org.chipsalliance.diplomacy._ 8 | import org.chipsalliance.diplomacy.nodes._ 9 | 10 | import freechips.rocketchip.prci.{HasClockDomainCrossing, HasResetDomainCrossing} 11 | 12 | package object interrupts 13 | { 14 | type IntInwardNode = InwardNodeHandle[IntSourcePortParameters, IntSinkPortParameters, IntEdge, Vec[Bool]] 15 | type IntOutwardNode = OutwardNodeHandle[IntSourcePortParameters, IntSinkPortParameters, IntEdge, Vec[Bool]] 16 | type IntNode = SimpleNodeHandle[IntSourcePortParameters, IntSinkPortParameters, IntEdge, Vec[Bool]] 17 | 18 | type IntSyncInwardNode = InwardNodeHandle[IntSourcePortParameters, IntSinkPortParameters, IntEdge, SyncInterrupts] 19 | type IntSyncOutwardNode = OutwardNodeHandle[IntSourcePortParameters, IntSinkPortParameters, IntEdge, SyncInterrupts] 20 | type IntSyncNode = SimpleNodeHandle[IntSourcePortParameters, IntSinkPortParameters, IntEdge, SyncInterrupts] 21 | 22 | implicit class IntClockDomainCrossing(private val x: HasClockDomainCrossing) extends AnyVal { 23 | def crossIn (n: IntInwardNode) (implicit valName: ValName) = IntInwardClockCrossingHelper(valName.name, x, n) 24 | def crossOut(n: IntOutwardNode)(implicit valName: ValName) = IntOutwardClockCrossingHelper(valName.name, x, n) 25 | def cross(n: IntInwardNode) (implicit valName: ValName) = crossIn(n) 26 | def cross(n: IntOutwardNode)(implicit valName: ValName) = crossOut(n) 27 | } 28 | 29 | implicit class IntResetDomainCrossing(private val x: HasResetDomainCrossing) extends AnyVal { 30 | def crossIn (n: IntInwardNode) (implicit valName: ValName) = IntInwardResetCrossingHelper(valName.name, x, n) 31 | def crossOut(n: IntOutwardNode)(implicit valName: ValName) = IntOutwardResetCrossingHelper(valName.name, x, n) 32 | def cross(n: IntInwardNode) (implicit valName: ValName) = crossIn(n) 33 | def cross(n: IntOutwardNode)(implicit valName: ValName) = crossOut(n) 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/main/scala/jtag/JtagUtils.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.jtag for license details. 2 | 3 | package freechips.rocketchip.jtag 4 | 5 | import chisel3._ 6 | 7 | class JTAGIdcodeBundle extends Bundle { 8 | val version = UInt(4.W) 9 | val partNumber = UInt(16.W) 10 | val mfrId = UInt(11.W) 11 | val always1 = UInt(1.W) 12 | } 13 | 14 | object JtagIdcode { 15 | /** Generates a JTAG IDCODE as a 32-bit integer, using the format in 12.1.1d. 16 | */ 17 | def apply(version: Int, partNumber: Int, mfrId: Int): BigInt = { 18 | require(version < (1 << 4), "version field must be 4 bits at most") 19 | require(partNumber < (1 << 16), "part number must be 16 bits at most") 20 | require(mfrId < (1 << 11), "manufacturer identity must be 11 bits at most") 21 | BigInt(version) << 28 | BigInt(partNumber) << 12 | BigInt(mfrId) << 1 | 1 22 | } 23 | 24 | /** A dummy manufacturer ID, not to be used per 12.2.1b since bus masters may shift this out to 25 | * determine the end of a bus. 26 | */ 27 | def dummyMfrId: Int = 0x7f 28 | } 29 | -------------------------------------------------------------------------------- /src/main/scala/jtag/Utils.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.jtag for license details. 2 | 3 | package freechips.rocketchip.jtag 4 | 5 | import chisel3._ 6 | import chisel3.util._ 7 | 8 | /** Bundle representing a tristate pin. 9 | */ 10 | class Tristate extends Bundle { 11 | val data = Bool() 12 | val driven = Bool() // active high, pin is hi-Z when driven is low 13 | } 14 | 15 | /** A module that counts transitions on the input clock line, used as a basic sanity check and 16 | * debug indicator clock-crossing designs. 17 | */ 18 | class ClockedCounter(counts: BigInt, init: Option[BigInt]) extends Module { 19 | require(counts > 0, "really?") 20 | 21 | val width = log2Ceil(counts) 22 | class CountIO extends Bundle { 23 | val count = Output(UInt(width.W)) 24 | } 25 | val io = IO(new CountIO) 26 | 27 | val count = init match { 28 | case Some(init) => RegInit(init.U(width.W)) 29 | case None => Reg(UInt(width.W)) 30 | } 31 | 32 | when (count === (counts - 1).asUInt) { 33 | count := 0.U 34 | } .otherwise { 35 | count := count + 1.U 36 | } 37 | io.count := count 38 | } 39 | 40 | /** Count transitions on the input bit by specifying it as a clock to a counter. 41 | */ 42 | object ClockedCounter { 43 | def apply (data: Bool, counts: BigInt, init: BigInt): UInt = { 44 | withClock(data.asClock) { 45 | val counter = Module(new ClockedCounter(counts, Some(init))) 46 | counter.io.count 47 | } 48 | } 49 | 50 | def apply (data: Bool, counts: BigInt): UInt = { 51 | withClock(data.asClock) { 52 | val counter = Module(new ClockedCounter(counts, None)) 53 | counter.io.count 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/main/scala/jtag/package.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.jtag for license details 2 | 3 | package freechips.rocketchip 4 | 5 | import scala.language.implicitConversions 6 | 7 | package object jtag { 8 | /** An implicit conversion to allow the instruction map for the TAP generator to be specified as 9 | * an Int instead of BigInt. Scala doesn't seem to want to automatically apply the built-in Int 10 | * to BigInt conversion when used as a Map key. 11 | * 12 | * This is limited to value types of Chain to limit application scope. 13 | */ 14 | implicit def instructionIntKeyToBigInt[V <: Chain](x: (Int, V)) = (BigInt(x._1), x._2) 15 | } 16 | -------------------------------------------------------------------------------- /src/main/scala/prci/BundleBridgeBlockDuringReset.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | 3 | package freechips.rocketchip.prci 4 | 5 | import chisel3._ 6 | 7 | import org.chipsalliance.cde.config._ 8 | import org.chipsalliance.diplomacy.bundlebridge._ 9 | import org.chipsalliance.diplomacy.lazymodule._ 10 | 11 | import org.chipsalliance.diplomacy.bundlebridge.BundleBridgeNexus.fillN 12 | 13 | import freechips.rocketchip.util.{BlockDuringReset, Blockable} 14 | 15 | object BundleBridgeBlockDuringReset { 16 | def apply[T <: Data : Blockable]( 17 | resetCrossingType: ResetCrossingType, 18 | name: Option[String] = None, 19 | registered: Boolean = false, 20 | default: Option[() => T] = None, 21 | inputRequiresOutput: Boolean = false, 22 | shouldBeInlined: Boolean = true 23 | )(implicit p: Parameters): BundleBridgeNexusNode[T] = { 24 | val nexus = LazyModule(new BundleBridgeNexus[T]( 25 | inputFn = (s: Seq[T]) => { 26 | val data = BundleBridgeNexus.requireOne[T](registered)(s) 27 | resetCrossingType match { 28 | case _: NoResetCrossing => data 29 | case s: StretchedResetCrossing => BlockDuringReset(data, s.cycles) 30 | } 31 | }, 32 | outputFn = fillN[T](registered) _, 33 | default = default, 34 | inputRequiresOutput = inputRequiresOutput, 35 | shouldBeInlined = shouldBeInlined 36 | )) 37 | name.foreach(nexus.suggestName(_)) 38 | nexus.node 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/main/scala/prci/ClockBundles.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | package freechips.rocketchip.prci 3 | 4 | import chisel3._ 5 | import freechips.rocketchip.util.RecordMap 6 | 7 | 8 | class ClockBundle(val params: ClockBundleParameters = ClockBundleParameters()) extends Bundle 9 | { 10 | val clock = Output(Clock()) 11 | val reset = Output(Reset()) 12 | } 13 | 14 | class ClockGroupBundle(val params: ClockGroupBundleParameters) extends Bundle 15 | { 16 | val member: RecordMap[ClockBundle] = RecordMap(params.members.map { case (k, v) => 17 | k -> new ClockBundle(v) 18 | }) 19 | } 20 | -------------------------------------------------------------------------------- /src/main/scala/prci/ClockCrossingType.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | 3 | package freechips.rocketchip.prci 4 | import org.chipsalliance.diplomacy.lazymodule.{LazyScope, LazyModule} 5 | import freechips.rocketchip.diplomacy.{BufferParams} 6 | import freechips.rocketchip.util.{RationalDirection, FastToSlow, AsyncQueueParams, CreditedDelay} 7 | 8 | trait CrossingType 9 | 10 | trait HasDomainCrossing extends LazyScope { this: LazyModule => 11 | type DomainCrossingType <: CrossingType 12 | } 13 | 14 | trait HasClockDomainCrossing extends HasDomainCrossing { this: LazyModule => 15 | type DomainCrossingType = ClockCrossingType 16 | } 17 | 18 | /** Enumerates the types of clock crossings generally supported by Diplomatic bus protocols */ 19 | sealed trait ClockCrossingType extends CrossingType 20 | { 21 | def sameClock = this match { 22 | case _: SynchronousCrossing | _: CreditedCrossing => true 23 | case _ => false 24 | } 25 | } 26 | 27 | case object NoCrossing // converts to SynchronousCrossing(BufferParams.none) via implicit def in package 28 | case class SynchronousCrossing(params: BufferParams = BufferParams.default) extends ClockCrossingType 29 | case class RationalCrossing(direction: RationalDirection = FastToSlow) extends ClockCrossingType 30 | case class AsynchronousCrossing(depth: Int = 8, sourceSync: Int = 3, sinkSync: Int = 3, safe: Boolean = true, narrow: Boolean = false) extends ClockCrossingType 31 | { 32 | def asSinkParams = AsyncQueueParams(depth, sinkSync, safe, narrow) 33 | } 34 | case class CreditedCrossing(sourceDelay: CreditedDelay, sinkDelay: CreditedDelay) extends ClockCrossingType 35 | 36 | object CreditedCrossing { 37 | def apply(delay: CreditedDelay): CreditedCrossing = CreditedCrossing(delay, delay.flip) 38 | def apply(): CreditedCrossing = CreditedCrossing(CreditedDelay(1, 1)) 39 | } 40 | -------------------------------------------------------------------------------- /src/main/scala/prci/ClockDivider.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | package freechips.rocketchip.prci 3 | 4 | import chisel3._ 5 | import chisel3.util._ 6 | 7 | import org.chipsalliance.cde.config._ 8 | import org.chipsalliance.diplomacy.lazymodule._ 9 | 10 | import freechips.rocketchip.util.{ClockDivider3, Pow2ClockDivider} 11 | 12 | /* An example clock adapter that divides all clocks passed through this node by an integer factor 13 | */ 14 | class ClockDivider(div: Int)(implicit p: Parameters) extends LazyModule { 15 | val node = ClockAdapterNode( 16 | sourceFn = { case src => src.copy(give = src.give.map(x => x.copy(freqMHz = x.freqMHz / div))) }, 17 | sinkFn = { case snk => snk.copy(take = snk.take.map(x => x.copy(freqMHz = x.freqMHz * div))) }) 18 | 19 | lazy val module = new Impl 20 | class Impl extends LazyModuleImp(this) { 21 | (node.in zip node.out).foreach { case ((in, _), (out, _)) => 22 | val div_clock: Clock = div match { 23 | case x if isPow2(x) => Pow2ClockDivider(in.clock, x) 24 | case 3 => { 25 | val div3 = Module(new ClockDivider3) 26 | div3.io.clk_in := in.clock 27 | div3.io.clk_out 28 | } 29 | case x => throw new IllegalArgumentException(s"rocketchip.util only supports clock division by powers of 2, or exactly 3, but got $x") 30 | } 31 | out.clock := div_clock 32 | out.reset := withClock(out.clock) { RegNext(in.reset) } 33 | } 34 | } 35 | } 36 | 37 | // TODO make a version of this that output a clock group with two members, 38 | // one of which is the original clock and the other of which is some number of divided clocks 39 | -------------------------------------------------------------------------------- /src/main/scala/prci/ClockDomain.scala: -------------------------------------------------------------------------------- 1 | package freechips.rocketchip.prci 2 | 3 | import chisel3._ 4 | 5 | import org.chipsalliance.cde.config._ 6 | 7 | import org.chipsalliance.diplomacy.lazymodule._ 8 | 9 | abstract class Domain(implicit p: Parameters) extends LazyModule with HasDomainCrossing 10 | { 11 | def clockBundle: ClockBundle 12 | 13 | lazy val module = new Impl 14 | class Impl extends LazyRawModuleImp(this) { 15 | childClock := clockBundle.clock 16 | childReset := clockBundle.reset 17 | override def provideImplicitClockToLazyChildren = true 18 | 19 | // these are just for backwards compatibility with external devices 20 | // that were manually wiring themselves to the domain's clock/reset input: 21 | val clock = IO(Output(chiselTypeOf(clockBundle.clock))) 22 | val reset = IO(Output(chiselTypeOf(clockBundle.reset))) 23 | clock := clockBundle.clock 24 | reset := clockBundle.reset 25 | } 26 | } 27 | 28 | abstract class ClockDomain(implicit p: Parameters) extends Domain with HasClockDomainCrossing 29 | 30 | class ClockSinkDomain(val clockSinkParams: ClockSinkParameters)(implicit p: Parameters) extends ClockDomain 31 | { 32 | def this(take: Option[ClockParameters] = None, name: Option[String] = None)(implicit p: Parameters) = this(ClockSinkParameters(take = take, name = name)) 33 | val clockNode = ClockSinkNode(Seq(clockSinkParams)) 34 | def clockBundle = clockNode.in.head._1 35 | override lazy val desiredName = (clockSinkParams.name.toSeq :+ "ClockSinkDomain").mkString 36 | } 37 | 38 | class ClockSourceDomain(val clockSourceParams: ClockSourceParameters)(implicit p: Parameters) extends ClockDomain 39 | { 40 | def this(give: Option[ClockParameters] = None, name: Option[String] = None)(implicit p: Parameters) = this(ClockSourceParameters(give = give, name = name)) 41 | val clockNode = ClockSourceNode(Seq(clockSourceParams)) 42 | def clockBundle = clockNode.out.head._1 43 | override lazy val desiredName = (clockSourceParams.name.toSeq :+ "ClockSourceDomain").mkString 44 | } 45 | 46 | abstract class ResetDomain(implicit p: Parameters) extends Domain with HasResetDomainCrossing 47 | -------------------------------------------------------------------------------- /src/main/scala/prci/IOHelper.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | // See LICENSE.Berkeley for license details. 3 | package freechips.rocketchip.prci 4 | 5 | import chisel3._ 6 | 7 | import org.chipsalliance.diplomacy.lazymodule._ 8 | 9 | object IOHelper { 10 | 11 | def forNonSynchronous[T <: Data](gen: => T, xs: Seq[ClockCrossingType], prefix: String): Seq[Option[ModuleValue[T]]] = { 12 | xs.zipWithIndex.map { case (x, i) => forNonSynchronous(gen, x, prefix + s"_$i") } 13 | } 14 | 15 | def forNonSynchronous[T <: Data](gen: => T, x: ClockCrossingType, name: String): Option[ModuleValue[T]] = { 16 | x match { 17 | case SynchronousCrossing(_) => None 18 | case _ => Some(InModuleBody(IO(Input(gen)).suggestName(name))) 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/main/scala/prci/ResetCrossingType.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | package freechips.rocketchip.prci 3 | 4 | import org.chipsalliance.cde.config._ 5 | import org.chipsalliance.diplomacy.lazymodule._ 6 | 7 | trait HasResetDomainCrossing extends HasDomainCrossing { this: LazyModule => 8 | type DomainCrossingType = ResetCrossingType 9 | } 10 | 11 | sealed trait ResetCrossingType extends CrossingType { 12 | def injectClockNode(implicit p: Parameters): ClockNode 13 | } 14 | 15 | case class NoResetCrossing() extends ResetCrossingType { 16 | def injectClockNode(implicit p: Parameters): ClockNode = ClockTempNode() 17 | } 18 | 19 | case class StretchedResetCrossing(cycles: Int) extends ResetCrossingType { 20 | def injectClockNode(implicit p: Parameters): ClockNode = { 21 | val rs = LazyModule(new ResetStretcher(cycles)) 22 | rs.node 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/main/scala/prci/ResetStretcher.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | package freechips.rocketchip.prci 3 | 4 | import chisel3._ 5 | import chisel3.util._ 6 | import org.chipsalliance.cde.config._ 7 | import org.chipsalliance.diplomacy._ 8 | import org.chipsalliance.diplomacy.lazymodule._ 9 | 10 | /** This adapter takes an input reset and stretches it. 11 | * 12 | * If the reset was asynchronous, it becomes synchronous. 13 | */ 14 | class ResetStretcher(cycles: Int)(implicit p: Parameters) extends LazyModule { 15 | val node = ClockAdapterNode()(ValName("reset_stretcher")) 16 | require(cycles > 1, s"ResetStretcher only supports cycles > 1 but got ${cycles}") 17 | override lazy val desiredName = s"ResetStretcher$cycles" 18 | lazy val module = new Impl 19 | class Impl extends LazyModuleImp(this) { 20 | (node.in zip node.out).foreach { case ((in, _), (out, _)) => 21 | out.clock := in.clock 22 | out.reset := withClockAndReset(in.clock, in.reset) { 23 | val count = RegInit(0.U(log2Ceil(cycles).W)) 24 | val resetout = RegInit(true.B) 25 | when (resetout) { 26 | count := count + 1.U 27 | resetout := (count < (cycles-1).U) 28 | } 29 | resetout 30 | } 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/main/scala/prci/ResetSynchronizer.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE for license details. 2 | package freechips.rocketchip.prci 3 | 4 | import org.chipsalliance.cde.config._ 5 | import org.chipsalliance.diplomacy._ 6 | import org.chipsalliance.diplomacy.lazymodule._ 7 | 8 | import freechips.rocketchip.util.ResetCatchAndSync 9 | 10 | /** 11 | * Synchronizes the reset of a diplomatic clock-reset pair to its accompanying clock. 12 | */ 13 | class ResetSynchronizer(implicit p: Parameters) extends LazyModule { 14 | val node = ClockAdapterNode() 15 | lazy val module = new Impl 16 | class Impl extends LazyRawModuleImp(this) { 17 | (node.out zip node.in).map { case ((o, _), (i, _)) => 18 | o.clock := i.clock 19 | o.reset := ResetCatchAndSync(i.clock, i.reset.asBool) 20 | } 21 | } 22 | } 23 | 24 | object ResetSynchronizer { 25 | def apply()(implicit p: Parameters, valName: ValName) = LazyModule(new ResetSynchronizer()).node 26 | } 27 | 28 | 29 | /** 30 | * Instantiates a reset synchronizer on all clock-reset pairs in a clock group. 31 | */ 32 | class ClockGroupResetSynchronizer(implicit p: Parameters) extends LazyModule { 33 | val node = ClockGroupAdapterNode() 34 | lazy val module = new Impl 35 | class Impl extends LazyRawModuleImp(this) { 36 | (node.out zip node.in).map { case ((oG, _), (iG, _)) => 37 | (oG.member.data zip iG.member.data).foreach { case (o, i) => 38 | o.clock := i.clock 39 | o.reset := ResetCatchAndSync(i.clock, i.reset.asBool) 40 | } 41 | } 42 | } 43 | } 44 | 45 | object ClockGroupResetSynchronizer { 46 | def apply()(implicit p: Parameters, valName: ValName) = LazyModule(new ClockGroupResetSynchronizer()).node 47 | } 48 | -------------------------------------------------------------------------------- /src/main/scala/prci/ResetWrangler.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE for license details. 2 | package freechips.rocketchip.prci 3 | 4 | import chisel3._ 5 | import chisel3.util._ 6 | import org.chipsalliance.cde.config._ 7 | import org.chipsalliance.diplomacy.lazymodule._ 8 | 9 | import freechips.rocketchip.util.{AsyncResetReg, ResetCatchAndSync} 10 | 11 | class ResetWrangler(debounceNs: Double = 100000)(implicit p: Parameters) extends LazyModule 12 | { 13 | val node = ClockAdapterNode() 14 | 15 | lazy val module = new Impl 16 | class Impl extends LazyRawModuleImp(this) { 17 | val (in, _) = node.in.unzip 18 | val (out, _) = node.out.unzip 19 | 20 | val status = IO(Output(UInt(in.size.W))) 21 | status := Cat(in.map(_.reset.asBool).reverse) 22 | val causes = in.map(_.reset).foldLeft(false.B)(_.asBool || _.asBool) 23 | 24 | require(node.in.forall(_._2.clock.isDefined), "Cannot wrangle reset for an unspecified clock frequency") 25 | val (slowIn, slowEdge) = node.in.minBy(_._2.clock.get.freqMHz) 26 | val slowPeriodNs = 1000 / slowEdge.clock.get.freqMHz 27 | val slowTicks = math.ceil(debounceNs/slowPeriodNs).toInt max 7 28 | val slowBits = log2Ceil(slowTicks+1) 29 | 30 | // debounce 31 | val increment = Wire(Bool()) 32 | val incremented = Wire(UInt(slowBits.W)) 33 | val debounced = withClockAndReset(slowIn.clock, causes) { 34 | AsyncResetReg(incremented, 0, increment, Some("debounce")) 35 | } 36 | increment := debounced =/= slowTicks.U 37 | incremented := debounced + 1.U 38 | val deglitched = AsyncResetReg(increment, slowIn.clock, causes, true, Some("deglitch")) 39 | 40 | // catch and sync increment to each domain 41 | (in zip out) foreach { case (i, o) => 42 | o.clock := i.clock 43 | o.reset := ResetCatchAndSync(o.clock, deglitched) 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/main/scala/prci/package.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | 3 | package freechips.rocketchip 4 | 5 | import org.chipsalliance.diplomacy.nodes._ 6 | import freechips.rocketchip.diplomacy.{BufferParams} 7 | 8 | package object prci 9 | { 10 | type ClockInwardNode = InwardNodeHandle[ClockSourceParameters, ClockSinkParameters, ClockEdgeParameters, ClockBundle] 11 | type ClockOutwardNode = OutwardNodeHandle[ClockSourceParameters, ClockSinkParameters, ClockEdgeParameters, ClockBundle] 12 | type ClockNode = NodeHandle[ClockSourceParameters, ClockSinkParameters, ClockEdgeParameters, ClockBundle, ClockSourceParameters, ClockSinkParameters, ClockEdgeParameters, ClockBundle] 13 | 14 | type ClockGroupNode = NodeHandle[ClockGroupSourceParameters, ClockGroupSinkParameters, ClockGroupEdgeParameters, ClockGroupBundle, ClockGroupSourceParameters, ClockGroupSinkParameters, ClockGroupEdgeParameters, ClockGroupBundle] 15 | 16 | def asyncMux[T](xType: ClockCrossingType, async: T, notasync: T): T = xType match { 17 | case _: AsynchronousCrossing => async 18 | case _ => notasync 19 | } 20 | 21 | implicit def noCrossing(value: NoCrossing.type): ClockCrossingType = SynchronousCrossing(BufferParams.none) 22 | } 23 | -------------------------------------------------------------------------------- /src/main/scala/regmapper/Annotation.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | 3 | package freechips.rocketchip.regmapper 4 | 5 | 6 | case class RegFieldDescSer( 7 | byteOffset: String, 8 | bitOffset: Int, 9 | bitWidth: Int, 10 | name: String, 11 | resetValue: BigInt, 12 | accessType: String, 13 | wrType: String, 14 | rdAction: String, 15 | desc: String, 16 | group: String, 17 | groupDesc: String, 18 | volatile: Boolean = false, 19 | hasReset: Boolean = false, 20 | enumerations: Map[BigInt, (String, String)] = Map() 21 | ) 22 | 23 | case class RegistersSer( 24 | displayName: String, 25 | deviceName: String, 26 | baseAddress: BigInt, 27 | regFields: Seq[RegFieldDescSer] 28 | ) 29 | -------------------------------------------------------------------------------- /src/main/scala/regmapper/DescribedReg.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE for license details. 2 | package freechips.rocketchip.regmapper 3 | 4 | import chisel3._ 5 | import freechips.rocketchip.util.{AsyncResetRegVec, SimpleRegIO} 6 | 7 | object DescribedReg { 8 | import freechips.rocketchip.regmapper.RegFieldAccessType._ 9 | import freechips.rocketchip.regmapper.RegFieldWrType._ 10 | import freechips.rocketchip.regmapper.RegFieldRdAction._ 11 | 12 | def apply[T <: Data]( 13 | gen: => T, 14 | name: String, 15 | desc: String, 16 | reset: Option[T], 17 | access: RegFieldAccessType = RW, 18 | wrType: Option[RegFieldWrType] = None, 19 | rdAction: Option[RegFieldRdAction] = None, 20 | volatile: Boolean = false, 21 | enumerations: Map[BigInt, (String, String)] = Map()): (T, RegFieldDesc) = { 22 | val rdesc = RegFieldDesc(name, desc, None, None, 23 | access, wrType, rdAction, volatile, reset.map{_.litValue}, enumerations) 24 | val reg = reset.map{i => RegInit(i)}.getOrElse(Reg(gen)) 25 | reg.suggestName(name + "_reg") 26 | (reg, rdesc) 27 | } 28 | 29 | def async( 30 | width: Int, 31 | name: String, 32 | desc: String, 33 | reset: Int, 34 | access: RegFieldAccessType = RW, 35 | wrType: Option[RegFieldWrType] = None, 36 | rdAction: Option[RegFieldRdAction] = None, 37 | volatile: Boolean = false, 38 | enumerations: Map[BigInt, (String, String)] = Map()): (SimpleRegIO, RegFieldDesc) = { 39 | val rdesc = RegFieldDesc(name, desc, None, None, 40 | access, wrType, rdAction, volatile, Some(reset), enumerations) 41 | val reg = Module(new AsyncResetRegVec(w = width, init = reset)) 42 | reg.suggestName(name + "_reg") 43 | (reg.io, rdesc) 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/main/scala/resources/AddressMapEntry.scala: -------------------------------------------------------------------------------- 1 | package freechips.rocketchip.resources 2 | 3 | import freechips.rocketchip.diplomacy.{AddressRange} 4 | 5 | case class AddressMapEntry(range: AddressRange, permissions: ResourcePermissions, names: Seq[String]) { 6 | val ResourcePermissions(r, w, x, c, a) = permissions 7 | 8 | def toString(aw: Int) = s"\t%${aw}x - %${aw}x %c%c%c%c%c %s".format( 9 | range.base, 10 | range.base+range.size, 11 | if (a) 'A' else ' ', 12 | if (r) 'R' else ' ', 13 | if (w) 'W' else ' ', 14 | if (x) 'X' else ' ', 15 | if (c) 'C' else ' ', 16 | names.mkString(", ")) 17 | 18 | def toJSON = s"""{"base":[${range.base}],"size":[${range.size}],""" + 19 | s""""r":[$r],"w":[$w],"x":[$x],"c":[$c],"a":[$a],""" + 20 | s""""names":[${names.map('"'+_+'"').mkString(",")}]}""" 21 | } 22 | -------------------------------------------------------------------------------- /src/main/scala/resources/FixedClockResource.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | 3 | package freechips.rocketchip.resources 4 | 5 | class FixedClockResource(val name: String, val freqMHz: Double, val prefix: String = "soc/") 6 | { 7 | val device = new DeviceSnippet { 8 | def describe() = 9 | Description(prefix + name, Map( 10 | "#clock-cells" -> Seq(ResourceInt(0)), 11 | "clock-frequency" -> Seq(ResourceInt(freqMHz * 1000000)), 12 | "clock-output-names" -> Seq(ResourceString(name)), 13 | "compatible" -> Seq(ResourceString("fixed-clock")))) 14 | } 15 | 16 | def bind(dev: Device): Unit = { 17 | ResourceBinding { Resource(dev, "clocks").bind(ResourceReference(device.label)) } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/main/scala/resources/JSON.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | 3 | package freechips.rocketchip.resources 4 | 5 | import scala.collection.immutable.SortedMap 6 | import freechips.rocketchip.diplomacy.{AddressRange} 7 | 8 | object JSON 9 | { 10 | def apply(res: ResourceValue): String = { 11 | val root = res match { 12 | case ResourceMap(value, _) => value.toList match { 13 | case Seq(("/", Seq(subtree))) => subtree 14 | case _ => res 15 | } 16 | case _ => res 17 | } 18 | helper(root)(SortedMap(map(root):_*)).mkString 19 | } 20 | 21 | private def map(res: ResourceValue, path: String = ""): Seq[(String, String)] = res match { 22 | case ResourceMap(value, labels) => { 23 | labels.map(_ -> path) ++ 24 | value.flatMap { case (key, seq) => seq.flatMap(map(_, path + "/" + key)) } 25 | } 26 | case _ => Nil 27 | } 28 | 29 | private def helper(res: ResourceValue)(implicit path: Map[String, String]): Seq[String] = res match { 30 | case ResourceAddress(address, ResourcePermissions(r, w, x, c, a)) => 31 | AddressRange.fromSets(address).map { case AddressRange(base, size) => 32 | s"""{"base":${base},"size":${size},"r":${r},"w":${w},"x":${x},"c":${c},"a":${a}}"""} 33 | case ResourceMapping(address, offset, ResourcePermissions(r, w, x, c, a)) => 34 | AddressRange.fromSets(address).map { case AddressRange(base, size) => 35 | s"""{"base":${base},"size":${size},"offset":${offset},"r":${r},"w":${w},"x":${x},"c":${c},"a":${a}}"""} 36 | case ResourceInt(value) => Seq(value.toString) 37 | case ResourceString(value) => Seq("\"" + value + "\"") 38 | case ResourceReference(value) => Seq("\"&" + path(value) + "\"") 39 | case ResourceAlias(value) => Seq("\"&" + path(value) + "\"") 40 | case ResourceMap(value, _) => { 41 | Seq(value.map { 42 | case (key, Seq(v: ResourceMap)) => s""""${key}":${helper(v).mkString}""" 43 | case (key, seq) => s""""${key}":[${seq.flatMap(helper).mkString(",")}]""" 44 | }.mkString("{", ",", "}")) 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/main/scala/resources/SRAM.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | 3 | package freechips.rocketchip.resources 4 | 5 | import chisel3._ 6 | import chisel3.util.log2Ceil 7 | import org.chipsalliance.cde.config.Parameters 8 | import freechips.rocketchip.util.{DescribedSRAM, Code} 9 | import freechips.rocketchip.diplomacy.{AddressSet, LazyModule} 10 | 11 | abstract class DiplomaticSRAM( 12 | val address: AddressSet, 13 | beatBytes: Int, 14 | devName: Option[String], 15 | dtsCompat: Option[Seq[String]] = None, 16 | devOverride: Option[Device with DeviceRegName] = None)(implicit p: Parameters) extends LazyModule 17 | { 18 | val device = devOverride.getOrElse(devName 19 | .map(new SimpleDevice(_, dtsCompat.getOrElse(Seq("sifive,sram0")))) 20 | .getOrElse(new MemoryDevice()) 21 | ) 22 | 23 | val resources = device.reg("mem") 24 | 25 | def bigBits(x: BigInt, tail: List[Boolean] = Nil): List[Boolean] = 26 | if (x == 0) tail.reverse else bigBits(x >> 1, ((x & 1) == 1) :: tail) 27 | 28 | def mask: List[Boolean] = bigBits(address.mask >> log2Ceil(beatBytes)) 29 | 30 | // Use single-ported memory with byte-write enable 31 | def makeSinglePortedByteWriteSeqMem(size: BigInt, lanes: Int = beatBytes, bits: Int = 8) = { 32 | // We require the address range to include an entire beat (for the write mask) 33 | 34 | val mem = DescribedSRAM( 35 | name = devName.getOrElse("mem"), 36 | desc = devName.getOrElse("mem"), 37 | size = size, 38 | data = Vec(lanes, UInt(bits.W)) 39 | ) 40 | devName.foreach(n => mem.suggestName(n.split("-").last)) 41 | 42 | mem 43 | } 44 | } 45 | 46 | /** Represents a single seq mem mapped to a single, contiguous address space 47 | */ 48 | trait HasJustOneSeqMem { 49 | 50 | /** A reference to the chisel memory mapped to this address 51 | * 52 | * Each element of the Vec type is a lane 53 | */ 54 | def mem: SyncReadMem[Vec[UInt]] 55 | 56 | /** The number of bits used for data in a single lane 57 | * 58 | * laneDataBits + laneECCBits should equal the total width of a lane 59 | */ 60 | def laneDataBits: Int 61 | 62 | /** The ecc code used by this memory 63 | */ 64 | def eccCode: Option[Code] 65 | 66 | /** The address set this memory is mapped to 67 | */ 68 | def address: AddressSet 69 | } 70 | -------------------------------------------------------------------------------- /src/main/scala/resources/package.scala: -------------------------------------------------------------------------------- 1 | package freechips.rocketchip 2 | 3 | package object resources { 4 | type PropertyOption = Option[(String, Seq[ResourceValue])] 5 | type PropertyMap = Iterable[(String, Seq[ResourceValue])] 6 | 7 | implicit class BigIntHexContext(private val sc: StringContext) extends AnyVal { 8 | def x(args: Any*): BigInt = { 9 | val orig = sc.s(args: _*) 10 | BigInt(orig.replace("_", ""), 16) 11 | } 12 | } 13 | 14 | implicit class IntToProperty(x: Int) { 15 | def asProperty: Seq[ResourceValue] = Seq(ResourceInt(BigInt(x))) 16 | } 17 | 18 | implicit class BigIntToProperty(x: BigInt) { 19 | def asProperty: Seq[ResourceValue] = Seq(ResourceInt(x)) 20 | } 21 | 22 | implicit class StringToProperty(x: String) { 23 | def asProperty: Seq[ResourceValue] = Seq(ResourceString(x)) 24 | } 25 | 26 | implicit class DeviceToProperty(x: Device) { 27 | def asProperty: Seq[ResourceValue] = Seq(ResourceReference(x.label)) 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/main/scala/rocket/PMA.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | // See LICENSE.Berkeley for license details. 3 | 4 | package freechips.rocketchip.rocket 5 | 6 | import chisel3._ 7 | import chisel3.util._ 8 | import chisel3.experimental.SourceInfo 9 | 10 | import org.chipsalliance.cde.config._ 11 | 12 | import freechips.rocketchip.devices.debug.DebugModuleKey 13 | import freechips.rocketchip.diplomacy.RegionType 14 | import freechips.rocketchip.subsystem.CacheBlockBytes 15 | import freechips.rocketchip.tile.{CoreModule, CoreBundle} 16 | import freechips.rocketchip.tilelink.{TLSlavePortParameters, TLManagerParameters} 17 | 18 | class PMAChecker(manager: TLSlavePortParameters)(implicit p: Parameters) extends CoreModule()(p) { 19 | val io = IO(new Bundle { 20 | val paddr = Input(UInt()) 21 | 22 | val resp = Output(new Bundle { 23 | val cacheable = Bool() 24 | val r = Bool() 25 | val w = Bool() 26 | val pp = Bool() 27 | val al = Bool() 28 | val aa = Bool() 29 | val x = Bool() 30 | val eff = Bool() 31 | }) 32 | }) 33 | 34 | // PMA 35 | // check exist a slave can consume this address. 36 | val legal_address = manager.findSafe(io.paddr).reduce(_||_) 37 | // check utility to help check SoC property. 38 | def fastCheck(member: TLManagerParameters => Boolean) = 39 | legal_address && manager.fastProperty(io.paddr, member, (b:Boolean) => b.B) 40 | 41 | io.resp.cacheable := fastCheck(_.supportsAcquireB) 42 | io.resp.r := fastCheck(_.supportsGet) 43 | io.resp.w := fastCheck(_.supportsPutFull) 44 | io.resp.pp := fastCheck(_.supportsPutPartial) 45 | io.resp.al := fastCheck(_.supportsLogical) 46 | io.resp.aa := fastCheck(_.supportsArithmetic) 47 | io.resp.x := fastCheck(_.executable) 48 | io.resp.eff := fastCheck(Seq(RegionType.PUT_EFFECTS, RegionType.GET_EFFECTS) contains _.regionType) 49 | } 50 | -------------------------------------------------------------------------------- /src/main/scala/rocket/package.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.Berkeley for license details. 2 | 3 | package freechips.rocketchip 4 | 5 | package object rocket extends rocket.constants.ScalarOpConstants with rocket.constants.MemoryOpConstants 6 | -------------------------------------------------------------------------------- /src/main/scala/subsystem/FrontBus.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | 3 | package freechips.rocketchip.subsystem 4 | 5 | import org.chipsalliance.cde.config._ 6 | import org.chipsalliance.diplomacy.lazymodule._ 7 | 8 | import freechips.rocketchip.devices.tilelink.{BuiltInErrorDeviceParams, BuiltInZeroDeviceParams, BuiltInDevices, HasBuiltInDeviceParams} 9 | import freechips.rocketchip.tilelink.{HasTLBusParams, TLBusWrapper, TLBusWrapperInstantiationLike, HasTLXbarPhy} 10 | import freechips.rocketchip.util.{Location} 11 | 12 | case class FrontBusParams( 13 | beatBytes: Int, 14 | blockBytes: Int, 15 | dtsFrequency: Option[BigInt] = None, 16 | zeroDevice: Option[BuiltInZeroDeviceParams] = None, 17 | errorDevice: Option[BuiltInErrorDeviceParams] = None) 18 | extends HasTLBusParams 19 | with HasBuiltInDeviceParams 20 | with TLBusWrapperInstantiationLike 21 | { 22 | def instantiate(context: HasTileLinkLocations, loc: Location[TLBusWrapper])(implicit p: Parameters): FrontBus = { 23 | val fbus = LazyModule(new FrontBus(this, loc.name)) 24 | fbus.suggestName(loc.name) 25 | context.tlBusWrapperLocationMap += (loc -> fbus) 26 | fbus 27 | } 28 | } 29 | 30 | class FrontBus(params: FrontBusParams, name: String = "front_bus")(implicit p: Parameters) 31 | extends TLBusWrapper(params, name) 32 | with HasTLXbarPhy { 33 | val builtInDevices: BuiltInDevices = BuiltInDevices.attach(params, outwardNode) 34 | val prefixNode = None 35 | } 36 | -------------------------------------------------------------------------------- /src/main/scala/subsystem/Litex.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | // See LICENSE.Berkeley for license details. 3 | 4 | package freechips.rocketchip.subsystem 5 | 6 | import chisel3.util._ 7 | 8 | import org.chipsalliance.cde.config._ 9 | import org.chipsalliance.diplomacy.lazymodule._ 10 | 11 | import freechips.rocketchip.devices.debug.{DebugModuleKey, DefaultDebugModuleParams, ExportDebug, JTAG, APB} 12 | import freechips.rocketchip.devices.tilelink.{ 13 | BuiltInErrorDeviceParams, BootROMLocated, BootROMParams, CLINTKey, DevNullDevice, CLINTParams, PLICKey, PLICParams, DevNullParams 14 | } 15 | import freechips.rocketchip.prci.{SynchronousCrossing, AsynchronousCrossing, RationalCrossing, ClockCrossingType} 16 | import freechips.rocketchip.diplomacy.{ 17 | AddressSet, MonitorsEnabled, 18 | } 19 | import freechips.rocketchip.resources.{ 20 | DTSModel, DTSCompat, DTSTimebase, BigIntHexContext 21 | } 22 | import freechips.rocketchip.tile.{ 23 | MaxHartIdBits, RocketTileParams, BuildRoCC, AccumulatorExample, OpcodeSet, TranslatorExample, CharacterCountExample, BlackBoxExample 24 | } 25 | import freechips.rocketchip.util.ClockGateModelFile 26 | import scala.reflect.ClassTag 27 | 28 | class WithLitexMemPort extends Config((site, here, up) => { 29 | case ExtMem => Some(MemoryPortParams(MasterPortParams( 30 | base = x"8000_0000", 31 | size = x"8000_0000", 32 | beatBytes = site(MemoryBusKey).beatBytes, 33 | idBits = 4), 1)) 34 | }) 35 | 36 | class WithLitexMMIOPort extends Config((site, here, up) => { 37 | case ExtBus => Some(MasterPortParams( 38 | base = x"1000_0000", 39 | size = x"7000_0000", 40 | beatBytes = site(SystemBusKey).beatBytes, 41 | idBits = 4)) 42 | }) 43 | 44 | class WithLitexSlavePort extends Config((site, here, up) => { 45 | case ExtIn => Some(SlavePortParams( 46 | beatBytes = site(SystemBusKey).beatBytes, 47 | idBits = 8, 48 | sourceBits = 4)) 49 | }) 50 | 51 | class WithNBitMemoryBus(dataBits: Int) extends Config((site, here, up) => { 52 | case MemoryBusKey => up(MemoryBusKey, site).copy(beatBytes = dataBits/8) 53 | }) 54 | -------------------------------------------------------------------------------- /src/main/scala/subsystem/LookupByClusterId.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | 3 | package freechips.rocketchip.subsystem 4 | 5 | import chisel3._ 6 | import chisel3.util._ 7 | 8 | abstract class LookupByClusterIdImpl { 9 | def apply[T <: Data](f: ClusterParams => Option[T], clusterId: UInt): T 10 | } 11 | 12 | case class ClustersWontDeduplicate(t: ClusterParams) extends LookupByClusterIdImpl { 13 | def apply[T <: Data](f: ClusterParams => Option[T], clusterId: UInt): T = f(t).get 14 | } 15 | 16 | case class PriorityMuxClusterIdFromSeq(seq: Seq[ClusterParams]) extends LookupByClusterIdImpl { 17 | def apply[T <: Data](f: ClusterParams => Option[T], clusterId: UInt): T = 18 | PriorityMux(seq.collect { case t if f(t).isDefined => (t.clusterId.U === clusterId) -> f(t).get }) 19 | } 20 | -------------------------------------------------------------------------------- /src/main/scala/subsystem/RTC.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | 3 | package freechips.rocketchip.subsystem 4 | 5 | import chisel3._ 6 | import chisel3.util._ 7 | 8 | import org.chipsalliance.diplomacy.lazymodule._ 9 | 10 | import freechips.rocketchip.resources.DTSTimebase 11 | import freechips.rocketchip.devices.tilelink.{CLINTAttachKey, CanHavePeripheryCLINT} 12 | 13 | trait HasRTCModuleImp extends LazyRawModuleImp { 14 | val outer: BaseSubsystem with CanHavePeripheryCLINT 15 | 16 | // Use the static period to toggle the RTC 17 | outer.clintDomainOpt.map { domain => { 18 | val bus = outer.locateTLBusWrapper(p(CLINTAttachKey).slaveWhere) 19 | val busFreq = bus.dtsFrequency.get 20 | val rtcFreq = outer.p(DTSTimebase) 21 | val internalPeriod: BigInt = busFreq / rtcFreq 22 | 23 | 24 | // check whether pbusFreq >= rtcFreq 25 | require(internalPeriod > 0) 26 | // check wehther the integer division is within 5% of the real division 27 | require((busFreq - rtcFreq * internalPeriod) * 100 / busFreq <= 5) 28 | 29 | withClockAndReset (domain.module.clock, domain.module.reset) { 30 | val (_, int_rtc_tick) = Counter(true.B, internalPeriod.toInt) 31 | outer.clintTickOpt.foreach { _ := int_rtc_tick } 32 | } 33 | }} 34 | } 35 | -------------------------------------------------------------------------------- /src/main/scala/subsystem/RocketSubsystem.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | 3 | package freechips.rocketchip.subsystem 4 | 5 | import org.chipsalliance.cde.config._ 6 | 7 | import freechips.rocketchip.devices.debug.HasPeripheryDebug 8 | import freechips.rocketchip.devices.tilelink.{CanHavePeripheryCLINT, CanHavePeripheryPLIC} 9 | import freechips.rocketchip.prci.{ResetCrossingType, NoResetCrossing, SynchronousCrossing, ClockCrossingType} 10 | import freechips.rocketchip.tile.{RocketTile, RocketTileParams} 11 | import freechips.rocketchip.util.HasCoreMonitorBundles 12 | 13 | case class RocketCrossingParams( 14 | crossingType: ClockCrossingType = SynchronousCrossing(), 15 | master: HierarchicalElementPortParamsLike = HierarchicalElementMasterPortParams(), 16 | slave: HierarchicalElementSlavePortParams = HierarchicalElementSlavePortParams(), 17 | mmioBaseAddressPrefixWhere: TLBusWrapperLocation = CBUS, 18 | resetCrossingType: ResetCrossingType = NoResetCrossing(), 19 | forceSeparateClockReset: Boolean = false 20 | ) extends HierarchicalElementCrossingParamsLike 21 | 22 | case class RocketTileAttachParams( 23 | tileParams: RocketTileParams, 24 | crossingParams: RocketCrossingParams 25 | ) extends CanAttachTile { type TileType = RocketTile } 26 | 27 | trait HasRocketTiles { 28 | this: BaseSubsystem with InstantiatesHierarchicalElements => 29 | val rocketTiles = totalTiles.values.collect { case r: RocketTile => r } 30 | 31 | def coreMonitorBundles = (rocketTiles map { t => 32 | t.module.core.rocketImpl.coreMonitorBundle 33 | }).toList 34 | } 35 | 36 | class RocketSubsystem(implicit p: Parameters) extends BaseSubsystem 37 | with InstantiatesHierarchicalElements 38 | with HasTileNotificationSinks 39 | with HasTileInputConstants 40 | with CanHavePeripheryCLINT 41 | with CanHavePeripheryPLIC 42 | with HasPeripheryDebug 43 | with HasHierarchicalElementsRootContext 44 | with HasHierarchicalElements 45 | with HasCoreMonitorBundles 46 | with HasRocketTiles 47 | { 48 | override lazy val module = new RocketSubsystemModuleImp(this) 49 | } 50 | 51 | class RocketSubsystemModuleImp[+L <: RocketSubsystem](_outer: L) extends BaseSubsystemModuleImp(_outer) 52 | with HasHierarchicalElementsRootContextModuleImp { 53 | override lazy val outer = _outer 54 | } 55 | 56 | -------------------------------------------------------------------------------- /src/main/scala/subsystem/SystemBus.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | 3 | package freechips.rocketchip.subsystem 4 | 5 | import org.chipsalliance.cde.config._ 6 | import org.chipsalliance.diplomacy.lazymodule._ 7 | 8 | import freechips.rocketchip.devices.tilelink.{ 9 | BuiltInDevices, BuiltInZeroDeviceParams, BuiltInErrorDeviceParams, HasBuiltInDeviceParams 10 | } 11 | import freechips.rocketchip.tilelink.{ 12 | TLArbiter, RegionReplicator, ReplicatedRegion, HasTLBusParams, TLBusWrapper, 13 | TLBusWrapperInstantiationLike, TLXbar, TLEdge, TLInwardNode, TLOutwardNode, 14 | TLFIFOFixer, TLTempNode 15 | } 16 | import freechips.rocketchip.util.Location 17 | 18 | case class SystemBusParams( 19 | beatBytes: Int, 20 | blockBytes: Int, 21 | policy: TLArbiter.Policy = TLArbiter.roundRobin, 22 | dtsFrequency: Option[BigInt] = None, 23 | zeroDevice: Option[BuiltInZeroDeviceParams] = None, 24 | errorDevice: Option[BuiltInErrorDeviceParams] = None, 25 | replication: Option[ReplicatedRegion] = None) 26 | extends HasTLBusParams 27 | with HasBuiltInDeviceParams 28 | with TLBusWrapperInstantiationLike 29 | { 30 | def instantiate(context: HasTileLinkLocations, loc: Location[TLBusWrapper])(implicit p: Parameters): SystemBus = { 31 | val sbus = LazyModule(new SystemBus(this, loc.name)) 32 | sbus.suggestName(loc.name) 33 | context.tlBusWrapperLocationMap += (loc -> sbus) 34 | sbus 35 | } 36 | } 37 | 38 | class SystemBus(params: SystemBusParams, name: String = "system_bus")(implicit p: Parameters) 39 | extends TLBusWrapper(params, name) 40 | { 41 | private val replicator = params.replication.map(r => LazyModule(new RegionReplicator(r))) 42 | val prefixNode = replicator.map { r => 43 | r.prefix := addressPrefixNexusNode 44 | addressPrefixNexusNode 45 | } 46 | 47 | private val system_bus_xbar = LazyModule(new TLXbar(policy = params.policy, nameSuffix = Some(name))) 48 | val inwardNode: TLInwardNode = system_bus_xbar.node :=* TLFIFOFixer(TLFIFOFixer.allVolatile) :=* replicator.map(_.node).getOrElse(TLTempNode()) 49 | val outwardNode: TLOutwardNode = system_bus_xbar.node 50 | def busView: TLEdge = system_bus_xbar.node.edges.in.head 51 | 52 | val builtInDevices: BuiltInDevices = BuiltInDevices.attach(params, outwardNode) 53 | } 54 | -------------------------------------------------------------------------------- /src/main/scala/system/ExampleRocketSystem.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | 3 | package freechips.rocketchip.system 4 | 5 | import org.chipsalliance.cde.config.Parameters 6 | import freechips.rocketchip.subsystem._ 7 | import freechips.rocketchip.devices.tilelink._ 8 | import freechips.rocketchip.util.DontTouch 9 | 10 | /** Example Top with periphery devices and ports, and a Rocket subsystem */ 11 | class ExampleRocketSystem(implicit p: Parameters) extends RocketSubsystem 12 | with HasAsyncExtInterrupts 13 | with CanHaveMasterAXI4MemPort 14 | with CanHaveMasterAXI4MMIOPort 15 | with CanHaveSlaveAXI4Port 16 | { 17 | // optionally add ROM devices 18 | // Note that setting BootROMLocated will override the reset_vector for all tiles 19 | val bootROM = p(BootROMLocated(location)).map { BootROM.attach(_, this, CBUS) } 20 | val maskROMs = p(MaskROMLocated(location)).map { MaskROM.attach(_, this, CBUS) } 21 | 22 | override lazy val module = new ExampleRocketSystemModuleImp(this) 23 | } 24 | 25 | class ExampleRocketSystemModuleImp[+L <: ExampleRocketSystem](_outer: L) extends RocketSubsystemModuleImp(_outer) 26 | with HasRTCModuleImp 27 | with HasExtInterruptsModuleImp 28 | with DontTouch 29 | -------------------------------------------------------------------------------- /src/main/scala/system/SimAXIMem.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | 3 | package freechips.rocketchip.system // TODO this should really be in a testharness package 4 | 5 | import chisel3._ 6 | 7 | import org.chipsalliance.cde.config._ 8 | import org.chipsalliance.diplomacy.lazymodule._ 9 | 10 | import freechips.rocketchip.amba.AMBACorrupt 11 | import freechips.rocketchip.amba.axi4.{AXI4RAM, AXI4MasterNode, AXI4EdgeParameters, AXI4Xbar, AXI4Buffer, AXI4Fragmenter} 12 | import freechips.rocketchip.diplomacy.AddressSet 13 | import freechips.rocketchip.subsystem.{CanHaveMasterAXI4MMIOPort, CanHaveMasterAXI4MemPort, ExtBus, ExtMem} 14 | 15 | /** Memory with AXI port for use in elaboratable test harnesses. 16 | * 17 | * Topology: AXIRAM <-< AXI4Buffer <-< AXI4Fragmenter <-< AXI4Xbar <-< AXI4MasterNode 18 | */ 19 | class SimAXIMem(edge: AXI4EdgeParameters, size: BigInt, base: BigInt = 0)(implicit p: Parameters) extends SimpleLazyModule { 20 | val node = AXI4MasterNode(List(edge.master)) 21 | val srams = AddressSet.misaligned(base, size).map { aSet => 22 | LazyModule(new AXI4RAM( 23 | address = aSet, 24 | beatBytes = edge.bundle.dataBits/8, 25 | wcorrupt=edge.slave.requestKeys.contains(AMBACorrupt))) 26 | } 27 | val xbar = AXI4Xbar() 28 | srams.foreach{ s => s.node := AXI4Buffer() := AXI4Fragmenter() := xbar } 29 | xbar := node 30 | val io_axi4 = InModuleBody { node.makeIOs() } 31 | } 32 | 33 | /** 34 | * Connect Master AXI4 Mem/MMIO Port to SimAXIMem. 35 | */ 36 | object SimAXIMem { 37 | def connectMMIO(dut: CanHaveMasterAXI4MMIOPort)(implicit p: Parameters): Seq[SimAXIMem] = { 38 | dut.mmio_axi4.zip(dut.mmioAXI4Node.in).map { case (io, (_, edge)) => 39 | // test harness size capped to 4KB (ignoring p(ExtMem).get.master.size) 40 | val mmio_mem = LazyModule(new SimAXIMem(edge, base = p(ExtBus).get.base, size = 4096)) 41 | Module(mmio_mem.module).suggestName("mmio_mem") 42 | mmio_mem.io_axi4.head <> io 43 | mmio_mem 44 | }.toSeq 45 | } 46 | 47 | def connectMem(dut: CanHaveMasterAXI4MemPort)(implicit p: Parameters): Seq[SimAXIMem] = { 48 | dut.mem_axi4.zip(dut.memAXI4Node.in).map { case (io, (_, edge)) => 49 | val mem = LazyModule(new SimAXIMem(edge, base = p(ExtMem).get.master.base, size = p(ExtMem).get.master.size)) 50 | Module(mem.module).suggestName("mem") 51 | mem.io_axi4.head <> io 52 | mem 53 | }.toSeq 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/main/scala/system/TestHarness.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | 3 | package freechips.rocketchip.system 4 | 5 | import chisel3._ 6 | 7 | import org.chipsalliance.cde.config._ 8 | import org.chipsalliance.diplomacy.lazymodule._ 9 | 10 | import freechips.rocketchip.devices.debug.Debug 11 | import freechips.rocketchip.util.AsyncResetReg 12 | 13 | class TestHarness()(implicit p: Parameters) extends Module { 14 | val io = IO(new Bundle { 15 | val success = Output(Bool()) 16 | }) 17 | 18 | val ldut = LazyModule(new ExampleRocketSystem) 19 | val dut = Module(ldut.module) 20 | 21 | ldut.io_clocks.get.elements.values.foreach(_.clock := clock) 22 | // Allow the debug ndreset to reset the dut, but not until the initial reset has completed 23 | val dut_reset = (reset.asBool | ldut.debug.map { debug => AsyncResetReg(debug.ndreset) }.getOrElse(false.B)).asBool 24 | ldut.io_clocks.get.elements.values.foreach(_.reset := dut_reset) 25 | 26 | dut.dontTouchPorts() 27 | dut.tieOffInterrupts() 28 | SimAXIMem.connectMem(ldut) 29 | SimAXIMem.connectMMIO(ldut) 30 | ldut.l2_frontend_bus_axi4.foreach( a => { 31 | a.ar.valid := false.B 32 | a.ar.bits := DontCare 33 | a.aw.valid := false.B 34 | a.aw.bits := DontCare 35 | a.w.valid := false.B 36 | a.w.bits := DontCare 37 | a.r.ready := false.B 38 | a.b.ready := false.B 39 | }) 40 | //ldut.l2_frontend_bus_axi4.foreach(_.tieoff) 41 | Debug.connectDebug(ldut.debug, ldut.resetctrl, ldut.psd, clock, reset.asBool, io.success) 42 | } 43 | -------------------------------------------------------------------------------- /src/main/scala/tile/L1Cache.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | 3 | package freechips.rocketchip.tile 4 | 5 | import chisel3._ 6 | import chisel3.util.log2Up 7 | 8 | import org.chipsalliance.cde.config.Parameters 9 | 10 | trait L1CacheParams { 11 | def nSets: Int 12 | def nWays: Int 13 | def rowBits: Int 14 | def nTLBSets: Int 15 | def nTLBWays: Int 16 | def blockBytes: Int // TODO this is ignored in favor of p(CacheBlockBytes) in BaseTile 17 | } 18 | 19 | trait HasL1CacheParameters extends HasTileParameters { 20 | val cacheParams: L1CacheParams 21 | 22 | def nSets = cacheParams.nSets 23 | def blockOffBits = lgCacheBlockBytes 24 | def idxBits = log2Up(cacheParams.nSets) 25 | def untagBits = blockOffBits + idxBits 26 | def pgUntagBits = if (usingVM) untagBits min pgIdxBits else untagBits 27 | def tagBits = tlBundleParams.addressBits - pgUntagBits 28 | def nWays = cacheParams.nWays 29 | def wayBits = log2Up(nWays) 30 | def isDM = nWays == 1 31 | def rowBits = cacheParams.rowBits 32 | def rowBytes = rowBits/8 33 | def rowOffBits = log2Up(rowBytes) 34 | def nTLBSets = cacheParams.nTLBSets 35 | def nTLBWays = cacheParams.nTLBWays 36 | 37 | def cacheDataBits = cacheParams.rowBits 38 | def cacheDataBytes = cacheDataBits / 8 39 | def cacheDataBeats = (cacheBlockBytes * 8) / cacheDataBits 40 | def refillCycles = cacheDataBeats 41 | } 42 | 43 | abstract class L1CacheModule(implicit val p: Parameters) extends Module 44 | with HasL1CacheParameters 45 | 46 | abstract class L1CacheBundle(implicit val p: Parameters) extends Bundle 47 | with HasL1CacheParameters 48 | -------------------------------------------------------------------------------- /src/main/scala/tile/LookupByHartId.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | 3 | package freechips.rocketchip.tile 4 | 5 | import chisel3._ 6 | import chisel3.util._ 7 | 8 | abstract class LookupByHartIdImpl { 9 | def apply[T <: Data](f: TileParams => Option[T], hartId: UInt): T 10 | } 11 | 12 | case class HartsWontDeduplicate(t: TileParams) extends LookupByHartIdImpl { 13 | def apply[T <: Data](f: TileParams => Option[T], tileId: UInt): T = f(t).get 14 | } 15 | 16 | case class PriorityMuxHartIdFromSeq(seq: Seq[TileParams]) extends LookupByHartIdImpl { 17 | def apply[T <: Data](f: TileParams => Option[T], tileId: UInt): T = 18 | PriorityMux(seq.collect { case t if f(t).isDefined => (t.tileId.U === tileId) -> f(t).get }) 19 | } 20 | -------------------------------------------------------------------------------- /src/main/scala/tile/TilePRCIDomain.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | 3 | package freechips.rocketchip.tile 4 | 5 | import chisel3._ 6 | 7 | import org.chipsalliance.cde.config._ 8 | 9 | import freechips.rocketchip.prci.ClockSinkParameters 10 | import freechips.rocketchip.rocket.TracedInstruction 11 | import freechips.rocketchip.subsystem.{HierarchicalElementCrossingParamsLike, HierarchicalElementPRCIDomain} 12 | import freechips.rocketchip.trace.TraceCoreInterface 13 | 14 | 15 | /** A wrapper containing all logic necessary to safely place a tile 16 | * inside of a particular Power/Reset/Clock/Interrupt domain. 17 | * 18 | * This adds a layer to the module hierarchy which is a parent of the tile 19 | * and should contain all logic related to clock crossings, isolation cells, 20 | * hierarchical P&R boundary buffers, core-local interrupt handling, 21 | * and any other IOs related to PRCI control. 22 | */ 23 | abstract class TilePRCIDomain[T <: BaseTile]( 24 | clockSinkParams: ClockSinkParameters, 25 | crossingParams: HierarchicalElementCrossingParamsLike) 26 | (implicit p: Parameters) 27 | extends HierarchicalElementPRCIDomain[T](clockSinkParams, crossingParams) 28 | { 29 | def tile_reset_domain = element_reset_domain 30 | } 31 | -------------------------------------------------------------------------------- /src/main/scala/tilelink/Atomics.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | 3 | package freechips.rocketchip.tilelink 4 | 5 | import chisel3._ 6 | import chisel3.util._ 7 | 8 | class Atomics(params: TLBundleParameters) extends Module 9 | { 10 | val io = IO(new Bundle { 11 | val write = Flipped(Bool()) // ignore opcode 12 | val a = Flipped(new TLBundleA(params)) 13 | val data_in = Flipped(UInt(params.dataBits.W)) 14 | val data_out = UInt(params.dataBits.W) 15 | }) 16 | 17 | // Arithmetic, what to do 18 | val adder = io.a.param(2) 19 | val unsigned = io.a.param(1) 20 | val take_max = io.a.param(0) 21 | 22 | val signBit = io.a.mask & Cat(1.U, ~io.a.mask >> 1) 23 | val inv_d = Mux(adder, io.data_in, ~io.data_in) 24 | val sum = (FillInterleaved(8, io.a.mask) & io.a.data) + inv_d 25 | def sign(x: UInt): Bool = (Cat(x.asBools.grouped(8).map(_.last).toList.reverse) & signBit).orR 26 | val sign_a = sign(io.a.data) 27 | val sign_d = sign(io.data_in) 28 | val sign_s = sign(sum) 29 | val a_bigger_uneq = unsigned === sign_a // result if high bits are unequal 30 | val a_bigger = Mux(sign_a === sign_d, !sign_s, a_bigger_uneq) 31 | val pick_a = take_max === a_bigger 32 | 33 | // Logical, what to do 34 | val lut = VecInit(Seq( 35 | (0x6).U, // XOR 36 | (0xe).U, // OR 37 | (0x8).U, // AND 38 | (0xc).U))( // SWAP 39 | io.a.param(1,0)) 40 | val logical = Cat((io.a.data.asBools zip io.data_in.asBools).map { case (a, d) => 41 | lut(Cat(a, d)) 42 | }.reverse) 43 | 44 | // Operation, what to do? (0=d, 1=a, 2=sum, 3=logical) 45 | val select = Mux(io.write, 1.U, VecInit(Seq( 46 | 1.U, // PutFullData 47 | 1.U, // PutPartialData 48 | Mux(adder, 2.U, Mux(pick_a, 1.U, 0.U)), // ArithmeticData 49 | 3.U, // LogicalData 50 | 0.U, // Get 51 | 0.U, // Hint 52 | 0.U, // AcquireBlock 53 | 0.U))( // AcquirePerm 54 | io.a.opcode)) 55 | 56 | // Only the masked bytes can be modified 57 | val selects = io.a.mask.asBools.map(b => Mux(b, select, 0.U)) 58 | io.data_out := Cat(selects.zipWithIndex.map { case (s, i) => 59 | VecInit(Seq(io.data_in, io.a.data, sum, logical).map(_((i + 1) * 8 - 1, i * 8)))(s) 60 | }.reverse) 61 | } 62 | -------------------------------------------------------------------------------- /src/main/scala/tilelink/BlockDuringReset.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | 3 | package freechips.rocketchip.tilelink 4 | 5 | import chisel3._ 6 | 7 | import org.chipsalliance.cde.config._ 8 | import org.chipsalliance.diplomacy.lazymodule._ 9 | 10 | import freechips.rocketchip.util.BlockDuringReset 11 | 12 | /** BlockDuringReset ensures that no channel admits to be ready or valid while reset is raised. */ 13 | class TLBlockDuringReset(stretchResetCycles: Int = 0) 14 | (implicit p: Parameters) extends LazyModule 15 | { 16 | val node = TLAdapterNode() 17 | override def shouldBeInlined = true 18 | lazy val module = new Impl 19 | class Impl extends LazyModuleImp(this) { 20 | (node.in zip node.out) foreach { case ((in, edgeIn), (out, edgeOut)) => 21 | out.a :<>= BlockDuringReset(in .a, stretchResetCycles) 22 | in .d :<>= BlockDuringReset(out.d, stretchResetCycles) 23 | if (edgeOut.manager.anySupportAcquireB && edgeOut.client.anySupportProbe) { 24 | in .b :<>= BlockDuringReset(out.b, stretchResetCycles) 25 | out.c :<>= BlockDuringReset(in .c, stretchResetCycles) 26 | out.e :<>= BlockDuringReset(in .e, stretchResetCycles) 27 | } else { 28 | in.b.valid := false.B 29 | in.c.ready := true.B 30 | in.e.ready := true.B 31 | out.b.ready := true.B 32 | out.c.valid := false.B 33 | out.e.valid := false.B 34 | } 35 | } 36 | } 37 | } 38 | 39 | object TLBlockDuringReset { 40 | def apply(stretchCycles: Int = 0)(implicit p: Parameters): TLNode = { 41 | val block_during_reset = LazyModule(new TLBlockDuringReset(stretchCycles)) 42 | block_during_reset.node 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/main/scala/tilelink/Map.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | 3 | package freechips.rocketchip.tilelink 4 | 5 | import chisel3._ 6 | 7 | import org.chipsalliance.cde.config._ 8 | import org.chipsalliance.diplomacy.lazymodule._ 9 | 10 | import freechips.rocketchip.diplomacy.AddressSet 11 | 12 | // Moves the AddressSets of slave devices around 13 | // Combine with TLFilter to remove slaves or reduce their size 14 | class TLMap(fn: AddressSet => BigInt)(implicit p: Parameters) extends LazyModule 15 | { 16 | val node = TLAdapterNode( 17 | clientFn = { cp => cp }, 18 | managerFn = { mp => 19 | mp.v1copy(managers = mp.managers.map(m => 20 | m.v1copy(address = m.address.map(a => 21 | AddressSet(fn(a), a.mask)))))}) 22 | 23 | lazy val module = new Impl 24 | class Impl extends LazyModuleImp(this) { 25 | (node.in zip node.out) foreach { case ((in, edgeIn), (out, edgeOut)) => 26 | out <> in 27 | val convert = edgeIn.manager.managers.flatMap(_.address) zip edgeOut.manager.managers.flatMap(_.address) 28 | def forward(x: UInt) = 29 | convert.map { case (i, o) => Mux(i.contains(x), o.base.U | (x & o.mask.U), 0.U) }.reduce(_ | _) 30 | def backward(x: UInt) = 31 | convert.map { case (i, o) => Mux(o.contains(x), i.base.U | (x & i.mask.U), 0.U) }.reduce(_ | _) 32 | 33 | out.a.bits.address := forward(in.a.bits.address) 34 | if (edgeOut.manager.anySupportAcquireB && edgeOut.client.anySupportProbe) { 35 | out.c.bits.address := forward(in.c.bits.address) 36 | in.b.bits.address := backward(out.b.bits.address) 37 | } 38 | } 39 | } 40 | } 41 | 42 | object TLMap 43 | { 44 | def apply(fn: AddressSet => BigInt)(implicit p: Parameters): TLNode = 45 | { 46 | val map = LazyModule(new TLMap(fn)) 47 | map.node 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/main/scala/tilelink/RegisterRouterTest.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | 3 | package freechips.rocketchip.tilelink 4 | 5 | import chisel3._ 6 | 7 | import org.chipsalliance.cde.config._ 8 | import org.chipsalliance.diplomacy.lazymodule._ 9 | 10 | import freechips.rocketchip.regmapper.{RRTest0, RRTest1} 11 | import freechips.rocketchip.unittest.{UnitTest, UnitTestModule} 12 | 13 | class TLRRTest0(address: BigInt)(implicit p: Parameters) 14 | extends RRTest0(address) 15 | with HasTLControlRegMap 16 | 17 | class TLRRTest1(address: BigInt)(implicit p: Parameters) 18 | extends RRTest1(address, concurrency = 6, undefZero = false) 19 | with HasTLControlRegMap 20 | 21 | class FuzzRRTest0(txns: Int)(implicit p: Parameters) extends LazyModule { 22 | val fuzz = LazyModule(new TLFuzzer(txns)) 23 | val rrtr = LazyModule(new TLRRTest0(0x400)) 24 | 25 | rrtr.node := TLFragmenter(4, 32) := TLDelayer(0.1) := fuzz.node 26 | 27 | lazy val module = new Impl 28 | class Impl extends LazyModuleImp(this) with UnitTestModule { 29 | io.finished := fuzz.module.io.finished 30 | } 31 | } 32 | 33 | class TLRR0Test(txns: Int = 5000, timeout: Int = 500000)(implicit p: Parameters) extends UnitTest(timeout) { 34 | val dut = Module(LazyModule(new FuzzRRTest0(txns)).module) 35 | io.finished := dut.io.finished 36 | dut.io.start := io.start 37 | } 38 | 39 | class FuzzRRTest1(txns: Int)(implicit p: Parameters) extends LazyModule { 40 | val fuzz = LazyModule(new TLFuzzer(txns)) 41 | val rrtr = LazyModule(new TLRRTest1(0x400)) 42 | 43 | rrtr.node := TLFragmenter(4, 32) := TLDelayer(0.1) := fuzz.node 44 | 45 | lazy val module = new Impl 46 | class Impl extends LazyModuleImp(this) with UnitTestModule { 47 | io.finished := fuzz.module.io.finished 48 | } 49 | } 50 | 51 | class TLRR1Test(txns: Int = 5000, timeout: Int = 500000)(implicit p: Parameters) extends UnitTest(timeout) { 52 | val dut = Module(LazyModule(new FuzzRRTest1(txns)).module) 53 | io.finished := dut.io.finished 54 | dut.io.start := io.start 55 | } 56 | 57 | -------------------------------------------------------------------------------- /src/main/scala/tilelink/package.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | 3 | package freechips.rocketchip 4 | 5 | import org.chipsalliance.diplomacy._ 6 | import org.chipsalliance.diplomacy.nodes._ 7 | 8 | import freechips.rocketchip.prci.{HasResetDomainCrossing, HasClockDomainCrossing} 9 | 10 | package object tilelink 11 | { 12 | type TLInwardNode = InwardNodeHandle[TLMasterPortParameters, TLSlavePortParameters, TLEdgeIn, TLBundle] 13 | type TLOutwardNode = OutwardNodeHandle[TLMasterPortParameters, TLSlavePortParameters, TLEdgeOut, TLBundle] 14 | type TLNode = NodeHandle[TLMasterPortParameters, TLSlavePortParameters, TLEdgeIn, TLBundle, TLMasterPortParameters, TLSlavePortParameters, TLEdgeOut, TLBundle] 15 | type TLManagerParameters = TLSlaveParameters 16 | type TLManagerPortParameters = TLSlavePortParameters 17 | type TLClientParameters = TLMasterParameters 18 | type TLClientPortParameters = TLMasterPortParameters 19 | 20 | implicit class TLClockDomainCrossing(private val x: HasClockDomainCrossing) extends AnyVal { 21 | def crossIn (n: TLInwardNode) (implicit valName: ValName) = TLInwardClockCrossingHelper (valName.name, x, n) 22 | def crossOut(n: TLOutwardNode)(implicit valName: ValName) = TLOutwardClockCrossingHelper(valName.name, x, n) 23 | def cross(n: TLInwardNode) (implicit valName: ValName) = crossIn(n) 24 | def cross(n: TLOutwardNode)(implicit valName: ValName) = crossOut(n) 25 | } 26 | 27 | implicit class TLResetDomainCrossing(private val x: HasResetDomainCrossing) extends AnyVal { 28 | def crossIn (n: TLInwardNode) (implicit valName: ValName) = TLInwardResetCrossingHelper (valName.name, x, n) 29 | def crossOut(n: TLOutwardNode)(implicit valName: ValName) = TLOutwardResetCrossingHelper(valName.name, x, n) 30 | def cross(n: TLInwardNode) (implicit valName: ValName) = crossIn(n) 31 | def cross(n: TLOutwardNode)(implicit valName: ValName) = crossOut(n) 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/main/scala/trace/TraceCoreIngress.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.Berkeley for license details. 2 | // See LICENSE.SiFive for license details. 3 | 4 | package freechips.rocketchip.trace 5 | 6 | import chisel3._ 7 | 8 | class TraceCoreIngress(val params: TraceCoreParams) extends Module { 9 | val io = IO(new Bundle { 10 | val in = new Bundle { 11 | val valid = Input(Bool()) 12 | val taken = Input(Bool()) 13 | val is_branch = Input(Bool()) 14 | val is_jal = Input(Bool()) 15 | val is_jalr = Input(Bool()) 16 | val is_compressed = Input(Bool()) 17 | val insn = Input(UInt(params.xlen.W)) 18 | val pc = Input(UInt(params.xlen.W)) 19 | val interrupt = Input(Bool()) 20 | val exception = Input(Bool()) 21 | val trap_return = Input(Bool()) 22 | } 23 | val out = Output(new TraceCoreGroup(params)) 24 | }) 25 | 26 | def gen_itype(insn: UInt, taken: Bool, is_branch: Bool, is_jal: Bool, is_jalr: Bool) = { 27 | val itype = Wire(TraceItype()) 28 | when (io.in.exception) { 29 | itype := TraceItype.ITException 30 | }.elsewhen (io.in.interrupt) { 31 | itype := TraceItype.ITInterrupt 32 | }.elsewhen (io.in.trap_return) { 33 | itype := TraceItype.ITReturn 34 | }.elsewhen (is_branch && taken) { 35 | itype := TraceItype.ITBrTaken 36 | }.elsewhen (is_branch && !taken) { 37 | itype := TraceItype.ITBrNTaken 38 | }.elsewhen (is_jal) { 39 | itype := TraceItype.ITInJump 40 | }.elsewhen (is_jalr) { 41 | itype := TraceItype.ITUnJump 42 | }.otherwise { 43 | itype := TraceItype.ITNothing 44 | } 45 | itype 46 | } 47 | 48 | io.out.iretire := io.in.valid 49 | io.out.iaddr := io.in.pc 50 | io.out.itype := gen_itype(io.in.insn, io.in.taken, io.in.is_branch, io.in.is_jal, io.in.is_jalr) 51 | io.out.ilastsize := io.in.valid && !io.in.is_compressed // 2^1 if non-compressed, 2^0 if compressed 52 | } -------------------------------------------------------------------------------- /src/main/scala/trace/TraceCoreInterface.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.Berkeley for license details. 2 | // See LICENSE.SiFive for license details. 3 | 4 | package freechips.rocketchip.trace 5 | 6 | import chisel3._ 7 | 8 | // Definitions for Trace core Interface defined in RISC-V Processor Trace Specification V1.0 9 | object TraceItype extends ChiselEnum { 10 | val ITNothing = Value(0.U) 11 | val ITException = Value(1.U) 12 | val ITInterrupt = Value(2.U) 13 | val ITExcReturn = Value(3.U) 14 | val ITBrNTaken = Value(4.U) 15 | val ITBrTaken = Value(5.U) 16 | val ITReserved6 = Value(6.U) 17 | val ITReserved7 = Value(7.U) 18 | val ITUnCall = Value(8.U) 19 | val ITInCall = Value(9.U) 20 | val ITUnTail = Value(10.U) 21 | val ITInTail = Value(11.U) 22 | val ITCoSwap = Value(12.U) 23 | val ITReturn = Value(13.U) 24 | val ITUnJump = Value(14.U) 25 | val ITInJump = Value(15.U) 26 | } 27 | 28 | case class TraceCoreParams ( 29 | nGroups: Int = 1, 30 | iretireWidth: Int = 1, 31 | xlen: Int = 32, 32 | iaddrWidth: Int = 32 33 | ) 34 | 35 | 36 | class TraceCoreGroup (val params: TraceCoreParams) extends Bundle { 37 | val iretire = UInt(params.iretireWidth.W) 38 | val iaddr = UInt(params.iaddrWidth.W) 39 | val itype = TraceItype() 40 | val ilastsize = UInt(1.W) 41 | } 42 | 43 | class TraceCoreInterface (val params: TraceCoreParams) extends Bundle { 44 | val group = Vec(params.nGroups, new TraceCoreGroup(params)) 45 | val priv = UInt(4.W) 46 | val tval = UInt(params.xlen.W) 47 | val cause = UInt(params.xlen.W) 48 | val time = UInt(params.xlen.W) 49 | } 50 | 51 | -------------------------------------------------------------------------------- /src/main/scala/trace/TraceEncoder.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.Berkeley for license details. 2 | // See LICENSE.SiFive for license details. 3 | 4 | package freechips.rocketchip.trace 5 | 6 | import chisel3._ 7 | import chisel3.util._ 8 | import scala.math.min 9 | 10 | import org.chipsalliance.cde.config.Parameters 11 | import freechips.rocketchip.diplomacy._ 12 | 13 | case class TraceEncoderParams( 14 | encoderBaseAddr: BigInt, 15 | buildEncoder: Parameters => LazyTraceEncoder, 16 | useArbiterMonitor: Boolean, 17 | // a seq of functions that takes a parameter and returns a lazymodule and a target id 18 | buildSinks: Seq[Parameters => (LazyTraceSink, Int)] = Seq.empty[Parameters => (LazyTraceSink, Int)] 19 | ) 20 | 21 | class LazyTraceEncoder(val coreParams: TraceCoreParams)(implicit p: Parameters) extends LazyModule { 22 | override lazy val module = new LazyTraceEncoderModule(this) 23 | override def shouldBeInlined = false 24 | } 25 | 26 | class LazyTraceEncoderModule(outer: LazyTraceEncoder) extends LazyModuleImp(outer) { 27 | val io = IO(new Bundle { 28 | val control = Input(new TraceEncoderControlInterface()) 29 | val in = Input(new TraceCoreInterface(outer.coreParams)) 30 | val stall = Output(Bool()) 31 | val out = Decoupled(UInt(8.W)) 32 | }) 33 | } -------------------------------------------------------------------------------- /src/main/scala/trace/TraceSink.scala: -------------------------------------------------------------------------------- 1 | package freechips.rocketchip.trace 2 | 3 | import chisel3._ 4 | import chisel3.util._ 5 | import freechips.rocketchip.tilelink._ 6 | import freechips.rocketchip.diplomacy._ 7 | import org.chipsalliance.cde.config.Parameters 8 | import freechips.rocketchip.prci._ 9 | import freechips.rocketchip.subsystem._ 10 | 11 | abstract class LazyTraceSink()(implicit p: Parameters) extends LazyModule { 12 | val module: LazyTraceSinkModuleImp 13 | } 14 | 15 | class LazyTraceSinkModuleImp(outer: LazyTraceSink) extends LazyModuleImp(outer) { 16 | val io = IO(new Bundle { 17 | val trace_in = Flipped(Decoupled(UInt(8.W))) 18 | }) 19 | io := DontCare 20 | } -------------------------------------------------------------------------------- /src/main/scala/trace/TraceSinkArbiter.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.Berkeley for license details. 2 | // See LICENSE.SiFive for license details. 3 | 4 | package freechips.rocketchip.trace 5 | 6 | import chisel3._ 7 | import chisel3.util._ 8 | import org.chipsalliance.cde.config.Parameters 9 | import org.chipsalliance.diplomacy.lazymodule._ 10 | import freechips.rocketchip.diplomacy.{AddressSet} 11 | import freechips.rocketchip.resources.{SimpleDevice} 12 | import freechips.rocketchip.tile._ 13 | import freechips.rocketchip.regmapper.{RegField, RegFieldDesc} 14 | 15 | class TraceSinkArbiter(nSeq : Seq[Int], use_monitor: Boolean = false, monitor_name: String = "unknown") extends Module { 16 | val io = IO(new Bundle { 17 | val target = Input(UInt(TraceSinkTarget.width.W)) 18 | val in = Flipped(Decoupled(UInt(8.W))) 19 | val out = Vec(nSeq.size, Decoupled(UInt(8.W))) 20 | }) 21 | val nVec = VecInit(nSeq.map(_.U)) 22 | io.in.ready := Mux(nVec.contains(io.target), io.out(nVec.indexWhere(_ === io.target)).ready, true.B) 23 | io.out.zipWithIndex.foreach { case (o, i) => 24 | o.valid := io.in.valid && (io.target === nVec(i)) 25 | o.bits := io.in.bits 26 | } 27 | 28 | if (use_monitor) { 29 | val monitor = Module(new TraceSinkMonitor(s"trace_monitor_$monitor_name.out")) 30 | monitor.io.in_fire := io.in.valid && io.in.ready 31 | monitor.io.in_byte := io.in.bits 32 | monitor.io.clk := clock 33 | monitor.io.reset := reset 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/main/scala/trace/TraceSinkMonitor.scala: -------------------------------------------------------------------------------- 1 | package freechips.rocketchip.trace 2 | 3 | import chisel3._ 4 | import chisel3.util._ 5 | import chisel3.experimental.StringParam 6 | 7 | class TraceSinkMonitor(name: String) extends BlackBox( 8 | Map( 9 | "FILE_NAME" -> StringParam(s"${name}_trace.out") 10 | ) 11 | ) with HasBlackBoxResource { 12 | val io = IO(new Bundle { 13 | val clk = Input(Clock()) 14 | val reset = Input(Reset()) 15 | val in_fire = Input(Bool()) 16 | val in_byte = Input(UInt(8.W)) 17 | }) 18 | addResource("/vsrc/TraceSinkMonitor.v") 19 | } -------------------------------------------------------------------------------- /src/main/scala/unittest/TestGenerator.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | 3 | package freechips.rocketchip.unittest 4 | 5 | import chisel3._ 6 | 7 | import org.chipsalliance.cde.config._ 8 | import org.chipsalliance.diplomacy.lazymodule._ 9 | 10 | abstract class LazyUnitTest(implicit p: Parameters) extends LazyModule 11 | { self => 12 | protected def finished: Bool 13 | 14 | lazy val module = new Impl 15 | class Impl extends LazyModuleImp(this) { 16 | val finished = IO(Output(Bool())) 17 | finished := self.finished 18 | } 19 | } 20 | 21 | // FYI, you can call .finished on a Seq[LazyUnitTest] 22 | class TestGenerator(gen: LazyModule => Seq[LazyUnitTest]) 23 | { 24 | def apply(lm: LazyModule) = gen(lm) 25 | def ++ (other: TestGenerator) = new TestGenerator(gen = lm => gen(lm) ++ other(lm)) 26 | } 27 | 28 | object TestGenerator 29 | { 30 | def apply(matcher: PartialFunction[LazyModule, Seq[LazyUnitTest]]): TestGenerator = 31 | new TestGenerator(gen = matcher.lift(_).getOrElse(Nil)) 32 | def recurse(other: TestGenerator): TestGenerator = { 33 | def helper(lm: LazyModule, tail: Seq[LazyUnitTest]): Seq[LazyUnitTest] = 34 | lm.getChildren.foldLeft(other(lm) ++ tail) { case (tail, child) => helper(child, tail) } 35 | new TestGenerator(gen = helper(_, Nil)) 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/main/scala/unittest/TestHarness.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | 3 | package freechips.rocketchip.unittest 4 | 5 | import chisel3._ 6 | import org.chipsalliance.cde.config.Parameters 7 | 8 | class TestHarness(implicit val p: Parameters) extends Module { 9 | val io = IO(new Bundle { val success = Output(Bool()) }) 10 | io.success := Module(new UnitTestSuite).io.finished 11 | } 12 | -------------------------------------------------------------------------------- /src/main/scala/unittest/UnitTest.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | 3 | package freechips.rocketchip.unittest 4 | 5 | import chisel3._ 6 | import chisel3.util._ 7 | import org.chipsalliance.cde.config._ 8 | import freechips.rocketchip.util._ 9 | 10 | trait UnitTestIO { 11 | val finished = Output(Bool()) 12 | val start = Input(Bool()) 13 | } 14 | 15 | trait HasUnitTestIO { 16 | val io: UnitTestIO 17 | } 18 | 19 | trait UnitTestLegacyModule extends HasUnitTestIO { 20 | val io = IO(new Bundle with UnitTestIO) 21 | } 22 | 23 | trait UnitTestModule extends Module with HasUnitTestIO { 24 | val io = IO(new Bundle with UnitTestIO) 25 | ElaborationArtefacts.add("plusArgs", PlusArgArtefacts.serialize_cHeader()) 26 | } 27 | 28 | abstract class UnitTest(val timeout: Int = 4096) extends Module with UnitTestLegacyModule { 29 | val testName = this.getClass.getSimpleName 30 | 31 | when (io.start) { printf(s"Started UnitTest $testName\n") } 32 | 33 | val timed_out = SimpleTimer(timeout, io.start, io.finished) 34 | assert(!timed_out, s"UnitTest $testName timed out") 35 | } 36 | 37 | case object UnitTests extends Field[Parameters => Seq[UnitTest]] 38 | 39 | class UnitTestSuite(implicit p: Parameters) extends Module { 40 | val io = IO(new Bundle { 41 | val finished = Output(Bool()) 42 | }) 43 | 44 | val tests = p(UnitTests)(p) 45 | 46 | val s_idle :: s_start :: s_busy :: s_done :: Nil = Enum(4) 47 | val state = RegInit(s_idle) 48 | val tests_finished = VecInit(tests.map(_.io.finished)).reduce(_&&_) 49 | 50 | tests.foreach { _.io.start := (state === s_start) } 51 | io.finished := (state === s_done) 52 | 53 | when (state === s_idle) { state := s_start } 54 | when (state === s_start) { state := s_busy } 55 | when (state === s_busy && tests_finished) { state := s_done } 56 | } 57 | -------------------------------------------------------------------------------- /src/main/scala/unittest/package.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | 3 | package freechips.rocketchip 4 | 5 | import chisel3._ 6 | 7 | package object unittest 8 | { 9 | implicit class LazyUnitTestSeq(val seq: Seq[LazyUnitTest]) { 10 | def finished = seq.map(_.module.finished).foldLeft(true.B)(_ && _) 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/main/scala/util/BarrelShifter.scala: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chipsalliance/rocket-chip/f517abbf41abb65cea37421d3559f9739efd00a9/src/main/scala/util/BarrelShifter.scala -------------------------------------------------------------------------------- /src/main/scala/util/BlockDuringReset.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | 3 | package freechips.rocketchip.util 4 | 5 | import chisel3._ 6 | import chisel3.util.{Counter, RegEnable} 7 | 8 | /** Blocks transactions until the cycle after reset. */ 9 | object BlockDuringReset 10 | { 11 | private def outOfReset(stretchCycles: Int): Bool = stretchCycles match { 12 | case 0 => RegNext(true.B, false.B) 13 | case i => RegEnable(true.B, false.B, Counter(true.B, i)._2) 14 | } 15 | 16 | def apply[T <: Data : Blockable](data: T, stretchCycles: Int = 0): T = { 17 | implicitly[Blockable[T]].blockWhile(!outOfReset(stretchCycles), data) 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/main/scala/util/Broadcaster.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | // See LICENSE.Berkeley for license details. 3 | 4 | package freechips.rocketchip.util 5 | 6 | import chisel3._ 7 | import chisel3.util._ 8 | 9 | /** Takes in data on one decoupled interface and broadcasts it 10 | * to N decoupled output interfaces. 11 | */ 12 | class Broadcaster[T <: Data](typ: T, n: Int) extends Module { 13 | val io = IO(new Bundle { 14 | val in = Flipped(Decoupled(typ)) 15 | val out = Vec(n, Decoupled(typ)) 16 | }) 17 | 18 | require (n > 0) 19 | 20 | if (n == 1) { 21 | io.out.head <> io.in 22 | } else { 23 | val idx = RegInit(0.U(log2Up(n).W)) 24 | val save = Reg(typ) 25 | 26 | io.out.head.valid := idx === 0.U && io.in.valid 27 | io.out.head.bits := io.in.bits 28 | for (i <- 1 until n) { 29 | io.out(i).valid := idx === i.U 30 | io.out(i).bits := save 31 | } 32 | io.in.ready := io.out.head.ready && idx === 0.U 33 | 34 | when (io.in.fire) { save := io.in.bits } 35 | 36 | when (io.out(idx).fire) { 37 | when (idx === (n - 1).U) { idx := 0.U } 38 | .otherwise { idx := idx + 1.U } 39 | } 40 | } 41 | } 42 | 43 | object Broadcaster { 44 | def apply[T <: Data](in: DecoupledIO[T], n: Int): Vec[DecoupledIO[T]] = { 45 | val split = Module(new Broadcaster(in.bits, n)) 46 | split.io.in <> in 47 | split.io.out 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/main/scala/util/CRC.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | 3 | package freechips.rocketchip.util 4 | 5 | import chisel3._ 6 | import chisel3.util._ 7 | 8 | object CRC 9 | { 10 | // A divisor is interpretted using an explicit+1 CRC notation where bit 0 is required to be one. 11 | // For example, a divisor of 0x1d5 is interpretted to be x^8 + x^7 + x^6 + x^4 + x^2 + 1 12 | // Let n be the highest term in the divisor; n=8 in 0x1d5. 13 | // Then, this function calculates c mod d, returning an n-bit UInt. 14 | // coefficient.width must be <= width 15 | def apply(divisor: BigInt, coefficient: UInt, width: Integer): UInt = { 16 | require (divisor > 0 && divisor.testBit(0)) 17 | require (width > 0) 18 | assert (coefficient >> width === 0.U) 19 | val n = log2Floor(divisor) 20 | val m = width 21 | if (m <= n) return coefficient 22 | 23 | // Initialize the reduction matrix 24 | val array = Array.tabulate(m) { BigInt(1) << _ } 25 | // Reduce the matrix of terms larger than n 26 | for { 27 | i <- (n until m).reverse 28 | j <- 0 to n 29 | if divisor.testBit(j) 30 | } array(i-(n-j)) ^= array(i) 31 | // Construct the circuit 32 | Cat(Seq.tabulate(n) { i => (array(i).U & coefficient).xorR } .reverse) 33 | } 34 | 35 | // Find more great CRC polynomials (using implicit+1 notation) here: https://users.ece.cmu.edu/~koopman/crc/ 36 | val CRC_16F_4_2 = BigInt(0x1a2eb) // HD=4 for <32751 bits and HD=6 for <93 bits, 0xd175 in implicit+1 notation 37 | } 38 | -------------------------------------------------------------------------------- /src/main/scala/util/ClockDivider.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.Berkeley for license details. 2 | 3 | package freechips.rocketchip.util 4 | 5 | import chisel3._ 6 | import chisel3.withClock 7 | import chisel3.util.HasBlackBoxResource 8 | 9 | /** This black-boxes a Clock Divider by 2. 10 | * The output clock is phase-aligned to the input clock. 11 | * If you use this in synthesis, make sure your sdc 12 | * declares that you want it to do the same. 13 | * 14 | * Because Chisel does not support 15 | * blocking assignments, it is impossible 16 | * to create a deterministic divided clock. 17 | */ 18 | class ClockDivider2 extends BlackBox with HasBlackBoxResource { 19 | val io = IO(new Bundle { 20 | val clk_out = Output(Clock()) 21 | val clk_in = Input(Clock()) 22 | }) 23 | 24 | addResource("/vsrc/ClockDivider2.v") 25 | } 26 | class ClockDivider3 extends BlackBox with HasBlackBoxResource { 27 | val io = IO(new Bundle { 28 | val clk_out = Output(Clock()) 29 | val clk_in = Input(Clock()) 30 | }) 31 | 32 | addResource("/vsrc/ClockDivider3.v") 33 | } 34 | 35 | /** Divide the clock by power of 2 times. 36 | * @param pow2 divides the clock 2 ^ pow2 times */ 37 | class Pow2ClockDivider(pow2: Int) extends Module { 38 | val io = IO(new Bundle { 39 | val clock_out = Output(Clock()) 40 | }) 41 | 42 | if (pow2 == 0) { 43 | io.clock_out := clock 44 | } else { 45 | val dividers = Seq.fill(pow2) { Module(new ClockDivider2) } 46 | 47 | dividers.init.zip(dividers.tail).map { case (last, next) => 48 | next.io.clk_in := last.io.clk_out 49 | } 50 | 51 | dividers.head.io.clk_in := clock 52 | io.clock_out := dividers.last.io.clk_out 53 | } 54 | } 55 | 56 | object Pow2ClockDivider { 57 | def apply(pow2: Int): Clock = Module(new Pow2ClockDivider(pow2)).io.clock_out 58 | def apply(clock_in: Clock, pow2: Int): Clock = withClock(clock_in) { apply(pow2) } 59 | } 60 | -------------------------------------------------------------------------------- /src/main/scala/util/ClockGate.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | 3 | package freechips.rocketchip.util 4 | 5 | import chisel3._ 6 | import chisel3.util.{HasBlackBoxResource, HasBlackBoxPath} 7 | import org.chipsalliance.cde.config.{Field, Parameters} 8 | 9 | import java.nio.file.{Files, Paths} 10 | 11 | case object ClockGateImpl extends Field[() => ClockGate](() => new EICG_wrapper) 12 | case object ClockGateModelFile extends Field[Option[String]](None) 13 | 14 | abstract class ClockGate extends BlackBox 15 | with HasBlackBoxResource with HasBlackBoxPath { 16 | val io = IO(new Bundle{ 17 | val in = Input(Clock()) 18 | val test_en = Input(Bool()) 19 | val en = Input(Bool()) 20 | val out = Output(Clock()) 21 | }) 22 | 23 | def addVerilogResource(vsrc: String): Unit = { 24 | if (Files.exists(Paths.get(vsrc))) 25 | addPath(vsrc) 26 | else 27 | addResource(vsrc) 28 | } 29 | } 30 | 31 | object ClockGate { 32 | def apply[T <: ClockGate]( 33 | in: Clock, 34 | en: Bool, 35 | name: Option[String] = None)(implicit p: Parameters): Clock = { 36 | val cg = Module(p(ClockGateImpl)()) 37 | name.foreach(cg.suggestName(_)) 38 | p(ClockGateModelFile).map(cg.addVerilogResource(_)) 39 | 40 | cg.io.in := in 41 | cg.io.test_en := false.B 42 | cg.io.en := en 43 | cg.io.out 44 | } 45 | 46 | def apply[T <: ClockGate]( 47 | in: Clock, 48 | en: Bool, 49 | name: String)(implicit p: Parameters): Clock = 50 | apply(in, en, Some(name)) 51 | } 52 | 53 | // behavioral model of Integrated Clock Gating cell 54 | class EICG_wrapper extends ClockGate 55 | -------------------------------------------------------------------------------- /src/main/scala/util/CoreMonitor.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.Berkeley for license details. 2 | // See LICENSE.SiFive for license details. 3 | 4 | package freechips.rocketchip.util 5 | 6 | import chisel3._ 7 | 8 | // this bundle is used to expose some internal core signals 9 | // to verification monitors which sample instruction commits 10 | class CoreMonitorBundle(val xLen: Int, val fLen: Int) extends Bundle with Clocked { 11 | val excpt = Bool() 12 | val priv_mode = UInt(width = 3.W) 13 | val hartid = UInt(width = xLen.W) 14 | val timer = UInt(width = 32.W) 15 | val valid = Bool() 16 | val pc = UInt(width = xLen.W) 17 | val wrdst = UInt(width = 5.W) 18 | val wrdata = UInt(width = (xLen max fLen).W) 19 | val wrenx = Bool() 20 | val wrenf = Bool() 21 | @deprecated("replace wren with wrenx or wrenf to specify integer or floating point","Rocket Chip 2020.05") 22 | def wren: Bool = wrenx || wrenf 23 | val rd0src = UInt(width = 5.W) 24 | val rd0val = UInt(width = xLen.W) 25 | val rd1src = UInt(width = 5.W) 26 | val rd1val = UInt(width = xLen.W) 27 | val inst = UInt(width = 32.W) 28 | } 29 | 30 | // mark a module that has cores with CoreMonitorBundles 31 | trait HasCoreMonitorBundles { 32 | def coreMonitorBundles: List[CoreMonitorBundle] 33 | } 34 | -------------------------------------------------------------------------------- /src/main/scala/util/Counters.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.Berkeley for license details. 2 | // See LICENSE.SiFive for license details. 3 | 4 | package freechips.rocketchip.util 5 | 6 | import chisel3._ 7 | import chisel3.util._ 8 | 9 | // Produces 0-width value when counting to 1 10 | class ZCounter(val n: Int) { 11 | val value = RegInit(0.U(log2Ceil(n).W)) 12 | def inc(): Bool = { 13 | if (n == 1) true.B 14 | else { 15 | val wrap = value === (n-1).U 16 | value := Mux(!isPow2(n).B && wrap, 0.U, value + 1.U) 17 | wrap 18 | } 19 | } 20 | } 21 | 22 | object ZCounter { 23 | def apply(n: Int) = new ZCounter(n) 24 | def apply(cond: Bool, n: Int): (UInt, Bool) = { 25 | val c = new ZCounter(n) 26 | var wrap: Bool = null 27 | when (cond) { wrap = c.inc() } 28 | (c.value, cond && wrap) 29 | } 30 | } 31 | 32 | object TwoWayCounter { 33 | def apply(up: Bool, down: Bool, max: Int): UInt = { 34 | val cnt = RegInit(0.U(log2Up(max + 1).W)) 35 | when (up && !down) { cnt := cnt + 1.U } 36 | when (down && !up) { cnt := cnt - 1.U } 37 | cnt 38 | } 39 | } 40 | 41 | // a counter that clock gates most of its MSBs using the LSB carry-out 42 | case class WideCounter(width: Int, inc: UInt = 1.U, reset: Boolean = true, inhibit: Bool = false.B) { 43 | private val isWide = width > (2 * inc.getWidth) 44 | private val smallWidth = if (isWide) inc.getWidth max log2Up(width) else width 45 | private val small = if (reset) RegInit(0.U(smallWidth.W)) else Reg(UInt(smallWidth.W)) 46 | private val nextSmall = small +& inc 47 | when (!inhibit) { small := nextSmall } 48 | 49 | private val large = if (isWide) { 50 | val r = if (reset) RegInit(0.U((width - smallWidth).W)) else Reg(UInt((width - smallWidth).W)) 51 | when (nextSmall(smallWidth) && !inhibit) { r := r + 1.U } 52 | r 53 | } else null 54 | 55 | val value = if (isWide) Cat(large, small) else small 56 | lazy val carryOut = { 57 | val lo = (small ^ nextSmall) >> 1 58 | if (!isWide) 59 | lo 60 | else { 61 | val hi = Mux(nextSmall(smallWidth), large ^ (large +& 1.U), 0.U) >> 1 62 | Cat(hi, lo) 63 | } 64 | } 65 | 66 | def := (x: UInt) = { 67 | small := x 68 | if (isWide) large := x >> smallWidth 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/main/scala/util/Crossing.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | 3 | package freechips.rocketchip.util 4 | 5 | import chisel3._ 6 | import chisel3.util._ 7 | 8 | class CrossingIO[T <: Data](gen: T) extends Bundle { 9 | // Enqueue clock domain 10 | val enq_clock = Input(Clock()) 11 | val enq_reset = Input(Bool()) // synchronously deasserted wrt. enq_clock 12 | val enq = Flipped(Decoupled(gen)) 13 | // Dequeue clock domain 14 | val deq_clock = Input(Clock()) 15 | val deq_reset = Input(Bool()) // synchronously deasserted wrt. deq_clock 16 | val deq = Decoupled(gen) 17 | } 18 | 19 | abstract class Crossing[T <: Data] extends RawModule { 20 | val io: CrossingIO[T] 21 | } 22 | -------------------------------------------------------------------------------- /src/main/scala/util/DescribedSRAM.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.Berkeley for license details. 2 | // See LICENSE.SiFive for license details. 3 | 4 | package freechips.rocketchip.util 5 | 6 | import chisel3.{Data, SyncReadMem, Vec} 7 | import chisel3.util.log2Ceil 8 | 9 | object DescribedSRAM { 10 | def apply[T <: Data]( 11 | name: String, 12 | desc: String, 13 | size: BigInt, // depth 14 | data: T 15 | ): SyncReadMem[T] = { 16 | 17 | val mem = SyncReadMem(size, data) 18 | 19 | mem.suggestName(name) 20 | 21 | val granWidth = data match { 22 | case v: Vec[_] => v.head.getWidth 23 | case d => d.getWidth 24 | } 25 | 26 | val uid = 0 27 | 28 | Annotated.srams( 29 | component = mem, 30 | name = name, 31 | address_width = log2Ceil(size), 32 | data_width = data.getWidth, 33 | depth = size, 34 | description = desc, 35 | write_mask_granularity = granWidth 36 | ) 37 | 38 | mem 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/main/scala/util/Frequency.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | // See LICENSE.Berkeley for license details. 3 | 4 | package freechips.rocketchip.util 5 | 6 | import chisel3._ 7 | import chisel3.util._ 8 | 9 | /** Given a list of (frequency, value) pairs, return a random value 10 | * according to the frequency distribution. The sum of the 11 | * frequencies in the distribution must be a power of two. 12 | */ 13 | object Frequency { 14 | def apply(dist : List[(Int, Bits)]) : Bits = { 15 | // Distribution must be non-empty 16 | require(dist.length > 0) 17 | 18 | // Require that the frequencies sum to a power of two 19 | val (freqs, vals) = dist.unzip 20 | val total = freqs.sum 21 | require(isPow2(total)) 22 | 23 | // First item in the distribution 24 | val (firstFreq, firstVal) = dist.head 25 | 26 | // Result wire 27 | val result = Wire(Bits(firstVal.getWidth.W)) 28 | result := 0.U 29 | 30 | // Random value 31 | val randVal = LCG(log2Up(total)) 32 | 33 | // Pick return value 34 | var count = firstFreq 35 | var select = when (randVal < firstFreq.U) { result := firstVal } 36 | for (p <- dist.drop(1)) { 37 | count = count + p._1 38 | select = select.elsewhen(randVal < count.U) { result := p._2 } 39 | } 40 | 41 | return result 42 | } 43 | } 44 | 45 | -------------------------------------------------------------------------------- /src/main/scala/util/GeneratorUtils.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | 3 | package freechips.rocketchip.util 4 | 5 | object ElaborationArtefacts { 6 | var files: Seq[(String, () => String)] = Nil 7 | 8 | def add(extension: String, contents: => String): Unit = { 9 | files = (extension, () => contents) +: files 10 | } 11 | 12 | def contains(extension: String): Boolean = { 13 | files.foldLeft(false)((t, s) => {s._1 == extension | t}) 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/main/scala/util/GenericParameterizedBundle.scala: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chipsalliance/rocket-chip/f517abbf41abb65cea37421d3559f9739efd00a9/src/main/scala/util/GenericParameterizedBundle.scala -------------------------------------------------------------------------------- /src/main/scala/util/HellaQueue.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.Berkeley for license details. 2 | 3 | package freechips.rocketchip.util 4 | 5 | import chisel3._ 6 | import chisel3.util._ 7 | 8 | class HellaFlowQueue[T <: Data](val entries: Int)(data: => T) extends Module { 9 | val io = IO(new QueueIO(data, entries)) 10 | require(entries > 1) 11 | 12 | val do_flow = Wire(Bool()) 13 | val do_enq = io.enq.fire && !do_flow 14 | val do_deq = io.deq.fire && !do_flow 15 | 16 | val maybe_full = RegInit(false.B) 17 | val enq_ptr = Counter(do_enq, entries)._1 18 | val (deq_ptr, deq_done) = Counter(do_deq, entries) 19 | when (do_enq =/= do_deq) { maybe_full := do_enq } 20 | 21 | val ptr_match = enq_ptr === deq_ptr 22 | val empty = ptr_match && !maybe_full 23 | val full = ptr_match && maybe_full 24 | val atLeastTwo = full || enq_ptr - deq_ptr >= 2.U 25 | do_flow := empty && io.deq.ready 26 | 27 | val ram = SyncReadMem(entries, data) 28 | when (do_enq) { ram.write(enq_ptr, io.enq.bits) } 29 | 30 | // BUG! does not hold the output of the SRAM when !ready 31 | // ... However, HellaQueue is correct due to the pipe stage 32 | val ren = io.deq.ready && (atLeastTwo || !io.deq.valid && !empty) 33 | val raddr = Mux(io.deq.valid, Mux(deq_done, 0.U, deq_ptr + 1.U), deq_ptr) 34 | val ram_out_valid = RegNext(ren) 35 | 36 | io.deq.valid := Mux(empty, io.enq.valid, ram_out_valid) 37 | io.enq.ready := !full 38 | io.deq.bits := Mux(empty, io.enq.bits, ram.read(raddr, ren)) 39 | 40 | // Count was never correctly set. To keep the same behavior across chisel3 upgrade, we are explicitly setting it to DontCare 41 | io.count := DontCare 42 | } 43 | 44 | class HellaQueue[T <: Data](val entries: Int)(data: => T) extends Module { 45 | val io = IO(new QueueIO(data, entries)) 46 | 47 | val fq = Module(new HellaFlowQueue(entries)(data)) 48 | fq.io.enq <> io.enq 49 | io.deq <> Queue(fq.io.deq, 1, pipe = true) 50 | io.count := fq.io.count 51 | } 52 | 53 | object HellaQueue { 54 | def apply[T <: Data](enq: DecoupledIO[T], entries: Int) = { 55 | val q = Module((new HellaQueue(entries)) { enq.bits }) 56 | q.io.enq.valid := enq.valid // not using <> so that override is allowed 57 | q.io.enq.bits := enq.bits 58 | enq.ready := q.io.enq.ready 59 | q.io.deq 60 | } 61 | } 62 | 63 | 64 | -------------------------------------------------------------------------------- /src/main/scala/util/IDPool.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | 3 | package freechips.rocketchip.util 4 | 5 | import chisel3._ 6 | import chisel3.util._ 7 | 8 | class IDPool(numIds: Int, lateValid: Boolean = false, revocableSelect: Boolean = false) extends Module { 9 | require (numIds > 0) 10 | val idWidth = log2Up(numIds) 11 | 12 | val io = IO(new Bundle { 13 | val free = Flipped(Valid(UInt(idWidth.W))) 14 | val alloc = if (revocableSelect) Decoupled(UInt(idWidth.W)) else Irrevocable(UInt(idWidth.W)) 15 | }) 16 | 17 | // True indicates that the id is available 18 | val bitmap = RegInit(UInt(numIds.W), -1.S(numIds.W).asUInt) 19 | val select = RegInit(0.U(idWidth.W)) 20 | val valid = RegInit(true.B) 21 | 22 | io.alloc.valid := (if (lateValid) bitmap.orR else valid) 23 | io.alloc.bits := (if (revocableSelect) PriorityEncoder(bitmap) else select) 24 | 25 | val taken = Mux(io.alloc.ready, UIntToOH(io.alloc.bits, numIds), 0.U) 26 | val allocated = Mux(io.free .valid, UIntToOH(io.free .bits, numIds), 0.U) 27 | val bitmap1 = (bitmap & ~taken) | allocated 28 | val select1 = PriorityEncoder(bitmap1) 29 | val valid1 = ( (bitmap.orR && !((PopCount(bitmap) === 1.U) && io.alloc.ready)) // bitmap not zero, and not allocating last bit 30 | || io.free.valid) 31 | 32 | // Clock gate the bitmap 33 | when (io.alloc.ready || io.free.valid) { 34 | bitmap := bitmap1 35 | valid := valid1 36 | } 37 | 38 | // Make select irrevocable 39 | when (io.alloc.ready || (!io.alloc.valid && io.free.valid)) { 40 | select := select1 41 | } 42 | 43 | // No double freeing 44 | assert (!io.free.valid || !(bitmap & ~taken)(io.free.bits)) 45 | 46 | // pre-calculations for timing 47 | if (!lateValid) { 48 | assert (valid === bitmap.orR) 49 | } 50 | if (!revocableSelect) { 51 | when (io.alloc.valid && RegNext(io.alloc.ready || (!io.alloc.valid && io.free.valid))) { 52 | assert (select === PriorityEncoder(bitmap)) 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/main/scala/util/IdentityModule.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | 3 | package freechips.rocketchip.tilelink 4 | 5 | import chisel3._ 6 | 7 | class IdentityModule[T <: Data](gen: T) extends Module 8 | { 9 | val io = IO(new Bundle { 10 | val in = Flipped(gen.cloneType) 11 | val out = gen.cloneType 12 | }) 13 | 14 | io.out := io.in 15 | } 16 | 17 | object IdentityModule 18 | { 19 | def apply[T <: Data](x: T): T = { 20 | val identity = Module(new IdentityModule(x)) 21 | identity.io.in := x 22 | identity.io.out 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/main/scala/util/LCG.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | // See LICENSE.Berkeley for license details. 3 | 4 | package freechips.rocketchip.util 5 | 6 | import chisel3._ 7 | import chisel3.util.Cat 8 | 9 | /** A 16-bit psuedo-random generator based on a linear conguential 10 | * generator (LCG). The state is stored in an unitialised register. 11 | * When using the C++ backend, it is straigtforward to arrange a 12 | * random initial value for each uninitialised register, effectively 13 | * seeding each LCG16 instance with a different seed. 14 | */ 15 | class LCG16 extends Module { 16 | val io = IO(new Bundle { 17 | val out = Output(UInt(16.W)) 18 | val inc = Input(Bool()) 19 | }) 20 | val state = Reg(UInt(32.W)) 21 | when (io.inc) { 22 | state := state * 1103515245.U(32.W) + 12345.U(32.W) 23 | } 24 | io.out := state(30, 15) 25 | } 26 | 27 | /** An n-bit psuedo-random generator made from many instances of a 28 | * 16-bit LCG. Parameter 'width' must be larger than 0. 29 | */ 30 | class LCG(val w: Int) extends Module { 31 | val io = IO(new Bundle { 32 | val out = Output(UInt(w.W)) 33 | val inc = Input(Bool()) 34 | }) 35 | require(w > 0) 36 | val numLCG16s : Int = (w+15)/16 37 | val outs = Seq.fill(numLCG16s) { LCG16(io.inc) } 38 | io.out := Cat(outs) 39 | } 40 | 41 | object LCG16 { 42 | def apply(inc: Bool = true.B): UInt = { 43 | val lcg = Module(new LCG16) 44 | lcg.io.inc := inc 45 | lcg.io.out 46 | } 47 | } 48 | 49 | object LCG { 50 | def apply(w: Int, inc: Bool = true.B): UInt = { 51 | val lcg = Module(new LCG(w)) 52 | lcg.io.inc := inc 53 | lcg.io.out 54 | } 55 | } 56 | 57 | -------------------------------------------------------------------------------- /src/main/scala/util/LatencyPipe.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.Berkeley for license details. 2 | 3 | package freechips.rocketchip.util 4 | 5 | import chisel3._ 6 | import chisel3.util._ 7 | 8 | class LatencyPipe[T <: Data](typ: T, latency: Int) extends Module { 9 | val io = IO(new Bundle { 10 | val in = Flipped(Decoupled(typ)) 11 | val out = Decoupled(typ) 12 | }) 13 | 14 | def doN[T](n: Int, func: T => T, in: T): T = 15 | (0 until n).foldLeft(in)((last, _) => func(last)) 16 | 17 | io.out <> doN(latency, (last: DecoupledIO[T]) => Queue(last, 1, true), io.in) 18 | } 19 | 20 | object LatencyPipe { 21 | def apply[T <: Data](in: DecoupledIO[T], latency: Int): DecoupledIO[T] = { 22 | val pipe = Module(new LatencyPipe(chiselTypeOf(in.bits), latency)) 23 | pipe.io.in <> in 24 | pipe.io.out 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/main/scala/util/Location.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | 3 | package freechips.rocketchip.util 4 | 5 | import scala.language.dynamics 6 | import scala.collection.mutable.Map 7 | 8 | class Location[T](val name: String) extends Dynamic { 9 | def selectDynamic[A](portname: String): Location[A] = new Location[A](s"${name}_${portname}") 10 | def applyDynamic[A](portname: String)(args: A*): (Location[A], A) = { 11 | require(args.size == 1, "Location: can't support multiple things at one port yet") 12 | (new Location[A](s"${name}_${portname}"), args.head) 13 | } 14 | override def toString = s"Location($name)" 15 | } 16 | 17 | object Location { 18 | def apply[T](name: String): Location[T] = new Location[T](name) 19 | } 20 | 21 | class LocationMap[T] private (val internalMap: Map[String, T]) extends Map[Location[_], T] { 22 | def addOne(kv: (Location[_], T)) = { (internalMap += (kv._1.name -> kv._2)); this } 23 | def subtractOne(key: Location[_]) = { (internalMap -= key.name); this } 24 | def get(key: Location[_]) = internalMap.get(key.name) 25 | def iterator = internalMap.iterator.map(kv => (new Location(kv._1), kv._2)) 26 | // TODO override def default to provide specific exception on missing location? 27 | // TODO figure out how to be more clever about applying sub-type casting 28 | // for other the other Map trait methods 29 | def required[L <: T](key: Location[_]): L = internalMap(key.name).asInstanceOf[L] 30 | def optional[L <: T](key: Location[_]): Option[L] = internalMap.lift(key.name).map(_.asInstanceOf[L]) 31 | } 32 | 33 | object LocationMap { 34 | def apply[T](lm: Map[String, T]): LocationMap[T] = new LocationMap(lm) 35 | def empty[T]: LocationMap[T] = new LocationMap(Map.empty[String, T]) 36 | } 37 | -------------------------------------------------------------------------------- /src/main/scala/util/PSDTestMode.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | 3 | package freechips.rocketchip.util 4 | 5 | import chisel3._ 6 | 7 | import org.chipsalliance.cde.config._ 8 | import org.chipsalliance.diplomacy._ 9 | import org.chipsalliance.diplomacy.bundlebridge._ 10 | 11 | case object IncludePSDTest extends Field[Boolean](false) 12 | case object PSDTestModeBroadcastKey extends Field( 13 | BundleBridgeEphemeralNode[PSDTestMode]()(ValName("global_psd_test_mode")) 14 | ) 15 | 16 | class PSDTestMode extends Bundle { 17 | val test_mode = Bool() 18 | val test_mode_reset = Bool() 19 | // TODO: Clocks? 20 | } 21 | 22 | trait CanHavePSDTestModeIO { 23 | implicit val p: Parameters 24 | val psd = p(IncludePSDTest).option(Input(new PSDTestMode())) 25 | } 26 | -------------------------------------------------------------------------------- /src/main/scala/util/ROMGenerator.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | 3 | package freechips.rocketchip.util 4 | 5 | import chisel3._ 6 | import chisel3.util.log2Ceil 7 | import scala.collection.mutable.{HashMap} 8 | 9 | case class ROMConfig(name: String, depth: Int, width: Int) 10 | 11 | class BlackBoxedROM(c: ROMConfig) extends BlackBox { 12 | val io = IO(new Bundle { 13 | val clock = Input(Clock()) 14 | val address = Input(UInt(log2Ceil(c.depth).W)) 15 | val oe = Input(Bool()) 16 | val me = Input(Bool()) 17 | val q = Output(UInt(c.width.W)) 18 | }) 19 | 20 | override def desiredName: String = c.name 21 | } 22 | 23 | object ROMGenerator { 24 | private var finalized = false 25 | private val roms = HashMap[BlackBoxedROM, ROMConfig]() 26 | def apply(c: ROMConfig): BlackBoxedROM = { 27 | require(!finalized) 28 | val m = Module(new BlackBoxedROM(c)) 29 | roms(m) = c 30 | m 31 | } 32 | def lookup(m: BlackBoxedROM): ROMConfig = { 33 | finalized = true 34 | roms(m) 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/main/scala/util/RecordMap.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | 3 | package freechips.rocketchip.util 4 | 5 | import chisel3._ 6 | import scala.collection.immutable.ListMap 7 | import chisel3.experimental.requireIsChiselType 8 | import chisel3.reflect.DataMirror.internal.chiselTypeClone 9 | 10 | final class RecordMap[T <: Data] (eltMap: ListMap[String, T]) 11 | extends Record { 12 | 13 | eltMap.foreach { case (name, elt) => requireIsChiselType(elt, name) } 14 | 15 | // This is needed for Record 16 | val elements = ListMap[String, T]() ++ eltMap.mapValues(chiselTypeClone(_).asInstanceOf[T]) // mapValues return value is lazy 17 | 18 | def apply(x: Int) = elements.values.toSeq(x) 19 | def apply(x: String) = elements.get(x) 20 | def size = elements.size 21 | def data = elements.values 22 | 23 | } 24 | 25 | object RecordMap { 26 | 27 | def apply[T <: Data](eltMap: ListMap[String, T]) = new RecordMap(eltMap) 28 | 29 | def apply[T <: Data](elements: (String, T)*): RecordMap[T] = { 30 | new RecordMap[T](ListMap[String, T](elements:_*)) 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/main/scala/util/ReduceOthers.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | 3 | package freechips.rocketchip.util 4 | 5 | import chisel3._ 6 | 7 | object ReduceOthers { 8 | // Given a list of bools, create this output: 9 | // out[i] = AND[j=0..out.size, j!=i] in[j] 10 | def apply(x: Seq[Bool]): Seq[Bool] = { 11 | val (literals, variables) = x.partition(_.isLit) 12 | 13 | val falses = literals.count(_.litValue == 0) 14 | if (falses > 2) { 15 | Seq.fill(x.size) { false.B } 16 | } else if (falses == 1) { 17 | x.map { b => 18 | if (b.isLit && b.litValue == 0) { 19 | variables.foldLeft(true.B)(_ && _) 20 | } else { 21 | false.B 22 | } 23 | } 24 | } else { 25 | var (out, all) = helper(variables) 26 | x.map { b => 27 | if (b.isLit) { 28 | all 29 | } else { 30 | val sel = out.head 31 | out = out.tail 32 | sel 33 | } 34 | } 35 | } 36 | } 37 | // Take pairs of (output_wire, input_bool) 38 | def apply(x: Seq[(Bool, Bool)]): Unit = { 39 | (x.map(_._1) zip apply(x.map(_._2))) foreach { case (w, x) => w := x } 40 | } 41 | private def helper(x: Seq[Bool]): (Seq[Bool], Bool) = { 42 | if (x.size <= 1) { 43 | (Seq.fill(x.size) { true.B }, x.headOption.getOrElse(true.B)) 44 | } else if (x.size <= 3) { 45 | (Seq.tabulate(x.size) { i => 46 | (x.take(i) ++ x.drop(i+1)).reduce(_ && _) 47 | }, x.reduce(_ && _)) 48 | } else { 49 | val (half, all) = helper(x.grouped(2).map(_.reduce(_ && _)).toList) 50 | (Seq.tabulate(x.size) { i => 51 | if ((i ^ 1) >= x.size) half(i/2) else x(i ^ 1) && half(i / 2) 52 | }, all) 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/main/scala/util/Repeater.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | 3 | package freechips.rocketchip.util 4 | 5 | import chisel3._ 6 | import chisel3.util.{Decoupled, DecoupledIO} 7 | 8 | // A Repeater passes its input to its output, unless repeat is asserted. 9 | // When repeat is asserted, the Repeater copies the input and repeats it next cycle. 10 | class Repeater[T <: Data](gen: T) extends Module 11 | { 12 | override def desiredName = s"Repeater_${gen.typeName}" 13 | val io = IO( new Bundle { 14 | val repeat = Input(Bool()) 15 | val full = Output(Bool()) 16 | val enq = Flipped(Decoupled(gen.cloneType)) 17 | val deq = Decoupled(gen.cloneType) 18 | } ) 19 | 20 | val full = RegInit(false.B) 21 | val saved = Reg(gen.cloneType) 22 | 23 | // When !full, a repeater is pass-through 24 | io.deq.valid := io.enq.valid || full 25 | io.enq.ready := io.deq.ready && !full 26 | io.deq.bits := Mux(full, saved, io.enq.bits) 27 | io.full := full 28 | 29 | when (io.enq.fire && io.repeat) { full := true.B; saved := io.enq.bits } 30 | when (io.deq.fire && !io.repeat) { full := false.B } 31 | } 32 | 33 | object Repeater 34 | { 35 | def apply[T <: Data](enq: DecoupledIO[T], repeat: Bool): DecoupledIO[T] = { 36 | val repeater = Module(new Repeater(chiselTypeOf(enq.bits))) 37 | repeater.io.repeat := repeat 38 | repeater.io.enq <> enq 39 | repeater.io.deq 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/main/scala/util/ResetCatchAndSync.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | 3 | package freechips.rocketchip.util 4 | 5 | import chisel3._ 6 | import chisel3.{withClockAndReset, withReset} 7 | 8 | /** Reset: asynchronous assert, 9 | * synchronous de-assert 10 | * 11 | */ 12 | 13 | class ResetCatchAndSync (sync: Int = 3) extends Module { 14 | 15 | override def desiredName = s"ResetCatchAndSync_d${sync}" 16 | 17 | val io = IO(new Bundle { 18 | val sync_reset = Output(Bool()) 19 | val psd = Input(new PSDTestMode()) 20 | }) 21 | 22 | // Bypass both the resets to the flops themselves (to prevent DFT holes on 23 | // those flops) and on the output of the synchronizer circuit (to control 24 | // reset to any flops this circuit drives). 25 | 26 | val post_psd_reset = Mux(io.psd.test_mode, io.psd.test_mode_reset, reset.asBool) 27 | withReset(post_psd_reset) { 28 | io.sync_reset := Mux(io.psd.test_mode, io.psd.test_mode_reset, 29 | ~AsyncResetSynchronizerShiftReg(true.B, sync)) 30 | } 31 | } 32 | 33 | object ResetCatchAndSync { 34 | 35 | def apply(clk: Clock, rst: Bool, sync: Int = 3, name: Option[String] = None, 36 | psd: Option[PSDTestMode] = None): Bool = { 37 | 38 | withClockAndReset(clk, rst) { 39 | val catcher = Module (new ResetCatchAndSync(sync)) 40 | if (name.isDefined) {catcher.suggestName(name.get)} 41 | catcher.io.psd <> psd.getOrElse(WireDefault(0.U.asTypeOf(new PSDTestMode()))) 42 | catcher.io.sync_reset 43 | } 44 | } 45 | 46 | def apply(clk: Clock, rst: Bool, sync: Int, name: String): Bool = apply(clk, rst, sync, Some(name)) 47 | def apply(clk: Clock, rst: Bool, name: String): Bool = apply(clk, rst, name = Some(name)) 48 | 49 | def apply(clk: Clock, rst: Bool, sync: Int, name: String, psd: PSDTestMode): Bool = 50 | apply(clk, rst, sync, Some(name), Some(psd)) 51 | def apply(clk: Clock, rst: Bool, name: String, psd: PSDTestMode): Bool = 52 | apply(clk, rst, name = Some(name), psd = Some(psd)) 53 | 54 | } 55 | -------------------------------------------------------------------------------- /src/main/scala/util/SeededRandom.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | 3 | package freechips.rocketchip.util 4 | 5 | /** Using e.g. Random.nextInt makes your hardware generation non-repoducible, 6 | * which is almost certainly undesirable. Use LCG to increment random numbers in HW, 7 | * or use this SeededRandom.fromSeed to make reproducible Scala PRNGs. 8 | */ 9 | object SeededRandom { 10 | val fromSeed = new scala.util.Random(42) 11 | } 12 | -------------------------------------------------------------------------------- /src/main/scala/util/ShiftQueue.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | 3 | package freechips.rocketchip.util 4 | 5 | import chisel3._ 6 | import chisel3.util._ 7 | 8 | /** Implements the same interface as chisel3.util.Queue, but uses a shift 9 | * register internally. It is less energy efficient whenever the queue 10 | * has more than one entry populated, but is faster on the dequeue side. 11 | * It is efficient for usually-empty flow-through queues. */ 12 | class ShiftQueue[T <: Data](gen: T, 13 | val entries: Int, 14 | pipe: Boolean = false, 15 | flow: Boolean = false) 16 | extends Module { 17 | val io = IO(new QueueIO(gen, entries) { 18 | val mask = Output(UInt(entries.W)) 19 | }) 20 | 21 | private val valid = RegInit(VecInit(Seq.fill(entries) { false.B })) 22 | private val elts = Reg(Vec(entries, gen)) 23 | 24 | for (i <- 0 until entries) { 25 | def paddedValid(i: Int) = if (i == -1) true.B else if (i == entries) false.B else valid(i) 26 | 27 | val wdata = if (i == entries-1) io.enq.bits else Mux(valid(i+1), elts(i+1), io.enq.bits) 28 | val wen = 29 | Mux(io.deq.ready, 30 | paddedValid(i+1) || io.enq.fire && ((i == 0 && !flow).B || valid(i)), 31 | io.enq.fire && paddedValid(i-1) && !valid(i)) 32 | when (wen) { elts(i) := wdata } 33 | 34 | valid(i) := 35 | Mux(io.deq.ready, 36 | paddedValid(i+1) || io.enq.fire && ((i == 0 && !flow).B || valid(i)), 37 | io.enq.fire && paddedValid(i-1) || valid(i)) 38 | } 39 | 40 | io.enq.ready := !valid(entries-1) 41 | io.deq.valid := valid(0) 42 | io.deq.bits := elts.head 43 | 44 | if (flow) { 45 | when (io.enq.valid) { io.deq.valid := true.B } 46 | when (!valid(0)) { io.deq.bits := io.enq.bits } 47 | } 48 | 49 | if (pipe) { 50 | when (io.deq.ready) { io.enq.ready := true.B } 51 | } 52 | 53 | io.mask := valid.asUInt 54 | io.count := PopCount(io.mask) 55 | } 56 | 57 | object ShiftQueue 58 | { 59 | def apply[T <: Data](enq: DecoupledIO[T], entries: Int = 2, pipe: Boolean = false, flow: Boolean = false): DecoupledIO[T] = { 60 | val q = Module(new ShiftQueue(enq.bits.cloneType, entries, pipe, flow)) 61 | q.io.enq <> enq 62 | q.io.deq 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /src/main/scala/util/SimpleProduct.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | 3 | package freechips.rocketchip.util 4 | 5 | // To mix this trait, you must supply: 6 | // override def canEqual(that: Any): Boolean = that.isInstanceOf[YourClass] 7 | // override def productPrefix: String = "YourClass" 8 | // def productArity: Int = # of fields 9 | // def productElement(n: Int): Any = field accessors 10 | // In exchange you get: 11 | // def equals(that: Any): Boolean = same type and same fields 12 | // def hashCode: Int = hash of all fields (and productPrefix) 13 | // def toString: String = formats as "productPrefix(field1, field2, ...)" 14 | trait SimpleProduct extends Product with Equals { 15 | override def equals(other: Any): Boolean = other match { 16 | case that: SimpleProduct => 17 | def canEq = that.canEqual(this) && this.canEqual(that) 18 | def iter = that.productIterator zip this.productIterator 19 | canEq && iter.forall { case (a, b) => a == b } 20 | case _ => false 21 | } 22 | 23 | override def hashCode: Int = scala.util.hashing.MurmurHash3.productHash(this) 24 | 25 | override def toString: String = { 26 | val b = new StringBuilder(productPrefix) 27 | val iter = productIterator 28 | b += '(' 29 | if (iter.hasNext) { 30 | b ++= iter.next().toString 31 | while (iter.hasNext) { 32 | b ++= ", " 33 | b ++= iter.next().toString 34 | } 35 | } 36 | b += ')' 37 | b.toString 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /verilator.hash: -------------------------------------------------------------------------------- 1 | 4.226 2 | --------------------------------------------------------------------------------