├── .github ├── ISSUE_TEMPLATE.md └── PULL_REQUEST_TEMPLATE.md ├── .gitignore ├── .gitmodules ├── .travis.yml ├── LICENSE.Berkeley ├── LICENSE.SiFive ├── LICENSE.jtag ├── Makefrag ├── README-rocketchip.md ├── README.md ├── README_LvNA.md ├── README_TRAVIS.md ├── bootrom ├── .gitignore ├── Makefile ├── bootrom.S └── linker.ld ├── build.sbt ├── csrc ├── client.c └── dmi.h ├── emulator ├── .gitignore ├── Makefile └── Makefrag-verilator ├── fpga ├── .gitignore ├── Makefile ├── Makefile.check ├── Makefile.sw ├── README.md ├── board │ ├── common.tcl │ ├── sidewinder │ │ ├── bd │ │ │ └── prm.tcl │ │ ├── constr │ │ │ └── constr.xdc │ │ ├── mk.tcl │ │ ├── rtl │ │ │ ├── addr_mapper.v │ │ │ └── system_top.v │ │ └── vivado │ │ │ ├── README.md │ │ │ └── sidewinder │ │ │ └── Fidus │ │ │ └── 2.0 │ │ │ ├── Fidus.jpeg │ │ │ ├── board.xml │ │ │ └── preset.xml │ ├── ultraZ │ │ ├── bd │ │ │ └── prm.tcl │ │ ├── constr │ │ │ └── constr.xdc │ │ ├── mk.tcl │ │ └── rtl │ │ │ ├── addr_mapper.v │ │ │ └── system_top.v │ ├── zcu102 │ │ ├── bd │ │ │ └── prm.tcl │ │ ├── constr │ │ │ └── constr.xdc │ │ ├── mk.tcl │ │ ├── patch │ │ │ └── 0001-patch-for-new-version-of-zcu102.patch │ │ └── rtl │ │ │ ├── addr_mapper.v │ │ │ └── system_top.v │ └── zedboard │ │ ├── bd │ │ └── prm.tcl │ │ ├── constr │ │ └── constr.xdc │ │ ├── mk.tcl │ │ └── rtl │ │ ├── addr_mapper.v │ │ └── system_top.v ├── boot │ ├── .gitignore │ ├── README.md │ ├── bootgen-zynq.bif │ ├── bootgen-zynqmp.bif │ ├── bug-list.md │ └── mk.tcl ├── doc │ ├── lazy_module.md │ ├── openocd-rpc-on-smp.md │ ├── riscv-pard-fpga-how-to.md │ ├── riscv-pard-fpga-old.md │ ├── rocketchip-bus.md │ ├── rocketchip-pcie-ssd-debian.md │ ├── rocketchip_config_detail.md │ ├── rocketchip_linux_kernel_clock.md │ ├── rocketchip_on_pard_details.md │ ├── rocketchip_on_pard_journal_tailored.md │ └── rocketchip_on_pard_simulation.md ├── emu │ ├── Makefile │ ├── gen_bin.sh │ ├── gen_dtb_bin.sh │ ├── gen_nohype_dtb │ ├── mem_init │ ├── py-check.sh │ └── python │ │ ├── .gitignore │ │ ├── common.py │ │ └── emu_wrapper.py ├── lib │ ├── dmi │ │ ├── dmi.xml │ │ └── dmi_rtl.xml │ ├── include │ │ ├── axi.vh │ │ └── dmi.vh │ ├── jtag │ │ ├── axi4_lite_if.v │ │ ├── axi_jtag_v1_0.v │ │ └── jtag_proc.v │ └── util │ │ ├── axi_reg.v │ │ ├── cdma_addr.v │ │ ├── cross_domain.v │ │ ├── leds_mux_controller.v │ │ └── uart_inverter.v ├── openocd_rpc │ ├── .gitignore │ ├── dm_reg.py │ ├── dm_utils.py │ ├── dmcontrol │ ├── dmstatus │ ├── dpc │ ├── get_cp │ ├── get_mem │ ├── halt │ ├── haltsum0 │ ├── log │ ├── openocd.py │ ├── put_mem │ ├── restart │ ├── resume │ ├── scause │ ├── sepc │ ├── set_cp │ ├── show_cache_capacity │ ├── show_traffic │ └── stval ├── pardcore │ ├── Makefile │ ├── bd │ │ └── pardcore.tcl │ └── rtl │ │ └── rocket │ │ └── .gitignore └── scripts │ ├── account.py │ ├── gen.sh │ └── range.py ├── macros └── src │ └── main │ └── scala │ └── ValName.scala ├── origin_rocket_README.md ├── project ├── .gitignore ├── build.properties └── plugins.sbt ├── regression ├── .gitignore └── Makefile ├── riscv-tools.hash ├── sbt-launch.jar ├── scripts ├── .gitignore ├── Makefile ├── RocketSim.cfg ├── RocketSim.py ├── RocketSim32.py ├── RocketSim64.py ├── authors ├── check_cache_trace.py ├── check_comparator_trace.py ├── copyright-file ├── debug_rom │ ├── .gitignore │ ├── Makefile │ ├── debug_rom.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 │ │ ├── emulator.cc │ │ ├── float_fix.cc │ │ ├── remote_bitbang.cc │ │ ├── remote_bitbang.h │ │ └── verilator.h │ └── vsrc │ │ ├── AsyncResetReg.v │ │ ├── ClockDivider2.v │ │ ├── ClockDivider3.v │ │ ├── EICG_wrapper.v │ │ ├── SimDTM.v │ │ ├── SimJTAG.v │ │ ├── TestDriver.v │ │ ├── UARTPrinter.v │ │ └── plusarg_reader.v │ └── scala │ ├── amba │ ├── ahb │ │ ├── Bundles.scala │ │ ├── Nodes.scala │ │ ├── Parameters.scala │ │ ├── Protocol.scala │ │ ├── RegisterRouter.scala │ │ ├── SRAM.scala │ │ ├── Test.scala │ │ ├── ToTL.scala │ │ ├── Xbar.scala │ │ └── package.scala │ ├── apb │ │ ├── Bundles.scala │ │ ├── Nodes.scala │ │ ├── Parameters.scala │ │ ├── Protocol.scala │ │ ├── RegisterRouter.scala │ │ ├── SRAM.scala │ │ ├── Test.scala │ │ ├── Xbar.scala │ │ └── package.scala │ └── axi4 │ │ ├── AsyncCrossing.scala │ │ ├── Buffer.scala │ │ ├── Bundles.scala │ │ ├── CrossingHelper.scala │ │ ├── Deinterleaver.scala │ │ ├── Delayer.scala │ │ ├── Dumper.scala │ │ ├── Filter.scala │ │ ├── Fragmenter.scala │ │ ├── IdIndexer.scala │ │ ├── Nodes.scala │ │ ├── Parameters.scala │ │ ├── Protocol.scala │ │ ├── RegisterRouter.scala │ │ ├── SRAM.scala │ │ ├── Test.scala │ │ ├── ToTL.scala │ │ ├── UserYanker.scala │ │ ├── Xbar.scala │ │ └── package.scala │ ├── config │ └── Config.scala │ ├── debug │ ├── DebugBundles.scala │ └── Stats.scala │ ├── devices │ ├── debug │ │ ├── Custom.scala │ │ ├── DMI.scala │ │ ├── Debug.scala │ │ ├── DebugRomContents.scala │ │ ├── DebugTransport.scala │ │ ├── Periphery.scala │ │ ├── SBA.scala │ │ ├── abstract_commands.scala │ │ └── dm_registers.scala │ └── tilelink │ │ ├── BootROM.scala │ │ ├── BusBlocker.scala │ │ ├── BusBypass.scala │ │ ├── CLINT.scala │ │ ├── CanHaveBuiltInDevices.scala │ │ ├── Deadlock.scala │ │ ├── DevNull.scala │ │ ├── Error.scala │ │ ├── MaskROM.scala │ │ ├── MasterMux.scala │ │ ├── PhysicalFilter.scala │ │ ├── Plic.scala │ │ ├── TestRAM.scala │ │ └── Zero.scala │ ├── diplomacy │ ├── AddressDecoder.scala │ ├── AddressRange.scala │ ├── BundleBridge.scala │ ├── ClockDomain.scala │ ├── Clone.scala │ ├── CloneModule.scala │ ├── DeviceTree.scala │ ├── FixedClockResource.scala │ ├── JSON.scala │ ├── LazyModule.scala │ ├── Nodes.scala │ ├── Parameters.scala │ ├── Resources.scala │ ├── SRAM.scala │ ├── ValName.scala │ └── package.scala │ ├── diplomaticobjectmodel │ ├── DiplomaticObjectModel.scala │ ├── DiplomaticObjectModelUtils.scala │ └── model │ │ ├── ISASpecifications.scala │ │ ├── OMAddressing.scala │ │ ├── OMBase.scala │ │ ├── OMBranchPredictor.scala │ │ ├── OMCLINT.scala │ │ ├── OMCaches.scala │ │ ├── OMCore.scala │ │ ├── OMDebug.scala │ │ ├── OMDevice.scala │ │ ├── OMFPU.scala │ │ ├── OMISA.scala │ │ ├── OMInterrupts.scala │ │ ├── OMMemory.scala │ │ ├── OMMulDiv.scala │ │ ├── OMPLIC.scala │ │ ├── OMPMP.scala │ │ ├── OMPerformanceMonitor.scala │ │ ├── OMRTLModule.scala │ │ ├── OMRegFieldAccessType.scala │ │ ├── OMRegFieldRdAction.scala │ │ ├── OMRegFieldWrType.scala │ │ ├── OMRocketCore.scala │ │ └── OMSpecification.scala │ ├── groundtest │ ├── Configs.scala │ ├── DummyPTW.scala │ ├── Generator.scala │ ├── GroundTestSubsystem.scala │ ├── Package.scala │ ├── Status.scala │ ├── TestHarness.scala │ ├── Tile.scala │ └── TraceGen.scala │ ├── interrupts │ ├── 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 │ ├── l2cache │ ├── SimpleL2.scala │ └── TLSimpleL2.scala │ ├── lvna │ ├── Dirty.scala │ ├── ILA.scala │ ├── LvNAConfigs.scala │ ├── LvNATop.scala │ └── controlplane │ │ ├── ControlPlane.scala │ │ ├── TokenBucket.scala │ │ └── TokenBucketNode.scala │ ├── regmapper │ ├── Annotation.scala │ ├── DescribedReg.scala │ ├── RegField.scala │ ├── RegMapper.scala │ ├── RegisterCrossing.scala │ └── RegisterRouter.scala │ ├── rocket │ ├── ALU.scala │ ├── AMOALU.scala │ ├── BTB.scala │ ├── Breakpoint.scala │ ├── CSR.scala │ ├── Consts.scala │ ├── DCache.scala │ ├── Decode.scala │ ├── Events.scala │ ├── Frontend.scala │ ├── HellaCache.scala │ ├── HellaCacheArbiter.scala │ ├── IBuf.scala │ ├── ICache.scala │ ├── IDecode.scala │ ├── Instructions.scala │ ├── Multiplier.scala │ ├── NBDcache.scala │ ├── PMP.scala │ ├── PTW.scala │ ├── Prefetch.scala │ ├── RVC.scala │ ├── RocketCore.scala │ ├── ScratchpadSlavePort.scala │ ├── SimpleHellaCacheIF.scala │ ├── TLB.scala │ ├── TLBPermissions.scala │ └── package.scala │ ├── scie │ └── SCIE.scala │ ├── sifive-blocks │ ├── LICENSE │ ├── devices │ │ └── uart │ │ │ ├── UART.scala │ │ │ ├── UARTCtrlRegs.scala │ │ │ ├── UARTPeriphery.scala │ │ │ └── UARTPrinter.scala │ ├── util │ │ ├── DeglitchShiftRegister.scala │ │ ├── RegMapFIFO.scala │ │ ├── ResetCatchAndSync.scala │ │ ├── SRLatch.scala │ │ ├── ShiftReg.scala │ │ └── Timer.scala │ └── vsrc │ │ ├── SRLatch.v │ │ └── vc707reset.v │ ├── subsystem │ ├── BaseSubsystem.scala │ ├── Configs.scala │ ├── CrossingWrapper.scala │ ├── FrontBus.scala │ ├── HasTiles.scala │ ├── InterruptBus.scala │ ├── MemoryBus.scala │ ├── PeripheryBus.scala │ ├── Ports.scala │ ├── RTC.scala │ ├── ResetVector.scala │ ├── RocketSubsystem.scala │ └── SystemBus.scala │ ├── system │ ├── Configs.scala │ ├── ExampleRocketSystem.scala │ ├── Generator.scala │ ├── RocketTestSuite.scala │ └── TestHarness.scala │ ├── tile │ ├── BaseTile.scala │ ├── BusErrorUnit.scala │ ├── Core.scala │ ├── CustomCSRs.scala │ ├── FPU.scala │ ├── Interrupts.scala │ ├── L1Cache.scala │ ├── LazyRoCC.scala │ └── RocketTile.scala │ ├── tilelink │ ├── AddressAdjuster.scala │ ├── Arbiter.scala │ ├── AsyncCrossing.scala │ ├── AtomicAutomata.scala │ ├── Atomics.scala │ ├── BankBinder.scala │ ├── Broadcast.scala │ ├── Buffer.scala │ ├── Bundles.scala │ ├── BusWrapper.scala │ ├── CacheCork.scala │ ├── CrossingHelper.scala │ ├── Delayer.scala │ ├── Dumper.scala │ ├── Edges.scala │ ├── ErrorEvaluator.scala │ ├── Example.scala │ ├── FIFOFixer.scala │ ├── Filter.scala │ ├── Fragmenter.scala │ ├── Fuzzer.scala │ ├── HintHandler.scala │ ├── Isolation.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 │ ├── unittest │ ├── Configs.scala │ ├── Generator.scala │ ├── TestGenerator.scala │ ├── TestHarness.scala │ ├── UnitTest.scala │ └── package.scala │ └── util │ ├── Annotations.scala │ ├── Arbiters.scala │ ├── AsyncQueue.scala │ ├── AsyncResetReg.scala │ ├── Broadcaster.scala │ ├── CRC.scala │ ├── CheckOneHot.scala │ ├── ClockDivider.scala │ ├── ClockGate.scala │ ├── CoreMonitor.scala │ ├── Counters.scala │ ├── Crossing.scala │ ├── DescribedSRAM.scala │ ├── ECC.scala │ ├── Frequency.scala │ ├── GeneratorUtils.scala │ ├── GenericParameterizedBundle.scala │ ├── GlobalTimer.scala │ ├── HellaQueue.scala │ ├── HeterogeneousBag.scala │ ├── IDPool.scala │ ├── IdentityModule.scala │ ├── LCG.scala │ ├── LanePositionedQueue.scala │ ├── LatencyPipe.scala │ ├── Misc.scala │ ├── MultiLaneQueue.scala │ ├── MultiPortQueue.scala │ ├── MultiWidthFifo.scala │ ├── MuxLiteral.scala │ ├── PSDTestMode.scala │ ├── PlusArg.scala │ ├── PrefixSum.scala │ ├── Property.scala │ ├── ROMGenerator.scala │ ├── RationalCrossing.scala │ ├── ReduceOthers.scala │ ├── ReorderQueue.scala │ ├── Repeater.scala │ ├── Replacement.scala │ ├── ResetCatchAndSync.scala │ ├── ScatterGather.scala │ ├── SeededRandom.scala │ ├── ShiftQueue.scala │ ├── ShiftReg.scala │ ├── Timer.scala │ └── package.scala └── vsim ├── .gitignore ├── Makefile ├── Makefrag ├── Makefrag-verilog └── vlsi_mem_gen /.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 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | target/ 2 | project/target 3 | *.swp 4 | *~ 5 | .addons-dont-touch 6 | /lib/ 7 | ControlPlanes.v 8 | 9 | # ignore intellij idea projects under src/main/scala 10 | src/main/scala/.idea/ 11 | src/main/scala/build.sbt 12 | src/main/scala/project/ 13 | 14 | .idea/ 15 | boom-ether.err 16 | bootrom/bootrom.txt 17 | emulator/boom-failed.md 18 | emulator/log.txt 19 | emulator/serial6* 20 | fpga/.Xil/ 21 | fpga/bbl.elf.txt 22 | fpga/vivado_*.str 23 | fpga/vmlinux.txt 24 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "hardfloat"] 2 | path = hardfloat 3 | url = https://github.com/ucb-bar/berkeley-hardfloat.git 4 | [submodule "torture"] 5 | path = torture 6 | url = https://github.com/ucb-bar/riscv-torture.git 7 | [submodule "chisel3"] 8 | path = chisel3 9 | url = https://github.com/ucb-bar/chisel3.git 10 | [submodule "firrtl"] 11 | path = firrtl 12 | url = https://github.com/ucb-bar/firrtl.git 13 | [submodule "src/main/scala/boom"] 14 | path = src/main/scala/boom 15 | url = https://github.com/shinezyy/BOOM-inside-LvNA.git 16 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Labeled RISC-V based on Rocketchip 2 | 3 | We build our labeled RISC-V prototype based on rocketchip. 4 | 5 | - [Quick start guide for labeled RISC-V](./fpga/README.md), 6 | - [Original Rocketchip README](./README-rocketchip.md). 7 | -------------------------------------------------------------------------------- /README_LvNA.md: -------------------------------------------------------------------------------- 1 | For a quick start flow about Labeled RISC-V, please refer to [the README.md under `fpga/` directory](fpga/README.md). 2 | -------------------------------------------------------------------------------- /README_TRAVIS.md: -------------------------------------------------------------------------------- 1 | # Travis Notes for Administrators 2 | 3 | Administrators: Are PRs taking > 1 hr to run through Travis? If you look at the Travis logs is it building `riscv-tools`? 4 | 5 | This is because someone committed a PR to `master` which bumped `riscv-tools` and the master cache needs to be updated. 6 | This is the procedure to follow to get things fast again. We don't generally branch updates (e.g. to `master`), just PRs. 7 | 8 | To get the `master` cache good again: 9 | ---------------------------------- 10 | 11 | 1. Wait for the PR that is changing `riscv-tools` to go green. 12 | 2. On Travis, click `More Options -> Caches` on the upper right. 13 | 3. Click `Delete` for the `master` Cache. 14 | 4. Click `More Options->Settings` 15 | 5. On the `General Settings` section, switch the `Build Branch Updates` toggle to `ON`. 16 | 6. Perform the PR's merge to `master`. This will cause the `master` cache to build `riscv-tools`. 17 | 7. Once the merge commit goes green on Travis, switch the `Build Branch Updates` toggle to `OFF`. 18 | 19 | For other PRs which were happening in parallel to the bump of `riscv-tools`: 20 | ---------------------------------------------------------------------------- 21 | 22 | If your PR already has a cache and you want to keep doing development with the old version of `riscv-tools`, no action is needed. 23 | 24 | If you want to merge or rebase your PR on top of `master` with the new version of `riscv-tools`, you should delete your PR branch's local cache. Otherwise it will rebuild the branch cache instead of using `master`'s cache. To do this: 25 | 26 | 1. Wait for the previous steps to go through so that the `master` cache is done. 27 | 2. On Travis, click `More Options -> Caches` on the upper right. 28 | 3. Click `Delete` for your PR branch's cache. 29 | 4. Push updates to the PR as usual, it should download the new `master` cache. 30 | -------------------------------------------------------------------------------- /bootrom/.gitignore: -------------------------------------------------------------------------------- 1 | *.elf 2 | bootrom.img 3 | -------------------------------------------------------------------------------- /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 | riscv64-unknown-elf-objdump -d $@ >bootrom.txt 17 | -------------------------------------------------------------------------------- /bootrom/bootrom.S: -------------------------------------------------------------------------------- 1 | // #define DRAM_BASE 0x80000000 2 | #define DRAM_BASE 0x100000000 3 | 4 | .section .text.start, "ax", @progbits 5 | .globl _start 6 | _start: 7 | // csrwi 0x7c1, 0 // disable chicken bits 8 | li s0, DRAM_BASE 9 | csrr a0, mhartid 10 | la a1, _dtb 11 | 12 | jr s0 13 | 14 | .section .text.hang, "ax", @progbits 15 | .globl _hang 16 | _hang: 17 | // csrwi 0x7c1, 0 // disable chicken bits 18 | csrr a0, mhartid 19 | la a1, _dtb 20 | csrwi mie, 0 21 | 1: 22 | wfi 23 | j 1b 24 | 25 | .section .rodata.dtb, "a", @progbits 26 | .globl _dtb 27 | .align 5, 0 28 | _dtb: 29 | .ascii "DTB goes here" 30 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /emulator/.gitignore: -------------------------------------------------------------------------------- 1 | *~ 2 | *.o 3 | *.a 4 | *.log 5 | output/ 6 | emulator-* 7 | generated-src 8 | generated-src-debug 9 | kernel 10 | kernel.hex 11 | verilator/ 12 | -------------------------------------------------------------------------------- /fpga/.gitignore: -------------------------------------------------------------------------------- 1 | build/ 2 | scripts/*.bit 3 | -------------------------------------------------------------------------------- /fpga/Makefile: -------------------------------------------------------------------------------- 1 | include Makefile.check 2 | 3 | default: project 4 | 5 | # vivado project name 6 | PRJ ?= myproject 7 | PRJ_FULL = $(PRJ)-$(BOARD) 8 | VIVADO_FLAG = -nolog -nojournal -notrace 9 | 10 | #-------------------------------------------------------------------- 11 | # Project building and implementation 12 | #-------------------------------------------------------------------- 13 | 14 | PRJ_ROOT = board/$(BOARD)/build/$(PRJ_FULL) 15 | XPR_FILE = $(PRJ_ROOT)/$(PRJ_FULL).xpr 16 | $(XPR_FILE): 17 | make -C pardcore BOARD=$(BOARD) 18 | vivado $(VIVADO_FLAG) -mode batch -source board/$(BOARD)/mk.tcl -tclargs $(PRJ_FULL) 19 | 20 | project: $(XPR_FILE) 21 | 22 | bootgen: 23 | cd boot && hsi $(VIVADO_FLAG) -source mk.tcl -tclargs $(abspath $(PRJ_ROOT)/$(PRJ_FULL).sdk/system_top.hdf) $(PRJ_FULL) 24 | 25 | vivado: $(XPR_FILE) 26 | vivado $(VIVADO_FLAG) $(XPR_FILE) & 27 | 28 | .PHONY: default project vivado bootgen 29 | 30 | include Makefile.sw 31 | -------------------------------------------------------------------------------- /fpga/Makefile.check: -------------------------------------------------------------------------------- 1 | ifneq ($(MAKECMDGOALS),clean) # ignore check for make clean 2 | 3 | BOARD ?= zcu102 4 | 5 | BOARDS = $(shell ls board/) 6 | 7 | ifeq ($(filter $(BOARDS), $(BOARD)), ) # BOARD must be valid 8 | $(error Invalid BOARD. Supported: $(BOARDS)) 9 | endif 10 | 11 | endif 12 | -------------------------------------------------------------------------------- /fpga/board/sidewinder/constr/constr.xdc: -------------------------------------------------------------------------------- 1 | create_clock -period 10.000 -name pcie_x86_refclk -waveform {0.000 5.000} [get_ports CLK_IN_D_clk_p] 2 | set_property PACKAGE_PIN AB35 [get_ports {CLK_IN_D_clk_n[0]}] 3 | set_property PACKAGE_PIN AB34 [get_ports {CLK_IN_D_clk_p[0]}] -------------------------------------------------------------------------------- /fpga/board/sidewinder/mk.tcl: -------------------------------------------------------------------------------- 1 | set device xczu19eg-ffvc1760-2-i 2 | set board fidus:none:part0:2.0 3 | 4 | set script_dir [file dirname [info script]] 5 | 6 | # Add files for system top 7 | set src_files [list \ 8 | "[file normalize "${script_dir}/rtl/system_top.v"]" \ 9 | "[file normalize "${script_dir}/rtl/addr_mapper.v"]" \ 10 | ] 11 | 12 | # Add files for constraint 13 | set xdc_files [list \ 14 | "[file normalize "${script_dir}/constr/constr.xdc"]" \ 15 | ] 16 | 17 | source ${script_dir}/../common.tcl 18 | -------------------------------------------------------------------------------- /fpga/board/sidewinder/vivado/README.md: -------------------------------------------------------------------------------- 1 | Put the `sidewinder` directory under `/opt/Xilinx/Vivado/2019.1/data/boards/board_parts/` to let vivado find this board. 2 | -------------------------------------------------------------------------------- /fpga/board/sidewinder/vivado/sidewinder/Fidus/2.0/Fidus.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LvNA-system/labeled-RISC-V/f6895abf0a3d6c05fd1b87c9de21d251ffa43887/fpga/board/sidewinder/vivado/sidewinder/Fidus/2.0/Fidus.jpeg -------------------------------------------------------------------------------- /fpga/board/sidewinder/vivado/sidewinder/Fidus/2.0/board.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Fidus Sidewinder Board File Image 6 | 7 | 8 | 9 | 1.0 10 | 11 | 2.0 12 | Fidus Sidewinder 100 Board 13 | 14 | 15 | 16 | 17 | FPGA part on the board 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /fpga/board/ultraZ/constr/constr.xdc: -------------------------------------------------------------------------------- 1 | set_property PACKAGE_PIN F12 [get_ports {led[7]}] 2 | set_property PACKAGE_PIN G12 [get_ports {led[6]}] 3 | set_property PACKAGE_PIN G11 [get_ports {led[5]}] 4 | set_property PACKAGE_PIN H11 [get_ports {led[4]}] 5 | set_property PACKAGE_PIN F10 [get_ports {led[3]}] 6 | set_property PACKAGE_PIN G10 [get_ports {led[2]}] 7 | set_property PACKAGE_PIN H9 [get_ports {led[1]}] 8 | set_property PACKAGE_PIN H10 [get_ports {led[0]}] 9 | 10 | set_property IOSTANDARD LVCMOS18 [get_ports {led[7]}] 11 | set_property IOSTANDARD LVCMOS18 [get_ports {led[6]}] 12 | set_property IOSTANDARD LVCMOS18 [get_ports {led[5]}] 13 | set_property IOSTANDARD LVCMOS18 [get_ports {led[4]}] 14 | set_property IOSTANDARD LVCMOS18 [get_ports {led[3]}] 15 | set_property IOSTANDARD LVCMOS18 [get_ports {led[2]}] 16 | set_property IOSTANDARD LVCMOS18 [get_ports {led[1]}] 17 | set_property IOSTANDARD LVCMOS18 [get_ports {led[0]}] 18 | -------------------------------------------------------------------------------- /fpga/board/ultraZ/mk.tcl: -------------------------------------------------------------------------------- 1 | set device xczu2eg-sfva625-1-e 2 | set board interwiser:none:part0:2.0 3 | 4 | set script_dir [file dirname [info script]] 5 | 6 | # Add files for system top 7 | set src_files [list \ 8 | "[file normalize "${script_dir}/rtl/system_top.v"]" \ 9 | "[file normalize "${script_dir}/rtl/addr_mapper.v"]" \ 10 | ] 11 | 12 | # Add files for constraint 13 | set xdc_files [list \ 14 | "[file normalize "${script_dir}/constr/constr.xdc"]" \ 15 | ] 16 | 17 | source ${script_dir}/../common.tcl 18 | -------------------------------------------------------------------------------- /fpga/board/ultraZ/rtl/addr_mapper.v: -------------------------------------------------------------------------------- 1 | module addr_mapper ( 2 | `axi_slave_if(s_axi, 64, 1), 3 | `axi_master_if(m_axi, 64, 1) 4 | ); 5 | 6 | assign m_axi_awaddr = {4'd0, 2'b01, s_axi_awaddr[29:0]}; 7 | assign m_axi_araddr = {4'd0, 2'b01, s_axi_araddr[29:0]}; 8 | assign m_axi_arburst = s_axi_arburst; 9 | assign m_axi_arcache = s_axi_arcache; 10 | assign m_axi_arid = s_axi_arid ; 11 | // assign m_axi_aruser = s_axi_aruser ; 12 | assign m_axi_arlen = s_axi_arlen ; 13 | assign m_axi_arlock = s_axi_arlock ; 14 | assign m_axi_arprot = s_axi_arprot ; 15 | assign s_axi_arready = m_axi_arready; 16 | assign m_axi_arsize = s_axi_arsize ; 17 | assign m_axi_arvalid = s_axi_arvalid; 18 | assign m_axi_awburst = s_axi_awburst; 19 | assign m_axi_awcache = s_axi_awcache; 20 | assign m_axi_awid = s_axi_awid ; 21 | // assign m_axi_awuser = s_axi_awuser ; 22 | assign m_axi_awlen = s_axi_awlen ; 23 | assign m_axi_awlock = s_axi_awlock ; 24 | assign m_axi_awprot = s_axi_awprot ; 25 | assign s_axi_awready = m_axi_awready; 26 | assign m_axi_awsize = s_axi_awsize ; 27 | assign m_axi_awvalid = s_axi_awvalid; 28 | assign s_axi_bid = m_axi_bid ; 29 | assign m_axi_bready = s_axi_bready ; 30 | assign s_axi_bresp = m_axi_bresp ; 31 | assign s_axi_bvalid = m_axi_bvalid ; 32 | assign s_axi_rdata = m_axi_rdata ; 33 | assign s_axi_rid = m_axi_rid ; 34 | assign s_axi_rlast = m_axi_rlast ; 35 | assign m_axi_rready = s_axi_rready ; 36 | assign s_axi_rresp = m_axi_rresp ; 37 | assign s_axi_rvalid = m_axi_rvalid ; 38 | assign m_axi_wdata = s_axi_wdata ; 39 | assign m_axi_wlast = s_axi_wlast ; 40 | assign s_axi_wready = m_axi_wready ; 41 | assign m_axi_wstrb = s_axi_wstrb ; 42 | assign m_axi_wvalid = s_axi_wvalid ; 43 | assign m_axi_arqos = s_axi_arqos ; 44 | assign m_axi_awqos = s_axi_awqos ; 45 | 46 | endmodule 47 | -------------------------------------------------------------------------------- /fpga/board/ultraZ/rtl/system_top.v: -------------------------------------------------------------------------------- 1 | `include "axi.vh" 2 | 3 | module system_top ( 4 | output [7:0] led 5 | ); 6 | 7 | `axi_wire(AXI_MEM_MAPPED, 64, 1); 8 | `axi_wire(AXI_MEM, 64, 1); 9 | `axilite_wire(AXILITE_MMIO); 10 | `axi_wire(AXI_DMA, 64, 1); 11 | 12 | wire jtag_TCK; 13 | wire jtag_TMS; 14 | wire jtag_TDI; 15 | wire jtag_TDO; 16 | wire jtag_TRST; 17 | 18 | wire pardcore_coreclk; 19 | wire [1:0] pardcore_corerstn; 20 | wire pardcore_uncoreclk; 21 | wire pardcore_uncorerstn; 22 | 23 | wire mm2s_introut; 24 | wire s2mm_introut; 25 | 26 | zynq_soc zynq_soc_i ( 27 | `axi_connect_if(S_AXI_MEM, AXI_MEM_MAPPED), 28 | `axilite_connect_if(S_AXILITE_MMIO, AXILITE_MMIO), 29 | `axi_connect_if_no_id(M_AXI_DMA, AXI_DMA), 30 | 31 | .jtag_TCK(jtag_TCK), 32 | .jtag_TMS(jtag_TMS), 33 | .jtag_TDI(jtag_TDI), 34 | .jtag_TDO(jtag_TDO), 35 | 36 | .led(led[6:0]), 37 | 38 | .mm2s_introut(mm2s_introut), 39 | .s2mm_introut(s2mm_introut), 40 | 41 | .pardcore_coreclk(pardcore_coreclk), 42 | .pardcore_corerstn(pardcore_corerstn), 43 | .pardcore_uncoreclk(pardcore_uncoreclk), 44 | .pardcore_uncorerstn(pardcore_uncorerstn) 45 | ); 46 | 47 | addr_mapper addr_mapper_i( 48 | `axi_connect_if(s_axi, AXI_MEM), 49 | `axi_connect_if(m_axi, AXI_MEM_MAPPED) 50 | ); 51 | 52 | pardcore pardcore_i( 53 | `axi_connect_if(M_AXI_MEM, AXI_MEM), 54 | `axi_connect_if(S_AXI_DMA, AXI_DMA), 55 | `axilite_connect_if(M_AXILITE_MMIO, AXILITE_MMIO), 56 | 57 | .jtag_TCK(jtag_TCK), 58 | .jtag_TMS(jtag_TMS), 59 | .jtag_TDI(jtag_TDI), 60 | .jtag_TDO(jtag_TDO), 61 | .jtag_TRST(~pardcore_corerstn), 62 | 63 | .intr0(mm2s_introut), 64 | .intr1(s2mm_introut), 65 | 66 | .led(led[7]), 67 | 68 | .coreclk(pardcore_coreclk), 69 | .corersts(~pardcore_corerstn), 70 | .uncoreclk(pardcore_uncoreclk), 71 | .uncore_rstn(pardcore_uncorerstn) 72 | ); 73 | 74 | endmodule 75 | -------------------------------------------------------------------------------- /fpga/board/zcu102/constr/constr.xdc: -------------------------------------------------------------------------------- 1 | set_property IOSTANDARD LVCMOS33 [get_ports {led[0]}] 2 | set_property IOSTANDARD LVCMOS33 [get_ports {led[1]}] 3 | set_property IOSTANDARD LVCMOS33 [get_ports {led[2]}] 4 | set_property IOSTANDARD LVCMOS33 [get_ports {led[3]}] 5 | set_property IOSTANDARD LVCMOS33 [get_ports {led[4]}] 6 | set_property IOSTANDARD LVCMOS33 [get_ports {led[5]}] 7 | set_property IOSTANDARD LVCMOS33 [get_ports {led[6]}] 8 | set_property IOSTANDARD LVCMOS33 [get_ports {led[7]}] 9 | 10 | set_property PACKAGE_PIN AG14 [get_ports {led[0]}] 11 | set_property PACKAGE_PIN AF13 [get_ports {led[1]}] 12 | set_property PACKAGE_PIN AE13 [get_ports {led[2]}] 13 | set_property PACKAGE_PIN AJ14 [get_ports {led[3]}] 14 | set_property PACKAGE_PIN AJ15 [get_ports {led[4]}] 15 | set_property PACKAGE_PIN AH13 [get_ports {led[5]}] 16 | set_property PACKAGE_PIN AH14 [get_ports {led[6]}] 17 | set_property PACKAGE_PIN AL12 [get_ports {led[7]}] 18 | -------------------------------------------------------------------------------- /fpga/board/zcu102/mk.tcl: -------------------------------------------------------------------------------- 1 | set device xczu9eg-ffvb1156-2-e 2 | set board xilinx.com:zcu102:part0:3.1 3 | 4 | set script_dir [file dirname [info script]] 5 | 6 | # Add files for system top 7 | set src_files [list \ 8 | "[file normalize "${script_dir}/rtl/system_top.v"]" \ 9 | "[file normalize "${script_dir}/rtl/addr_mapper.v"]" \ 10 | ] 11 | 12 | # Add files for constraint 13 | set xdc_files [list \ 14 | "[file normalize "${script_dir}/constr/constr.xdc"]" \ 15 | ] 16 | 17 | source ${script_dir}/../common.tcl 18 | -------------------------------------------------------------------------------- /fpga/board/zcu102/patch/0001-patch-for-new-version-of-zcu102.patch: -------------------------------------------------------------------------------- 1 | From d3211ce94e3c3e477991f1dd1a38e1399fbf50fc Mon Sep 17 00:00:00 2001 2 | From: chuanqizhang 3 | Date: Wed, 14 Apr 2021 12:08:12 +0800 4 | Subject: [PATCH] patch for new version of zcu102 5 | 6 | --- 7 | fpga/board/zcu102/bd/prm.tcl | 2 +- 8 | fpga/board/zcu102/mk.tcl | 2 +- 9 | 2 files changed, 2 insertions(+), 2 deletions(-) 10 | 11 | diff --git a/fpga/board/zcu102/bd/prm.tcl b/fpga/board/zcu102/bd/prm.tcl 12 | index b8c336a5..d562fe53 100644 13 | --- a/fpga/board/zcu102/bd/prm.tcl 14 | +++ b/fpga/board/zcu102/bd/prm.tcl 15 | @@ -924,7 +924,7 @@ proc create_root_design { parentCell } { 16 | CONFIG.PSU_DDR_RAM_HIGHADDR {0xFFFFFFFF} \ 17 | CONFIG.PSU_DDR_RAM_HIGHADDR_OFFSET {0x800000000} \ 18 | CONFIG.PSU_DDR_RAM_LOWADDR_OFFSET {0x80000000} \ 19 | - CONFIG.PSU_DYNAMIC_DDR_CONFIG_EN {0} \ 20 | + CONFIG.PSU_DYNAMIC_DDR_CONFIG_EN {1} \ 21 | CONFIG.PSU_MIO_0_DIRECTION {inout} \ 22 | CONFIG.PSU_MIO_0_INPUT_TYPE {schmitt} \ 23 | CONFIG.PSU_MIO_10_DIRECTION {inout} \ 24 | diff --git a/fpga/board/zcu102/mk.tcl b/fpga/board/zcu102/mk.tcl 25 | index 5edfde8f..22af30d4 100644 26 | --- a/fpga/board/zcu102/mk.tcl 27 | +++ b/fpga/board/zcu102/mk.tcl 28 | @@ -1,5 +1,5 @@ 29 | set device xczu9eg-ffvb1156-2-e 30 | -set board xilinx.com:zcu102:part0:3.1 31 | +set board xilinx.com:zcu102:part0:3.3 32 | 33 | set script_dir [file dirname [info script]] 34 | 35 | -- 36 | 2.20.1 37 | 38 | -------------------------------------------------------------------------------- /fpga/board/zedboard/constr/constr.xdc: -------------------------------------------------------------------------------- 1 | set_property IOSTANDARD LVCMOS33 [get_ports {led[0]}] 2 | set_property IOSTANDARD LVCMOS33 [get_ports {led[1]}] 3 | set_property IOSTANDARD LVCMOS33 [get_ports {led[2]}] 4 | set_property IOSTANDARD LVCMOS33 [get_ports {led[3]}] 5 | set_property IOSTANDARD LVCMOS33 [get_ports {led[4]}] 6 | set_property IOSTANDARD LVCMOS33 [get_ports {led[5]}] 7 | set_property IOSTANDARD LVCMOS33 [get_ports {led[6]}] 8 | set_property IOSTANDARD LVCMOS33 [get_ports {led[7]}] 9 | 10 | set_property PACKAGE_PIN T22 [get_ports {led[0]}] 11 | set_property PACKAGE_PIN T21 [get_ports {led[1]}] 12 | set_property PACKAGE_PIN U22 [get_ports {led[2]}] 13 | set_property PACKAGE_PIN U21 [get_ports {led[3]}] 14 | set_property PACKAGE_PIN V22 [get_ports {led[4]}] 15 | set_property PACKAGE_PIN W22 [get_ports {led[5]}] 16 | set_property PACKAGE_PIN U19 [get_ports {led[6]}] 17 | set_property PACKAGE_PIN U14 [get_ports {led[7]}] 18 | 19 | -------------------------------------------------------------------------------- /fpga/board/zedboard/mk.tcl: -------------------------------------------------------------------------------- 1 | set device xc7z020-1-clg484 2 | set board em.avnet.com:zed:part0:1.3 3 | 4 | set script_dir [file dirname [info script]] 5 | 6 | # Add files for system top 7 | set src_files [list \ 8 | "[file normalize "${script_dir}/rtl/system_top.v"]" \ 9 | "[file normalize "${script_dir}/rtl/addr_mapper.v"]" \ 10 | ] 11 | 12 | # Add files for constraint 13 | set xdc_files [list \ 14 | "[file normalize "${script_dir}/constr/constr.xdc"]" \ 15 | ] 16 | 17 | source ${script_dir}/../common.tcl 18 | -------------------------------------------------------------------------------- /fpga/boot/.gitignore: -------------------------------------------------------------------------------- 1 | build/ 2 | -------------------------------------------------------------------------------- /fpga/boot/bootgen-zynq.bif: -------------------------------------------------------------------------------- 1 | the_ROM_image: 2 | { 3 | [bootloader] build/zynq/fsbl.elf 4 | // build/zynq/system_top.bit 5 | build/zynq/u-boot.elf 6 | } 7 | -------------------------------------------------------------------------------- /fpga/boot/bootgen-zynqmp.bif: -------------------------------------------------------------------------------- 1 | the_ROM_image: 2 | { 3 | [fsbl_config] a53_x64 4 | [bootloader] build/zynqmp/fsbl.elf 5 | [pmufw_image] build/zynqmp/pmufw.elf 6 | // [destination_device=pl] build/zynqmp/system_top.bit 7 | [destination_cpu=a53-0, exception_level=el-3,trustzone] build/zynqmp/bl31.elf 8 | [destination_cpu=a53-0, exception_level=el-2] build/zynqmp/u-boot.elf 9 | } 10 | -------------------------------------------------------------------------------- /fpga/boot/bug-list.md: -------------------------------------------------------------------------------- 1 | 2 | ## sidewinder 3 | 4 | To make the SD card work, do the followings 5 | * use a class10 SD card 6 | * `fsbl/psu_init.c`: search for `IOU_SLCR_BANK1_CTRL5_OFFSET`, change `0x2000FFFU` to `0x3FFFFFFU` (already done inside `mk.tcl`) 7 | * add "disable-wp;" property to the node of "sdhci@ff170000" in device tree 8 | 9 | * remove gem3.phy node 10 | 11 | ## ultraZ 12 | 13 | To make the SD card work, do the followings 14 | * should use 2016.4 dts 15 | * add "no-1-8-v;" property to the node of "sdhci@ff170000" in device tree 16 | * modify gem3.phyc.reg to <0x5> 17 | 18 | ## u-boot 19 | 20 | define marco `CONFIG_ENV_OVERWRITE` in `u-boot-xlnx/include/configs/xilinx-zynqmp.h` to make `ethaddr` environment variable writable 21 | -------------------------------------------------------------------------------- /fpga/doc/riscv-pard-fpga-how-to.md: -------------------------------------------------------------------------------- 1 | # PARD on FPGA 2 | 3 | 下面描述从chisel到上板运行的全流程。 4 | 5 | ## 编译 6 | 7 | 8 | 9 | 首先我们这里包含了三个目标对象: 10 | vivado工程文件、由chisel生成的verilog、编译生成的bbl。 11 | 由于我们这里使用了Makefile调用tcl,tcl调用Makefile的方式,并没有正确地处理好make及clean时的依赖关系。导致在更新某一部分之后,无法正确地检查依赖,增量编译;clean时也无法正确clean。 12 | 直接生成三者使用如下命令: 13 | ``` 14 | make BOARD=zedboard 15 | ``` 16 | 17 | 当某一部分发生变化之后,增量编译及单独清理一个目标,命令如下: 18 | 19 | |目标对象|生成|清理方式| 20 | |-----|-------|-----------------| 21 | |vivado工程 | make BOARD=zedboard | make clean | 22 | |bbl | make bbl -j32 | make sw-clean -j32 | 23 | |generated verilog | make -C pardcore BOARD=zedboard| make -C pardcore BOARD=zedboard clean | 24 | 25 | 上述编译完成之后,得到的是一个vivado project以及bbl.bin文件。 26 | 27 | 接下来,我们打开vivado工程,单击refresh module。再单击generatebitstream。经过漫长的等待后,我们得到了bitstream文件system_top.bit。 28 | 29 | ## 运行 30 | 31 | 步骤太多,我都不知道该怎么分步了。 32 | 33 | 将板子开关打开,上电。 34 | 35 | ssh上123服务器(10.30.6.123) 36 | ``` 37 | ssh liuzhigang@10.30.6.123 38 | ``` 39 | 40 | 打开arm核的串口 41 | ``` 42 | minicom -D /dev/ttyACM0 43 | ``` 44 | 45 | 烧板子及启动arm核 46 | 将刚编好的bitstream文件拷贝到123的pard目录下,拷贝时请这样用如下命令: 47 | ``` 48 | scp system_top.bit liuzhigang@10.30.6.123:~ 49 | ``` 50 | 注意:后面的":~"不能少,不然会拷贝到本机上。 51 | 52 | 运行xsdb 53 | 输入`source noop.tcl`。则arm核启动。 54 | 55 | 切换到arm的minicom窗口,窗口提示符为:zynq-uboot> 56 | 输入bootm 0x3000000 - 0x2a00000,则arm核开始启动Linux kernel。 57 | 如果莫名奇妙地挂住,请重新`source noop.tcl`。 58 | 59 | 启动linux核之后,提示符为:`debian-airbook login:`,则说明成功启动linux。 60 | 61 | 用户名密码均为root,登录进去。 62 | 63 | 让zedboard上的linux获取ip地址 64 | ``` 65 | dhclient eth0 66 | ``` 67 | 68 | 查看arm linux的ip地址 69 | ``` 70 | ifconfig 71 | ``` 72 | 73 | 进入arm linux的pard目录下,从eda上将新编译的bbl.bin 74 | scp过来(实际上是scp到了arm核用的sd卡上),将runme.sh更改,保证a.out后面跟的是刚传上去的bbl文件。 75 | 76 | 打开FPGA上rocket核的串口 77 | 在123服务器上,新开一个窗口,ssh到arm linux上,运行`minicom -D /dev/ttyUL1`。 78 | 如果显示locked,则用`ps aux | grep "minicom"`来看一下在运行的minicom进程,并杀死。 79 | 80 | 启动rocket核 81 | 切换到arm linux上,运行bash runme.sh,在minicom上即可看到riscv linux的输出。 82 | 83 | 84 | 重新烧板子时记得先把arm上的debian给poweroff,不要直接烧,直接运行bootm,因为arm上的debian需要正常关机以保证sd卡上的东西不会被写坏。 85 | 86 | 不用了,记得把zync给关机。 87 | -------------------------------------------------------------------------------- /fpga/doc/rocketchip-bus.md: -------------------------------------------------------------------------------- 1 | 2 | 系统中有不少总线, 本文档对这些总线的功能和结构进行简单梳理. 3 | 可以将这些总线想象为crossbar, 其in和out分别连接其它模块. 4 | 5 | ## ibus 6 | 7 | Interrupt Bus, 可以认为是中断网络. 8 | * in 9 | * external interrupts (async) 10 | * sifive-blocks中的uart中断 (sync) 11 | * out 12 | * plic 13 | 14 | ## sbus 15 | 16 | System Bus, 是连接其它所有总线的总线. 17 | * in 18 | * fbus 19 | * ICache和DCache的masterNode 20 | * out 21 | * cbus 22 | * coherence manager的in, 最终连到mbus 23 | * 各个mmio channel, 它们会转换成MasterAXI4MMIO端口, 从rocketchip的顶层出去 24 | 25 | ## fbus 26 | 27 | Front Bus, 不清楚为何采用这个命名. 28 | * in 29 | * Debug Module 30 | * rocketchip的SlaveAXI4端口 31 | * out 32 | * sbus 33 | 34 | ## mbus 35 | 36 | Memory Bus, 是连接各个memory channel的总线. 37 | * in 38 | * coherence manager的out 39 | * out 40 | * 各个memory channel, 它们会转换成MasterAXI4Mem端口, 从rocketchip的顶层出去 41 | 42 | ## cbus 43 | 44 | Control Bus, 是连接内部MMIO设备的总线. 45 | 在2016年9月21日5bb575的commit中从internal MMIO network改名为cbus. 46 | * in 47 | * sbus 48 | * out 49 | * pbus 50 | * error device 51 | * controlplane 52 | * plic 53 | * clint 54 | * bootrom 55 | * debug module 56 | * bus blocker, 最终连到ICache.slaveNode和dtim.slavePort, 但我们生成的verilog代码里面好像没有bus blocker相关的代码, 暂时不清楚为什么cbus要连到ICache和dtim 57 | 58 | ## pbus 59 | 60 | Periphery Bus, 是连接外部MMIO设备的总线. 61 | 在2016年9月21日5bb575的commit中从external MMIO network改名为pbus. 62 | * in 63 | * cbus 64 | * out 65 | * 连接的设备例子有: sifive-blocks中的uart 66 | -------------------------------------------------------------------------------- /fpga/doc/rocketchip_config_detail.md: -------------------------------------------------------------------------------- 1 | # 对 `Config` 类的理解 2 | `config` 模块的设计需求是: 3 | 4 | 1. 通过 `Parameters(Key)` 获得 Key 所对应的数据; 5 | 2. 通过 `++` 操作将多份配置合并。 6 | 7 | `PartialParameters` 是执行搜索操作的最小单位。 8 | 只有它持有偏函数,如果没有找到需要的字段,则进一步去 `tail` 里寻找。 9 | 10 | `View` 类只提供搜索语义,参数集合间的拓扑信息由其子类 `Parameters` 维护。 11 | `Parameters` 类通过 `chain` 方法同时描述搜索和拓扑语义。`find` 成为了顶级的 `chain`. 12 | 13 | 偏函数本身是不能被合并的,所以只能通过链表将各个持有偏函数的 `PartialParameters` 链接起来。 14 | 这就是 `ChainParameters` 的作用。 15 | 任意两个 `Parameters` 类型的实例,都可以通过 `++` 操作变成一颗以 `ChainParameters` 为根的二叉树。 16 | 17 | 当 `chain` 操作执行到 `ChainParameters` 实例时,它有一个 `tail` 参数,用于自己以及子女都搜索失败时继续搜索。 18 | 那么,很自然地,先递归搜索左子女,然后递归搜索右子女,最后递归搜索 `tail`. 19 | 但是,作者希望左子女搜索完后自动搜索右子女,右子女搜索完后自动搜索 `tail`, 20 | 让 `ChainParameters` 执行一个函数调用后就当甩手掌柜。 21 | 此时自然不能直接把右子女直接当做左子女的 `tail`, 否则根节点自己的 `tail` 信息就丢失了。 22 | 而且传进去的 `tail` 是 `View` 实例,只提供搜索语义。 23 | 迭代语义是 `Parameters` 派生系的私货。 24 | 于是 `ChainView` 出现了。它将右节点和 `tail` 结合成一颗新树,先调用右节点的 `chain`, 25 | 让右节点把父节点的 `tail` 当做自己的 `tail`, 然后让自己成为左节点的 `tail`, 26 | 这样一切都自动串联了。 27 | 28 | 然后需要一个统一的容器抽象 `PartialParameters` 和 `ChainParameters`, 29 | 不过为什么要用一个新的类 `Config` 而不是直接用 `Parameters` 呢? 30 | `Config` 以形同的类名,提供不同构造接口的方式使代码统一化。 31 | 不过感觉 `Parameters` 类自己也提供两种构造接口不就行了? 32 | 33 | -------------------------------------------------------------------------------- /fpga/doc/rocketchip_linux_kernel_clock.md: -------------------------------------------------------------------------------- 1 | # RISCV-Linux中的时钟源的问题。 2 | 3 | 在linux kernel中时钟是叫时钟源(clock source)。现代的系统上,有很多不同的时钟源,他们性质,包括访问的latency,精确度各不相同,在内核中的作用也各不相同。在内核中,内核需要自己维护时间,这个时间当然是越精确越好,最好是直接从RTC读,但是由于从RTC读非常慢,所以内核只是在启动的时候,把自己的时间根据RTC校准,然后再根据timer interrupt来维护时间。 4 | 5 | 所以我们在看riscv-linux代码关于时间相关的问题时,也要考虑两个问题,wall clock是从哪里来的,timer interrupt又是怎么来的。 6 | 7 | 根据riscv-spec的定义,CSR中有mtime寄存器,是wall clock,但是具体的单位需要环境来指定。另外,有一些counter,可以设置成当mtime寄存器大于counter值时,触发时钟中断。在riscv-kernel中,获取wall clock是要通过rdtime指令来读取mtime寄存器,设置中断就是通过写入time counter。 8 | 9 | 但是在看rocketchip的代码时,我们会看到HasRTCModuleImp这个东西,会以为RTC是一个单独的定时设备,搞不清RTC和上述两种计时工具的关系。但实际上这个RTC仅仅是一个简单的计数器,负责驱动mtime寄存器的更新。 10 | 11 | mtime以及counter都是CSR寄存器,但是他们不是在CSR模块中实现的,他们是在Clint中实现的,Clint是coreplex local interrupter的缩写。 12 | 13 | HasRTCModuleImp实例化了一个计数器,并连接到Clint中,驱动mtime的更新,compare counter以及raise timer interrupt是在Clint中完成的。 14 | 15 | 接下来还要考虑wall clock的单位的问题,wall clock的单位在rocketchip代码中是通过DTSTimebase来指定的,这个决定了RTC模块以多高的频率更新mtime。这个配置最终会进入DTB中,内核在启动时可以查询到这个参数。 16 | -------------------------------------------------------------------------------- /fpga/doc/rocketchip_on_pard_details.md: -------------------------------------------------------------------------------- 1 | ## 为什么既有 AXI Interconnect 又有 AXI Crossbar 2 | 3 | AXI Interconnect 的地址映射信息在专门的 Address Editor 里,是给当前 block design 做路由的。 4 | 而 AXI Crossbar 则是在 IP 核设定中指定地址映射进行路由的。 5 | 6 | 为什么要有这两种划分,为什么在两种在工程里同时出现?这是因为工程中有多个地址映射域。 7 | 一个是 PRM, 另一个是 ldom, 这两个是隔离的,视角不同,所以不能只使用一个全局的 AXI Interconnect. 8 | 9 | ## Rocket Chip 是如何输出字符的? 10 | 11 | ### Hart 是如何访问自己对应的 UART 设备的? 12 | 13 | `PARDSimTop` 有 UART 接口,模拟器直接提供 UART 设备; 而 `PARDFPGATop` 则直接通过 MMIO 将串口输出送给 PRM. 14 | 15 | 在 FPGA 配置的 Rocket Chip 的 Device Tree 里, MMIO 的内存映射地址为 0x60000000 ~ 0x7fffffff. 再往上就是常规代码数据的地址空间了。 16 | 17 | 在 BBL 阶段,核心会查询 DTB 找到 UART 的相关描述,设置 MMIO 的基地址。 之后,出于 NoHype 的定制需求,UART 的内存映射基地址会以 0x10000B 为单位按 hartid 进行偏移。 最后,每个 hart 与 UART 地址的对应关系如下: 18 | 19 | | HART ID | UART BASE ADDR | 20 | | ------- | -------------- | 21 | | 0 | `0x60000000` | 22 | | 1 | `0x60010000` | 23 | | ... | ... | 24 | 25 | 不同 hart 向自己对应的 UART 内存映射空间发送数据时,都从 Rocket Chip 的同一个 MMIO 端口送出。 之后,会经过一个 AXI Crossbar. 在 Crossbar 中,会根据基地址的不同,路由到对应的 UART 总线上。 26 | 27 | ### 为什么进入 riscv-linux 后也能继续隔离 UART 地址空间? 28 | 29 | UART 地址空间的隔离在 BBL 阶段完成后,使用这一信息的代码驻留于 machine mode 的代码区。 操作系统内核(riscv-linux)处于 supervisor mode, 它使用 ecall(environment call) 陷入 machine mode, 以类似系统调用的方式执行 UART 相关的操作。 从 supervisor mode 陷入 machine mode 使用的是 9 号中断,在 BBL 里只有这个位置被设置成了 `mcall_trap`. 30 | 31 | ## DMA 传输镜像是如何工作的? 32 | 33 | [yzh 的文档](http://10.30.7.141/pard/riscv_pard_fpga/issues/33) 34 | 35 | SG 是 Scatter Gather 的缩写,是用来自动维护多个传输的模块,可以减少 CPU 用于控制 DMA 的时间。 36 | 37 | DMA 从 PRM 的内存取数据,通过 AXI4 总线将数据发送给 rocket chip. 38 | 在 rocket chip 里,这条总线通往 l2 frontside bus. 39 | 40 | 之后可能有这样两种情况: 41 | 42 | 1. 直接写到 cache 里,发生替换后写回到 rocket chip 的内存中,走内存控制平面做内存隔离; 43 | 2. 绕过核心,直接把请求转发给访存端口,走内存控制平面写到内存里。 44 | -------------------------------------------------------------------------------- /fpga/doc/rocketchip_on_pard_simulation.md: -------------------------------------------------------------------------------- 1 | ## 如何运行模拟 2 | 3 | 1. 进入 `riscv_fpga_pard/fpga/emulator` 执行 `make run-emu`最终生成的可执行文件是build/emu,输出到串口的内容在serial1000或者serial2000中。在运行hello时,可能输出的串口中内容有两份,这是正常的,因为有两个核,他们都在运行hello,且都输出到了串口中。 4 | 2. 在修改之后,建议先运行AM里面的hello程序。再运行bbl。运行的程序需要被objcopy成bin文件,并dump成bin.txt放到build目录下。 5 | 这个过程建议你看一下Makefile,手动hack一下。在生成bbl时要注意,由于busybox太大了,而我们仿真的ram太小了,所以需要把程序改成hello,记得改一改initramfs.txt以及若干文件。 6 | 3. 我们这个加载程序不是用的rocket原有的dmi接口,而是直接用的readmemh,把bin.txt给copy到仿真出来的内存中。readmemh是在sram init verilog中。这个verilog是有某个python文件生成的。 7 | -------------------------------------------------------------------------------- /fpga/emu/gen_bin.sh: -------------------------------------------------------------------------------- 1 | # $1 - bin file 2 | # $2 - bin text file 3 | /bin/echo -e "\033[1;31mremember to create a link from the target bin file to 'mem.bin' under build/ before calling this script\033[0m" 4 | hexdump -ve '2/ "%08x " "\n"' $1 | awk '{print $2$1}' > $2 5 | -------------------------------------------------------------------------------- /fpga/emu/gen_dtb_bin.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | BUILD_DIR=$1 4 | 5 | for i in $(ls $1/c*.dtb) 6 | do 7 | sh gen_bin.sh $i $i.txt 8 | done 9 | -------------------------------------------------------------------------------- /fpga/emu/py-check.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | if ! which python3 4 | then 5 | echo python3 not found, please input password to allow apt-get to go forward 6 | sudo apt-get install -y python3 7 | else 8 | echo python3 installed 9 | fi 10 | 11 | if ! which pip3 12 | then 13 | echo python3-pip not found, please input password to allow apt-get to go forward 14 | sudo apt-get install -y python3-pip 15 | else 16 | echo python-pip installed 17 | fi 18 | 19 | if ! python3 -c 'import pyfdt' 2> /dev/null 20 | then 21 | echo pyfdt package not found, please input password to allow pip3 to go forward 22 | sudo -H pip3 install pyfdt 23 | else 24 | echo python module pyfdt installed 25 | fi 26 | -------------------------------------------------------------------------------- /fpga/emu/python/.gitignore: -------------------------------------------------------------------------------- 1 | ts 2 | __pycache__ 3 | -------------------------------------------------------------------------------- /fpga/lib/dmi/dmi.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | riscv 4 | rocket 5 | dmi 6 | 1.0 7 | false 8 | false 9 | 1 10 | 1 11 | debug module interface 12 | 13 | 14 | DMI 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /fpga/lib/util/cdma_addr.v: -------------------------------------------------------------------------------- 1 | //`include "../include/axi.vh" 2 | 3 | module cdma_addr( 4 | `axi_slave_if(s_axi, 64, 4), 5 | `axi_master_if(m_axi, 64, 4) 6 | ); 7 | 8 | assign m_axi_awaddr = {1'b1, s_axi_awaddr[30:0]}; 9 | assign m_axi_araddr = {1'b1, s_axi_araddr[30:0]}; 10 | assign m_axi_arburst = s_axi_arburst; 11 | assign m_axi_arcache = s_axi_arcache; 12 | assign m_axi_arid = s_axi_arid ; 13 | assign m_axi_aruser = s_axi_aruser ; 14 | assign m_axi_arlen = s_axi_arlen ; 15 | assign m_axi_arlock = s_axi_arlock ; 16 | assign m_axi_arprot = s_axi_arprot ; 17 | assign s_axi_arready = m_axi_arready; 18 | assign m_axi_arsize = s_axi_arsize ; 19 | assign m_axi_arvalid = s_axi_arvalid; 20 | assign m_axi_awburst = s_axi_awburst; 21 | assign m_axi_awcache = s_axi_awcache; 22 | assign m_axi_awid = s_axi_awid ; 23 | assign m_axi_awuser = s_axi_awuser ; 24 | assign m_axi_awlen = s_axi_awlen ; 25 | assign m_axi_awlock = s_axi_awlock ; 26 | assign m_axi_awprot = s_axi_awprot ; 27 | assign s_axi_awready = m_axi_awready; 28 | assign m_axi_awsize = s_axi_awsize ; 29 | assign m_axi_awvalid = s_axi_awvalid; 30 | assign s_axi_bid = m_axi_bid ; 31 | assign m_axi_bready = s_axi_bready ; 32 | assign s_axi_bresp = m_axi_bresp ; 33 | assign s_axi_bvalid = m_axi_bvalid ; 34 | assign s_axi_rdata = m_axi_rdata ; 35 | assign s_axi_rid = m_axi_rid ; 36 | assign s_axi_rlast = m_axi_rlast ; 37 | assign m_axi_rready = s_axi_rready ; 38 | assign s_axi_rresp = m_axi_rresp ; 39 | assign s_axi_rvalid = m_axi_rvalid ; 40 | assign m_axi_wdata = s_axi_wdata ; 41 | assign m_axi_wlast = s_axi_wlast ; 42 | assign s_axi_wready = m_axi_wready ; 43 | assign m_axi_wstrb = s_axi_wstrb ; 44 | assign m_axi_wvalid = s_axi_wvalid ; 45 | assign m_axi_arqos = s_axi_arqos ; 46 | assign m_axi_awqos = s_axi_awqos ; 47 | 48 | endmodule 49 | -------------------------------------------------------------------------------- /fpga/lib/util/uart_inverter.v: -------------------------------------------------------------------------------- 1 | module uart_inverter( 2 | input tx_dest, 3 | input tx_src, 4 | output rx_src, 5 | output rx_dest 6 | ); 7 | assign rx_src = tx_dest; 8 | assign rx_dest = tx_src; 9 | 10 | endmodule 11 | -------------------------------------------------------------------------------- /fpga/openocd_rpc/.gitignore: -------------------------------------------------------------------------------- 1 | *.pyc 2 | __pycache__ 3 | -------------------------------------------------------------------------------- /fpga/openocd_rpc/dm_utils.py: -------------------------------------------------------------------------------- 1 | from ctypes import * 2 | from dm_reg import * 3 | 4 | def print_fields(dm_reg): 5 | names = [f[0] for f in dm_reg.reg._fields_ if f[0]] 6 | align = len(max(names, key=len)) 7 | for name in reversed(names): 8 | aligned_name = name.ljust(align, ' ') 9 | value = hex(int(getattr(dm_reg, name))) 10 | print(aligned_name + ': ' + value) 11 | 12 | def set_reg(dm_reg, hex_str): 13 | dm_reg.bits = int(hex_str, 16) 14 | -------------------------------------------------------------------------------- /fpga/openocd_rpc/dmcontrol: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | import socket 3 | import itertools 4 | import sys 5 | 6 | from dm_reg import * 7 | from dm_utils import * 8 | from openocd import * 9 | 10 | if __name__ == "__main__": 11 | with OpenOcd(verbose=False) as ocd: 12 | ocd.dmi_read_fields(dmcontrol) 13 | -------------------------------------------------------------------------------- /fpga/openocd_rpc/dmstatus: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | import socket 3 | import itertools 4 | import sys 5 | 6 | from dm_reg import * 7 | from dm_utils import * 8 | from openocd import * 9 | 10 | if __name__ == "__main__": 11 | with OpenOcd(verbose=False) as ocd: 12 | ocd.dmi_read_fields(dmstatus) 13 | -------------------------------------------------------------------------------- /fpga/openocd_rpc/dpc: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | import socket 3 | import itertools 4 | import sys 5 | 6 | from dm_reg import * 7 | from dm_utils import * 8 | from openocd import * 9 | 10 | if __name__ == "__main__": 11 | asm = [ 12 | 0x7b1022f3, # csrr t0, dpc 13 | 0x00100073 # ebreak 14 | ] 15 | progbuf_cmds = [(i + 0x20, data) for i, data in enumerate(asm)] 16 | with OpenOcd() as ocd: 17 | # Progbuf 18 | for reg, data in progbuf_cmds: 19 | ocd.send("riscv dmi_write {} {}".format(reg, data)) 20 | # Access Register 21 | ocd.send("riscv dmi_write 0x17 0x361001") # regno = sp, postexec, transfer, 64-bit 22 | ocd.send("riscv dmi_write 0x16 0xffffffff") 23 | abstractcs = ocd.send("riscv dmi_read 0x16") 24 | if abstractcs != "0x10000002": 25 | print("Exec error: abstracts " + abstractcs) 26 | ocd.send("riscv dmi_write 0x17 0x361005") # regno = t0, postexec, transfer, 64-bit 27 | dm_data0 = ocd.send("riscv dmi_read 0x4") 28 | dm_data1 = ocd.send("riscv dmi_read 0x5") 29 | print("data0: {}, data1: {}".format(dm_data0, dm_data1)) 30 | -------------------------------------------------------------------------------- /fpga/openocd_rpc/get_cp: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | import socket 3 | import itertools 4 | import sys 5 | 6 | from dm_reg import * 7 | from dm_utils import * 8 | from openocd import * 9 | 10 | # set_cp (in dec) [property]... 11 | # property: waymask bkt_freq bkt_size bkt_inc traffic l2_capacity 12 | VERBOSE = False 13 | 14 | DSID = 0x41 15 | DSID_SEL = 0x42 16 | DSID_COUNT = 0x43 17 | MEM_BASE_LO = 0x44 18 | MEM_BASE_HI = 0x45 19 | MEM_MASK_LO = 0x46 20 | MEM_MASK_HI = 0x47 21 | BUCKET_FREQ = 0x48 22 | BUCKET_SIZE = 0x49 23 | BUCKET_INC = 0x4a 24 | TRAFFIC = 0x4b 25 | WAYMASK = 0x4c 26 | L2_CAPACITY = 0x4d 27 | 28 | CP = { 29 | 'bkt_freq': BUCKET_FREQ, 30 | 'bkt_size': BUCKET_SIZE, 31 | 'bkt_inc' : BUCKET_INC, 32 | 'traffic' : TRAFFIC, 33 | 'l2_capacity' : L2_CAPACITY, 34 | 'waymask' : WAYMASK 35 | } 36 | 37 | if __name__ == "__main__": 38 | if len(sys.argv) == 1: 39 | print("get_cp.py [] ...") 40 | print("properties:") 41 | print(CP.keys()) 42 | sys.exit(0) 43 | 44 | if len(sys.argv) == 2: 45 | queries = CP.keys() 46 | else: 47 | queries = sys.argv[2:] 48 | 49 | hartid = int(sys.argv[1]) 50 | with OpenOcd(verbose=VERBOSE) as ocd: 51 | ocd.dmi_write(DSID_SEL, hartid) 52 | for query in queries: 53 | addr = CP[query] 54 | if not addr: 55 | print("Invalid control plane property: {}".format(query)) 56 | continue 57 | resp = ocd.dmi_read(addr) 58 | print(query + ": " + resp) 59 | -------------------------------------------------------------------------------- /fpga/openocd_rpc/get_mem: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | import socket 3 | import itertools 4 | import sys 5 | 6 | from dm_reg import * 7 | from dm_utils import * 8 | from openocd import * 9 | 10 | def check_busy(ocd): 11 | sbcs.bits = int(ocd.dmi_read(sbcs.addr), 16) 12 | return sbcs.sbbusy == 1 13 | 14 | if __name__ == "__main__": 15 | addr = int(sys.argv[1], 16) 16 | with OpenOcd(verbose=False) as ocd: 17 | sbcs.bits = int(ocd.dmi_read(sbcs.addr), 16) 18 | print_fields(sbcs) 19 | 20 | sbcs.sbaccess = 2 # 32-bit 21 | sbcs.sbreadonaddr = 1 22 | sbaddress0.bits = addr & 0xffffffff 23 | sbaddress1.bits = addr >> 32 24 | 25 | ocd.dmi_write(sbcs.addr, sbcs.bits) 26 | ocd.dmi_write(sbaddress1.addr, sbaddress1.bits) 27 | ocd.dmi_write(sbaddress0.addr, sbaddress0.bits) 28 | 29 | while check_busy(ocd): 30 | print("waiting") 31 | pass 32 | 33 | if sbcs.sberror or sbcs.sbbusyerror: 34 | print("Error:") 35 | print_fields(sbcs) 36 | sys.exit(-1) 37 | 38 | data = ocd.dmi_read(sbdata0.addr) 39 | print("{:x}: {}".format(addr, data)) 40 | -------------------------------------------------------------------------------- /fpga/openocd_rpc/halt: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | import socket 3 | import itertools 4 | import sys 5 | 6 | from dm_reg import * 7 | from dm_utils import * 8 | from openocd import * 9 | 10 | if __name__ == "__main__": 11 | with OpenOcd(verbose=False) as ocd: 12 | ocd.dmi_write_fields(dmcontrol, hartsello = int(sys.argv[1]), resumereq = 0, haltreq = 0) 13 | ocd.dmi_write_fields(dmcontrol, hartsello = int(sys.argv[1]), resumereq = 0, haltreq = 1) 14 | ocd.dmi_write_fields(dmcontrol, hartsello = int(sys.argv[1]), resumereq = 0, haltreq = 0) 15 | -------------------------------------------------------------------------------- /fpga/openocd_rpc/haltsum0: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | import socket 3 | import itertools 4 | import sys 5 | 6 | from dm_reg import * 7 | from dm_utils import * 8 | from openocd import * 9 | 10 | if __name__ == "__main__": 11 | with OpenOcd() as ocd: 12 | ocd.dmi_read_fields(haltsum0) 13 | -------------------------------------------------------------------------------- /fpga/openocd_rpc/log: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | import socket 3 | import itertools 4 | import sys 5 | 6 | from dm_reg import * 7 | from dm_utils import * 8 | from openocd import * 9 | 10 | if __name__ == "__main__": 11 | if sys.argv[1] == 'enable': 12 | asm = [ 0x8000d073 ] 13 | elif sys.argv[1] == 'disable': 14 | asm = [ 0x80005073 ] 15 | else: 16 | print("Unexpected command: " + sys.argv[1]) 17 | sys.exit(-1) 18 | 19 | asm += [ 20 | 0x00100073 # ebreak 21 | ] 22 | 23 | print(asm) 24 | 25 | progbuf_cmds = [(i + 0x20, data) for i, data in enumerate(asm)] 26 | with OpenOcd(verbose=False) as ocd: 27 | # Progbuf 28 | for reg, data in progbuf_cmds: 29 | ocd.send("riscv dmi_write {} {}".format(reg, data)) 30 | # Access Register 31 | ocd.send("riscv dmi_write 0x17 0x361001") # regno = sp, postexec, transfer, 64-bit 32 | ret = ocd.send("riscv dmi_read 0x16") 33 | if ret != "0x10000002": 34 | print("Exec error: abstracts " + ret) 35 | set_reg(abstractcs, ret) 36 | print_fields(abstractcs) 37 | -------------------------------------------------------------------------------- /fpga/openocd_rpc/put_mem: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | import socket 3 | import itertools 4 | import sys 5 | 6 | from dm_reg import * 7 | from dm_utils import * 8 | from openocd import * 9 | 10 | def check_busy(ocd): 11 | sbcs.bits = int(ocd.dmi_read(sbcs.addr), 16) 12 | return sbcs.sbbusy == 1 13 | 14 | if __name__ == "__main__": 15 | addr = int(sys.argv[1], 16) 16 | data = int(sys.argv[2], 16) 17 | 18 | with OpenOcd(verbose=False) as ocd: 19 | while check_busy(ocd): 20 | print("waiting") 21 | pass 22 | 23 | sbaddress0.bits = addr & 0xffffffff 24 | sbaddress1.bits = addr >> 32 25 | sbdata0.bits = data 26 | 27 | ocd.dmi_write(sbaddress1.addr, sbaddress1.bits) 28 | ocd.dmi_write(sbaddress0.addr, sbaddress0.bits) 29 | ocd.dmi_write(sbdata0.addr, sbdata0.bits) 30 | -------------------------------------------------------------------------------- /fpga/openocd_rpc/resume: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | import socket 3 | import itertools 4 | import sys 5 | 6 | from dm_reg import * 7 | from dm_utils import * 8 | from openocd import * 9 | 10 | if __name__ == "__main__": 11 | hartid = int(sys.argv[1]) 12 | with OpenOcd(verbose=False) as ocd: 13 | ocd.dmi_write_fields(dmcontrol, hartsello = hartid, resumereq = 0, haltreq = 0) 14 | ocd.dmi_write_fields(dmcontrol, hartsello = hartid, resumereq = 1, haltreq = 0) 15 | ocd.dmi_write_fields(dmcontrol, hartsello = hartid, resumereq = 0, haltreq = 0) 16 | -------------------------------------------------------------------------------- /fpga/openocd_rpc/scause: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | import socket 3 | import itertools 4 | import sys 5 | 6 | from dm_reg import * 7 | from dm_utils import * 8 | from openocd import * 9 | 10 | if __name__ == "__main__": 11 | asm = [ 12 | 0x142022f3, # csrr t0, scause 13 | #0x105022f3, # csrr t0, stvec 14 | 0x00100073 # ebreak 15 | ] 16 | progbuf_cmds = [(i + 0x20, data) for i, data in enumerate(asm)] 17 | with OpenOcd() as ocd: 18 | # Progbuf 19 | for reg, data in progbuf_cmds: 20 | ocd.send("riscv dmi_write {} {}".format(reg, data)) 21 | # Access Register 22 | ocd.send("riscv dmi_write 0x17 0x361001") # regno = sp, postexec, transfer, 64-bit 23 | ocd.send("riscv dmi_write 0x16 0xffffffff") 24 | abstractcs = ocd.send("riscv dmi_read 0x16") 25 | if abstractcs != "0x10000002": 26 | print("Exec error: abstracts " + abstractcs) 27 | ocd.send("riscv dmi_write 0x17 0x361005") # regno = t0, postexec, transfer, 64-bit 28 | dm_data0 = ocd.send("riscv dmi_read 0x4") 29 | dm_data1 = ocd.send("riscv dmi_read 0x5") 30 | print("data0: {}, data1: {}".format(dm_data0, dm_data1)) 31 | -------------------------------------------------------------------------------- /fpga/openocd_rpc/sepc: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | import socket 3 | import itertools 4 | import sys 5 | 6 | from dm_reg import * 7 | from dm_utils import * 8 | from openocd import * 9 | 10 | if __name__ == "__main__": 11 | asm = [ 12 | 0x141022f3, # csrr t0, scause 13 | #0x105022f3, # csrr t0, stvec 14 | 0x00100073 # ebreak 15 | ] 16 | progbuf_cmds = [(i + 0x20, data) for i, data in enumerate(asm)] 17 | with OpenOcd() as ocd: 18 | # Progbuf 19 | for reg, data in progbuf_cmds: 20 | ocd.send("riscv dmi_write {} {}".format(reg, data)) 21 | # Access Register 22 | ocd.send("riscv dmi_write 0x17 0x361001") # regno = sp, postexec, transfer, 64-bit 23 | ocd.send("riscv dmi_write 0x16 0xffffffff") 24 | abstractcs = ocd.send("riscv dmi_read 0x16") 25 | if abstractcs != "0x10000002": 26 | print("Exec error: abstracts " + abstractcs) 27 | ocd.send("riscv dmi_write 0x17 0x361005") # regno = t0, postexec, transfer, 64-bit 28 | dm_data0 = ocd.send("riscv dmi_read 0x4") 29 | dm_data1 = ocd.send("riscv dmi_read 0x5") 30 | print("data0: {}, data1: {}".format(dm_data0, dm_data1)) 31 | -------------------------------------------------------------------------------- /fpga/openocd_rpc/set_cp: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | import socket 3 | import itertools 4 | import sys 5 | 6 | from dm_reg import * 7 | from dm_utils import * 8 | from openocd import * 9 | 10 | # set_cp (in dec) [property=value(in hex)] 11 | # property: waymask bkt_freq bkt_size bkt_inc 12 | # no space around '='! 13 | VERBOSE = False 14 | 15 | DSID = 0x41 16 | DSID_SEL = 0x42 17 | DSID_COUNT = 0x43 18 | MEM_BASE_LO = 0x44 19 | MEM_BASE_HI = 0x45 20 | MEM_MASK_LO = 0x46 21 | MEM_MASK_HI = 0x47 22 | BUCKET_FREQ = 0x48 23 | BUCKET_SIZE = 0x49 24 | BUCKET_INC = 0x4a 25 | TRAFFIC = 0x4b 26 | WAYMASK = 0x4c 27 | L2_CAPACITY = 0x4d 28 | 29 | CP = { 30 | 'bkt_freq': BUCKET_FREQ, 31 | 'bkt_size': BUCKET_SIZE, 32 | 'bkt_inc' : BUCKET_INC, 33 | 'waymask' : WAYMASK 34 | } 35 | 36 | if __name__ == "__main__": 37 | if len(sys.argv) == 1: 38 | print("set_cp.py [=] ...") 39 | print("NOTE: no space around '='") 40 | print("Properties:") 41 | print(CP.keys()) 42 | sys.exit(0) 43 | 44 | hartid = int(sys.argv[1]) 45 | with OpenOcd(verbose=VERBOSE) as ocd: 46 | ocd.dmi_write(DSID_SEL, hartid) 47 | for pair in sys.argv[2:]: 48 | dst, val = pair.split('=') 49 | addr = CP[dst] 50 | if not addr: 51 | print("Invalid control plane property: {}".format(dst)) 52 | continue 53 | ocd.dmi_write(addr, val) 54 | -------------------------------------------------------------------------------- /fpga/openocd_rpc/show_cache_capacity: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | import socket 3 | import itertools 4 | import sys 5 | import time 6 | 7 | from dm_reg import * 8 | from dm_utils import * 9 | from openocd import * 10 | 11 | if __name__ == "__main__": 12 | with OpenOcd() as ocd: 13 | for i in range(0, 4): 14 | ocd.send("riscv dmi_write 0x42 {}" % i) 15 | print("hart " + i + ": " + ocd.send("riscv dmi_read 0x4d")) 16 | -------------------------------------------------------------------------------- /fpga/openocd_rpc/show_traffic: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | import socket 3 | import itertools 4 | import sys 5 | import time 6 | 7 | from dm_reg import * 8 | from dm_utils import * 9 | from openocd import * 10 | 11 | if __name__ == "__main__": 12 | with OpenOcd() as ocd: 13 | for i in range(0, 4): 14 | ocd.send("riscv dmi_write 0x42 {}" % i) 15 | print("hart " + i + ": " + ocd.send("riscv dmi_read 0x4b")) 16 | -------------------------------------------------------------------------------- /fpga/openocd_rpc/stval: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | import socket 3 | import itertools 4 | import sys 5 | 6 | from dm_reg import * 7 | from dm_utils import * 8 | from openocd import * 9 | 10 | if __name__ == "__main__": 11 | asm = [ 12 | 0x143022f3, # csrr t0, scause 13 | #0x105022f3, # csrr t0, stvec 14 | 0x00100073 # ebreak 15 | ] 16 | progbuf_cmds = [(i + 0x20, data) for i, data in enumerate(asm)] 17 | with OpenOcd() as ocd: 18 | # Progbuf 19 | for reg, data in progbuf_cmds: 20 | ocd.send("riscv dmi_write {} {}".format(reg, data)) 21 | # Access Register 22 | ocd.send("riscv dmi_write 0x17 0x361001") # regno = sp, postexec, transfer, 64-bit 23 | ocd.send("riscv dmi_write 0x16 0xffffffff") 24 | abstractcs = ocd.send("riscv dmi_read 0x16") 25 | if abstractcs != "0x10000002": 26 | print("Exec error: abstracts " + abstractcs) 27 | ocd.send("riscv dmi_write 0x17 0x361005") # regno = t0, postexec, transfer, 64-bit 28 | dm_data0 = ocd.send("riscv dmi_read 0x4") 29 | dm_data1 = ocd.send("riscv dmi_read 0x5") 30 | print("data0: {}, data1: {}".format(dm_data0, dm_data1)) 31 | -------------------------------------------------------------------------------- /fpga/pardcore/Makefile: -------------------------------------------------------------------------------- 1 | #======================================================================= 2 | # Makefile for Verilog simulation w/ VCS 3 | #----------------------------------------------------------------------- 4 | # Yunsup Lee (yunsup@cs.berkeley.edu) 5 | # 6 | # This makefile will build a rtl simulator and run various tests to 7 | # verify proper functionality. 8 | # 9 | 10 | default: verilog 11 | 12 | fpga_dir = $(abspath ..) 13 | base_dir = $(fpga_dir)/.. 14 | build_dir = $(fpga_dir)/build 15 | generated_dir = $(build_dir)/generated-src 16 | 17 | MODEL ?= TestHarness 18 | BOARD ?= zcu102 19 | CONFIG ?= LvNAFPGAConfig$(BOARD) 20 | 21 | #-------------------------------------------------------------------- 22 | # Rocket-chip verilog source generation 23 | #-------------------------------------------------------------------- 24 | 25 | -include $(base_dir)/Makefrag 26 | 27 | gen_rtl = $(generated_dir)/$(long_name).v 28 | srams_rtl = $(generated_dir)/$(long_name).behav_srams.v 29 | other_rtl = $(base_dir)/src/main/resources/vsrc/AsyncResetReg.v \ 30 | $(base_dir)/src/main/resources/vsrc/EICG_wrapper.v \ 31 | $(base_dir)/src/main/resources/vsrc/plusarg_reader.v 32 | 33 | $(gen_rtl): 34 | $(MAKE) verilog -C $(base_dir)/vsim CONFIG=$(CONFIG) MODEL=$(MODEL) generated_dir=$(generated_dir) 35 | 36 | $(srams_rtl): $(gen_rtl) 37 | 38 | rocketchip_rtl = rtl/rocket/rocketchip_board_$(BOARD).v 39 | 40 | $(rocketchip_rtl): $(gen_rtl) $(srams_rtl) $(other_rtl) 41 | cat $^ > $@ 42 | sed -i -e 's/_\(aw\|ar\|w\|r\|b\)_\(\|bits_\)/_\1/g' $@ 43 | sed -i -e 's/LvNABoomFPGATop/LvNAFPGATop/g' $@ 44 | 45 | verilog: $(rocketchip_rtl) 46 | 47 | .PHONY: $(gen_rtl) verilog 48 | 49 | #-------------------------------------------------------------------- 50 | # Cleaning 51 | #-------------------------------------------------------------------- 52 | 53 | clean: 54 | -rm -rf $(generated_dir) 55 | 56 | .PHONY: default clean 57 | -------------------------------------------------------------------------------- /fpga/pardcore/rtl/rocket/.gitignore: -------------------------------------------------------------------------------- 1 | rocketchip_board_*.v 2 | -------------------------------------------------------------------------------- /fpga/scripts/account.py: -------------------------------------------------------------------------------- 1 | import sys 2 | 3 | if __name__ == "__main__": 4 | if len(sys.argv) != 2: 5 | print "Log file expected." 6 | exit(1) 7 | files = {} 8 | with open(sys.argv[1], "r") as f: 9 | for line in f: 10 | l = line.split() 11 | if len(l) == 0 or l[0] != "Traffic": 12 | continue 13 | cycle = int(l[2]) 14 | dsid = int(l[4]) 15 | traffic = int(l[6]) 16 | if dsid not in files: 17 | files[dsid] = open("%d.trace" % dsid,"w") 18 | f = files[dsid] 19 | f.write("%d %d\n" % (cycle, traffic)) 20 | for dsid in files: 21 | files[dsid].close() 22 | -------------------------------------------------------------------------------- /fpga/scripts/gen.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | python account.py emu.log 3 | cp 0.trace nohype_0_32.trace 4 | cp 1.trace nohype_1_32.trace 5 | -------------------------------------------------------------------------------- /fpga/scripts/range.py: -------------------------------------------------------------------------------- 1 | import sys 2 | 3 | def prepare(file_name): 4 | data = {} 5 | with open(file_name, "r") as f: 6 | for line in f: 7 | l = line.split() 8 | if len(l) == 0 or l[0] != "Traffic": 9 | continue 10 | cycle = int(l[2]) 11 | dsid = int(l[4]) 12 | traffic = int(l[6]) 13 | if dsid not in data: 14 | data[dsid] = [] 15 | data[dsid].append([cycle, traffic]) 16 | return data 17 | 18 | def query(datas, dsid, start, end): 19 | total_traffic = 0 20 | for r in datas[dsid]: 21 | if r[0] > end: 22 | break 23 | if r[0] > start: 24 | total_traffic += r[1] 25 | return total_traffic 26 | 27 | if __name__ == "__main__": 28 | if len(sys.argv) != 2: 29 | print "Log file expected." 30 | exit(1) 31 | 32 | data = prepare(sys.argv[1]) 33 | 34 | for i in range(0, 2000): 35 | start = 17000 * i 36 | end = 17000 * (i + 1) 37 | sample_0 = query(data, 0, start, start + 1000) 38 | sample_1 = query(data, 1, start, start + 1000) 39 | regulate_0 = query(data, 0, start + 1000, end) 40 | regulate_1 = query(data, 1, start + 1000, end) 41 | print i, "\t", sample_0, "\t", sample_1, "\t", regulate_0, "\t", regulate_1 42 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /project/.gitignore: -------------------------------------------------------------------------------- 1 | *~ -------------------------------------------------------------------------------- /project/build.properties: -------------------------------------------------------------------------------- 1 | sbt.version=1.2.7 2 | -------------------------------------------------------------------------------- /project/plugins.sbt: -------------------------------------------------------------------------------- 1 | resolvers += "jgit-repo" at "http://download.eclipse.org/jgit/maven" 2 | 3 | addSbtPlugin("com.typesafe.sbt" % "sbt-ghpages" % "0.6.2") 4 | 5 | addSbtPlugin("com.typesafe.sbt" % "sbt-site" % "1.3.1") 6 | 7 | addSbtPlugin("com.eed3si9n" % "sbt-buildinfo" % "0.7.0") 8 | 9 | addSbtPlugin("org.xerial.sbt" % "sbt-pack" % "0.9.3") 10 | 11 | addSbtPlugin("com.eed3si9n" % "sbt-unidoc" % "0.4.1") 12 | 13 | addSbtPlugin("org.scoverage" % "sbt-scoverage" % "1.5.1") 14 | -------------------------------------------------------------------------------- /regression/.gitignore: -------------------------------------------------------------------------------- 1 | /install 2 | /stamps 3 | /torture-failures 4 | -------------------------------------------------------------------------------- /riscv-tools.hash: -------------------------------------------------------------------------------- 1 | 0425658510490d4d093941749c4d26e37af23504 2 | -------------------------------------------------------------------------------- /sbt-launch.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LvNA-system/labeled-RISC-V/f6895abf0a3d6c05fd1b87c9de21d251ffa43887/sbt-launch.jar -------------------------------------------------------------------------------- /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 riscv 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 | print "STARTING A SIMULATION" 20 | print 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/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)/include/ -Tlink.ld 9 | 10 | ELFS = debug_rom 11 | DEPS = debug_rom.S link.ld 12 | 13 | all: $(patsubst %,%.h,$(ELFS)) 14 | 15 | publish: debug_rom.scala 16 | mv $< ../../src/main/scala/devices/debug/DebugRomContents.scala 17 | 18 | %.scala: %.raw 19 | xxd -i $^ | sed -e "s/^unsigned char debug_rom_raw\[\] = {/\/\/ This file was auto-generated by 'make publish' in debug\/ directory.\n\npackage freechips.rocketchip.devices.debug\n\nobject DebugRomContents {\n\n def apply() : Array[Byte] = { Array (/" \ 20 | -e "s/};/ ).map(_.toByte) }\n\n}/" \ 21 | -e "s/^unsigned int debug_rom_raw_len.*//" > $@ 22 | 23 | 24 | %.raw: % 25 | $(OBJCOPY) -O binary --only-section .text $^ $@ 26 | 27 | debug_rom: $(DEPS) 28 | $(COMPILE) -o $@ $^ 29 | 30 | clean: 31 | rm -f $(ELFS) debug_rom*.raw debug_rom*.h 32 | -------------------------------------------------------------------------------- /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/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 in 7 | ); 8 | 9 | reg en_latched /*verilator clock_enable*/; 10 | 11 | always @(en or in) begin 12 | if (!in) begin 13 | en_latched = en; 14 | end 15 | end 16 | 17 | assign out = en_latched && in; 18 | 19 | endmodule 20 | -------------------------------------------------------------------------------- /src/main/resources/vsrc/UARTPrinter.v: -------------------------------------------------------------------------------- 1 | module UARTPrinter 2 | #( 3 | parameter FILENAME = "serial" 4 | )( 5 | input clock, 6 | input valid, 7 | input [7:0] data // Always expect an ASCII character 8 | ); 9 | 10 | integer fd; 11 | 12 | initial begin 13 | fd = $fopen(FILENAME, "w"); 14 | end 15 | 16 | always @(posedge clock) begin 17 | if (valid) begin 18 | $fwrite(fd, "%c", data); 19 | $fflush(fd); 20 | end 21 | end 22 | 23 | endmodule 24 | -------------------------------------------------------------------------------- /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 #(parameter FORMAT="borked=%d", DEFAULT=0) ( 8 | output [31:0] out 9 | ); 10 | 11 | `ifdef SYNTHESIS 12 | assign out = DEFAULT; 13 | `else 14 | reg [31:0] myplus; 15 | assign out = myplus; 16 | 17 | initial begin 18 | if (!$value$plusargs(FORMAT, myplus)) myplus = DEFAULT; 19 | end 20 | `endif 21 | 22 | endmodule 23 | -------------------------------------------------------------------------------- /src/main/scala/amba/ahb/Bundles.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | 3 | package freechips.rocketchip.amba.ahb 4 | 5 | import Chisel._ 6 | import freechips.rocketchip.util.GenericParameterizedBundle 7 | 8 | abstract class AHBBundleBase(params: AHBBundleParameters) extends GenericParameterizedBundle(params) 9 | 10 | // Signal directions are from the master's point-of-view 11 | class AHBBundle(params: AHBBundleParameters) extends AHBBundleBase(params) 12 | { 13 | // Flow control signals from the master 14 | val hmastlock = Bool(OUTPUT) 15 | val htrans = UInt(OUTPUT, width = params.transBits) 16 | val hsel = Bool(OUTPUT) 17 | val hready = Bool(OUTPUT) // on a master, drive this from readyout 18 | 19 | // Payload signals 20 | val hwrite = Bool(OUTPUT) 21 | val haddr = UInt(OUTPUT, width = params.addrBits) 22 | val hsize = UInt(OUTPUT, width = params.sizeBits) 23 | val hburst = UInt(OUTPUT, width = params.burstBits) 24 | val hprot = UInt(OUTPUT, width = params.protBits) 25 | val hwdata = UInt(OUTPUT, width = params.dataBits) 26 | 27 | val hreadyout = Bool(INPUT) 28 | val hresp = Bool(INPUT) 29 | val hrdata = UInt(INPUT, width = params.dataBits) 30 | 31 | def tieoff() { 32 | hreadyout.dir match { 33 | case INPUT => 34 | hreadyout := Bool(false) 35 | hresp := AHBParameters.RESP_OKAY 36 | hrdata := UInt(0) 37 | case OUTPUT => 38 | hmastlock := Bool(false) 39 | htrans := AHBParameters.TRANS_IDLE 40 | hsel := Bool(false) 41 | hready := Bool(false) 42 | hwrite := Bool(false) 43 | haddr := UInt(0) 44 | hsize := UInt(0) 45 | hburst := AHBParameters.BURST_SINGLE 46 | hprot := AHBParameters.PROT_DEFAULT 47 | hwdata := UInt(0) 48 | case _ => 49 | } 50 | } 51 | } 52 | 53 | object AHBBundle 54 | { 55 | def apply(params: AHBBundleParameters) = new AHBBundle(params) 56 | } 57 | -------------------------------------------------------------------------------- /src/main/scala/amba/ahb/Nodes.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | 3 | package freechips.rocketchip.amba.ahb 4 | 5 | import Chisel._ 6 | import chisel3.internal.sourceinfo.SourceInfo 7 | import freechips.rocketchip.config.Parameters 8 | import freechips.rocketchip.diplomacy._ 9 | 10 | object AHBImp extends SimpleNodeImp[AHBMasterPortParameters, AHBSlavePortParameters, AHBEdgeParameters, AHBBundle] 11 | { 12 | def edge(pd: AHBMasterPortParameters, pu: AHBSlavePortParameters, p: Parameters, sourceInfo: SourceInfo) = AHBEdgeParameters(pd, pu, p, sourceInfo) 13 | def bundle(e: AHBEdgeParameters) = AHBBundle(e.bundle) 14 | def render(e: AHBEdgeParameters) = RenderedEdge(colour = "#00ccff" /* bluish */, label = (e.slave.beatBytes * 8).toString) 15 | 16 | override def mixO(pd: AHBMasterPortParameters, node: OutwardNode[AHBMasterPortParameters, AHBSlavePortParameters, AHBBundle]): AHBMasterPortParameters = 17 | pd.copy(masters = pd.masters.map { c => c.copy (nodePath = node +: c.nodePath) }) 18 | override def mixI(pu: AHBSlavePortParameters, node: InwardNode[AHBMasterPortParameters, AHBSlavePortParameters, AHBBundle]): AHBSlavePortParameters = 19 | pu.copy(slaves = pu.slaves.map { m => m.copy (nodePath = node +: m.nodePath) }) 20 | } 21 | 22 | // Nodes implemented inside modules 23 | case class AHBMasterNode(portParams: Seq[AHBMasterPortParameters])(implicit valName: ValName) extends SourceNode(AHBImp)(portParams) 24 | case class AHBSlaveNode(portParams: Seq[AHBSlavePortParameters])(implicit valName: ValName) extends SinkNode(AHBImp)(portParams) 25 | case class AHBNexusNode( 26 | masterFn: Seq[AHBMasterPortParameters] => AHBMasterPortParameters, 27 | slaveFn: Seq[AHBSlavePortParameters] => AHBSlavePortParameters)( 28 | implicit valName: ValName) 29 | extends NexusNode(AHBImp)(masterFn, slaveFn) 30 | 31 | case class AHBIdentityNode()(implicit valName: ValName) extends IdentityNode(AHBImp)() 32 | -------------------------------------------------------------------------------- /src/main/scala/amba/ahb/Protocol.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | 3 | package freechips.rocketchip.amba.ahb 4 | 5 | import Chisel._ 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 | 15 | def TRANS_IDLE = UInt(0, width = transBits) // No transfer requested, not in a burst 16 | def TRANS_BUSY = UInt(1, width = transBits) // No transfer requested, in a burst 17 | def TRANS_NONSEQ = UInt(2, width = transBits) // First (potentially only) request in a burst 18 | def TRANS_SEQ = UInt(3, width = transBits) // Following requests in a burst 19 | 20 | def BURST_SINGLE = UInt(0, width = burstBits) // Single access (no burst) 21 | def BURST_INCR = UInt(1, width = burstBits) // Incrementing burst of arbitrary length, not crossing 1KB 22 | def BURST_WRAP4 = UInt(2, width = burstBits) // 4-beat wrapping burst 23 | def BURST_INCR4 = UInt(3, width = burstBits) // 4-beat incrementing burst 24 | def BURST_WRAP8 = UInt(4, width = burstBits) // 8-beat wrapping burst 25 | def BURST_INCR8 = UInt(5, width = burstBits) // 8-beat incrementing burst 26 | def BURST_WRAP16 = UInt(6, width = burstBits) // 16-beat wrapping burst 27 | def BURST_INCR16 = UInt(7, width = burstBits) // 16-beat incrementing burst 28 | 29 | val maxTransfer = 16 30 | 31 | def RESP_OKAY = Bool(false) 32 | def RESP_ERROR = Bool(true) 33 | 34 | def PROT_DATA = UInt(1, width = protBits) 35 | def PROT_PRIVILEDGED = UInt(2, width = protBits) 36 | def PROT_BUFFERABLE = UInt(4, width = protBits) 37 | def PROT_CACHEABLE = UInt(8, width = protBits) 38 | def PROT_DEFAULT = PROT_DATA | PROT_PRIVILEDGED 39 | } 40 | -------------------------------------------------------------------------------- /src/main/scala/amba/ahb/Xbar.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | 3 | package freechips.rocketchip.amba.ahb 4 | 5 | import Chisel._ 6 | import freechips.rocketchip.config.Parameters 7 | import freechips.rocketchip.diplomacy._ 8 | import freechips.rocketchip.regmapper._ 9 | import scala.math.{min,max} 10 | 11 | class AHBFanout()(implicit p: Parameters) extends LazyModule { 12 | val node = AHBNexusNode( 13 | masterFn = { case Seq(m) => m }, 14 | slaveFn = { seq => seq(0).copy(slaves = seq.flatMap(_.slaves)) }) 15 | 16 | lazy val module = new LazyModuleImp(this) { 17 | if (node.edges.in.size >= 1) { 18 | require (node.edges.in.size == 1, "AHBFanout does not support multiple masters") 19 | require (node.edges.out.size > 0, "AHBFanout requires at least one slave") 20 | 21 | // Require consistent bus widths 22 | val (io_out, edgesOut) = node.out.unzip 23 | val port0 = edgesOut(0).slave 24 | edgesOut.foreach { edge => 25 | val port = edge.slave 26 | require (port.beatBytes == port0.beatBytes, 27 | s"${port.slaves.map(_.name)} ${port.beatBytes} vs ${port0.slaves.map(_.name)} ${port0.beatBytes}") 28 | } 29 | 30 | val port_addrs = edgesOut.map(_.slave.slaves.map(_.address).flatten) 31 | val routingMask = AddressDecoder(port_addrs) 32 | val route_addrs = port_addrs.map(_.map(_.widen(~routingMask)).distinct) 33 | 34 | val (in, _) = node.in(0) 35 | val a_sel = Vec(route_addrs.map(seq => seq.map(_.contains(in.haddr)).reduce(_ || _))) 36 | val d_sel = Reg(a_sel) 37 | 38 | when (in.hready) { d_sel := a_sel } 39 | (a_sel zip io_out) foreach { case (sel, out) => 40 | out := in 41 | out.hsel := in.hsel && sel 42 | } 43 | 44 | in.hreadyout := !Mux1H(d_sel, io_out.map(!_.hreadyout)) 45 | in.hresp := Mux1H(d_sel, io_out.map(_.hresp)) 46 | in.hrdata := Mux1H(d_sel, io_out.map(_.hrdata)) 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/main/scala/amba/ahb/package.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | 3 | package freechips.rocketchip.amba 4 | 5 | import Chisel._ 6 | import freechips.rocketchip.diplomacy._ 7 | 8 | package object ahb 9 | { 10 | type AHBOutwardNode = OutwardNodeHandle[AHBMasterPortParameters, AHBSlavePortParameters, AHBEdgeParameters, AHBBundle] 11 | type AHBInwardNode = InwardNodeHandle[AHBMasterPortParameters, AHBSlavePortParameters, AHBEdgeParameters, AHBBundle] 12 | type AHBNode = SimpleNodeHandle[AHBMasterPortParameters, AHBSlavePortParameters, AHBEdgeParameters, AHBBundle] 13 | } 14 | -------------------------------------------------------------------------------- /src/main/scala/amba/apb/Bundles.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | 3 | package freechips.rocketchip.amba.apb 4 | 5 | import Chisel._ 6 | import freechips.rocketchip.util.GenericParameterizedBundle 7 | 8 | abstract class APBBundleBase(params: APBBundleParameters) extends GenericParameterizedBundle(params) 9 | 10 | // Signal directions are from the master's point-of-view 11 | class APBBundle(params: APBBundleParameters) extends APBBundleBase(params) 12 | { 13 | // Flow control signals from the master 14 | val psel = Bool(OUTPUT) 15 | val penable = Bool(OUTPUT) 16 | 17 | // Payload signals 18 | val pwrite = Bool(OUTPUT) 19 | val paddr = UInt(OUTPUT, width = params.addrBits) 20 | val pprot = UInt(OUTPUT, width = params.protBits) 21 | val pwdata = UInt(OUTPUT, width = params.dataBits) 22 | val pstrb = UInt(OUTPUT, width = params.dataBits/8) 23 | 24 | val pready = Bool(INPUT) 25 | val pslverr = Bool(INPUT) 26 | val prdata = UInt(INPUT, width = params.dataBits) 27 | 28 | def tieoff() { 29 | pready.dir match { 30 | case INPUT => 31 | pready := Bool(false) 32 | pslverr := Bool(false) 33 | prdata := UInt(0) 34 | case OUTPUT => 35 | pwrite := Bool(false) 36 | paddr := UInt(0) 37 | pprot := APBParameters.PROT_DEFAULT 38 | pwdata := UInt(0) 39 | pstrb := UInt(0) 40 | case _ => 41 | } 42 | } 43 | } 44 | 45 | object APBBundle 46 | { 47 | def apply(params: APBBundleParameters) = new APBBundle(params) 48 | } 49 | -------------------------------------------------------------------------------- /src/main/scala/amba/apb/Nodes.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | 3 | package freechips.rocketchip.amba.apb 4 | 5 | import Chisel._ 6 | import chisel3.internal.sourceinfo.SourceInfo 7 | import freechips.rocketchip.config.Parameters 8 | import freechips.rocketchip.diplomacy._ 9 | 10 | object APBImp extends SimpleNodeImp[APBMasterPortParameters, APBSlavePortParameters, APBEdgeParameters, APBBundle] 11 | { 12 | def edge(pd: APBMasterPortParameters, pu: APBSlavePortParameters, p: Parameters, sourceInfo: SourceInfo) = APBEdgeParameters(pd, pu, p, sourceInfo) 13 | def bundle(e: APBEdgeParameters) = APBBundle(e.bundle) 14 | def render(e: APBEdgeParameters) = RenderedEdge(colour = "#00ccff" /* bluish */, (e.slave.beatBytes * 8).toString) 15 | 16 | override def mixO(pd: APBMasterPortParameters, node: OutwardNode[APBMasterPortParameters, APBSlavePortParameters, APBBundle]): APBMasterPortParameters = 17 | pd.copy(masters = pd.masters.map { c => c.copy (nodePath = node +: c.nodePath) }) 18 | override def mixI(pu: APBSlavePortParameters, node: InwardNode[APBMasterPortParameters, APBSlavePortParameters, APBBundle]): APBSlavePortParameters = 19 | pu.copy(slaves = pu.slaves.map { m => m.copy (nodePath = node +: m.nodePath) }) 20 | } 21 | 22 | case class APBMasterNode(portParams: Seq[APBMasterPortParameters])(implicit valName: ValName) extends SourceNode(APBImp)(portParams) 23 | case class APBSlaveNode(portParams: Seq[APBSlavePortParameters])(implicit valName: ValName) extends SinkNode(APBImp)(portParams) 24 | case class APBNexusNode( 25 | masterFn: Seq[APBMasterPortParameters] => APBMasterPortParameters, 26 | slaveFn: Seq[APBSlavePortParameters] => APBSlavePortParameters)( 27 | implicit valName: ValName) 28 | extends NexusNode(APBImp)(masterFn, slaveFn) 29 | 30 | case class APBIdentityNode()(implicit valName: ValName) extends IdentityNode(APBImp)() 31 | -------------------------------------------------------------------------------- /src/main/scala/amba/apb/Protocol.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | 3 | package freechips.rocketchip.amba.apb 4 | 5 | import Chisel._ 6 | 7 | object APBParameters 8 | { 9 | // These are all fixed by the AHB standard: 10 | val protBits = 3 11 | 12 | def PROT_PRIVILEDGED = UInt(1, width = protBits) 13 | def PROT_NONSECURE = UInt(2, width = protBits) 14 | def PROT_INSTRUCTION = UInt(4, width = protBits) 15 | def PROT_DEFAULT = PROT_PRIVILEDGED 16 | } 17 | -------------------------------------------------------------------------------- /src/main/scala/amba/apb/SRAM.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | 3 | package freechips.rocketchip.amba.apb 4 | 5 | import Chisel._ 6 | import freechips.rocketchip.config.Parameters 7 | import freechips.rocketchip.diplomacy._ 8 | import freechips.rocketchip.util._ 9 | import freechips.rocketchip.tilelink.LFSRNoiseMaker 10 | 11 | class APBRAM( 12 | address: AddressSet, 13 | executable: Boolean = true, 14 | beatBytes: Int = 4, 15 | devName: Option[String] = None, 16 | errors: Seq[AddressSet] = Nil, 17 | fuzzReady: Boolean = false, 18 | fuzzError: Boolean = false) 19 | (implicit p: Parameters) extends DiplomaticSRAM(address, beatBytes, devName) 20 | { 21 | val node = APBSlaveNode(Seq(APBSlavePortParameters( 22 | Seq(APBSlaveParameters( 23 | address = List(address) ++ errors, 24 | resources = resources, 25 | regionType = RegionType.UNCACHED, 26 | executable = executable, 27 | supportsRead = true, 28 | supportsWrite = true)), 29 | beatBytes = beatBytes))) 30 | 31 | lazy val module = new LazyModuleImp(this) { 32 | val (in, _) = node.in(0) 33 | val (mem, omMem) = makeSinglePortedByteWriteSeqMem(1 << mask.filter(b=>b).size) 34 | 35 | val paddr = Cat((mask zip (in.paddr >> log2Ceil(beatBytes)).asBools).filter(_._1).map(_._2).reverse) 36 | val legal = address.contains(in.paddr) 37 | 38 | val read = in.psel && !in.penable && !in.pwrite 39 | when (in.psel && !in.penable && in.pwrite && legal) { 40 | mem.write(paddr, Vec.tabulate(beatBytes) { i => in.pwdata(8*(i+1)-1, 8*i) }, in.pstrb.asBools) 41 | } 42 | 43 | in.pready := Bool(!fuzzReady) || LFSRNoiseMaker(1)(0) 44 | in.pslverr := RegEnable(!legal, !in.penable) || (Bool(fuzzError) && LFSRNoiseMaker(1)(0)) 45 | in.prdata := mem.readAndHold(paddr, read).asUInt 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/main/scala/amba/apb/Test.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | 3 | package freechips.rocketchip.amba.apb 4 | 5 | import Chisel._ 6 | import freechips.rocketchip.config.Parameters 7 | import freechips.rocketchip.diplomacy._ 8 | import freechips.rocketchip.tilelink._ 9 | import freechips.rocketchip.unittest._ 10 | 11 | class RRTest0(address: BigInt)(implicit p: Parameters) extends APBRegisterRouter(address, 0, 32, 0, 4)( 12 | new APBRegBundle((), _) with RRTest0Bundle)( 13 | new APBRegModule((), _, _) with RRTest0Module) 14 | 15 | class RRTest1(address: BigInt)(implicit p: Parameters) extends APBRegisterRouter(address, 0, 32, 1, 4, false)( 16 | new APBRegBundle((), _) with RRTest1Bundle)( 17 | new APBRegModule((), _, _) with RRTest1Module) 18 | 19 | class APBFuzzBridge(aFlow: Boolean, txns: Int)(implicit p: Parameters) extends LazyModule 20 | { 21 | val fuzz = LazyModule(new TLFuzzer(txns)) 22 | val model = LazyModule(new TLRAMModel("APBFuzzMaster")) 23 | val xbar = LazyModule(new APBFanout) 24 | val ram = LazyModule(new APBRAM(AddressSet(0x0, 0xff), fuzzReady = true, fuzzError = true)) 25 | val gpio = LazyModule(new RRTest0(0x100)) 26 | 27 | ram.node := xbar.node 28 | gpio.node := xbar.node 29 | (xbar.node 30 | := TLToAPB(aFlow) 31 | := TLDelayer(0.2) 32 | := TLBuffer(BufferParams.flow) 33 | := TLDelayer(0.2) 34 | := TLFragmenter(4, 8) 35 | := model.node 36 | := fuzz.node) 37 | 38 | lazy val module = new LazyModuleImp(this) with UnitTestModule { 39 | io.finished := fuzz.module.io.finished 40 | } 41 | } 42 | 43 | class APBBridgeTest(aFlow: Boolean, txns: Int = 5000, timeout: Int = 500000)(implicit p: Parameters) extends UnitTest(timeout) { 44 | val dut = Module(LazyModule(new APBFuzzBridge(aFlow, txns)).module) 45 | io.finished := dut.io.finished 46 | } 47 | -------------------------------------------------------------------------------- /src/main/scala/amba/apb/Xbar.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | 3 | package freechips.rocketchip.amba.apb 4 | 5 | import Chisel._ 6 | import freechips.rocketchip.config.Parameters 7 | import freechips.rocketchip.diplomacy._ 8 | import freechips.rocketchip.regmapper._ 9 | import scala.math.{min,max} 10 | 11 | class APBFanout()(implicit p: Parameters) extends LazyModule { 12 | val node = APBNexusNode( 13 | masterFn = { case Seq(m) => m }, 14 | slaveFn = { seq => seq(0).copy(slaves = seq.flatMap(_.slaves)) }) 15 | 16 | lazy val module = new LazyModuleImp(this) { 17 | if (node.edges.in.size >= 1) { 18 | require (node.edges.in.size == 1, "APBFanout does not support multiple masters") 19 | require (node.edges.out.size > 0, "APBFanout requires at least one slave") 20 | 21 | val (in, _) = node.in(0) 22 | 23 | // Require consistent bus widths 24 | val (io_out, edgesOut) = node.out.unzip 25 | val port0 = edgesOut(0).slave 26 | edgesOut.foreach { edge => 27 | val port = edge.slave 28 | require (port.beatBytes == port0.beatBytes, 29 | s"${port.slaves.map(_.name)} ${port.beatBytes} vs ${port0.slaves.map(_.name)} ${port0.beatBytes}") 30 | } 31 | 32 | val port_addrs = edgesOut.map(_.slave.slaves.map(_.address).flatten) 33 | val routingMask = AddressDecoder(port_addrs) 34 | val route_addrs = port_addrs.map(_.map(_.widen(~routingMask)).distinct) 35 | 36 | val sel = Vec(route_addrs.map(seq => seq.map(_.contains(in.paddr)).reduce(_ || _))) 37 | (sel zip io_out) foreach { case (sel, out) => 38 | out := in 39 | out.psel := sel && in.psel 40 | out.penable := sel && in.penable 41 | } 42 | 43 | in.pready := !Mux1H(sel, io_out.map(!_.pready)) 44 | in.pslverr := Mux1H(sel, io_out.map(_.pslverr)) 45 | in.prdata := Mux1H(sel, io_out.map(_.prdata)) 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/main/scala/amba/apb/package.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | 3 | package freechips.rocketchip.amba 4 | 5 | import Chisel._ 6 | import freechips.rocketchip.diplomacy._ 7 | 8 | package object apb 9 | { 10 | type APBOutwardNode = OutwardNodeHandle[APBMasterPortParameters, APBSlavePortParameters, APBEdgeParameters, APBBundle] 11 | type APBInwardNode = InwardNodeHandle[APBMasterPortParameters, APBSlavePortParameters, APBEdgeParameters, APBBundle] 12 | type APBNode = SimpleNodeHandle[APBMasterPortParameters, APBSlavePortParameters, APBEdgeParameters, APBBundle] 13 | } 14 | -------------------------------------------------------------------------------- /src/main/scala/amba/axi4/CrossingHelper.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | 3 | package freechips.rocketchip.amba.axi4 4 | 5 | import freechips.rocketchip.config.Parameters 6 | import freechips.rocketchip.diplomacy._ 7 | 8 | case class AXI4InwardCrossingHelper(name: String, scope: LazyScope, node: AXI4InwardNode) { 9 | def apply(xing: ClockCrossingType = NoCrossing)(implicit p: Parameters): AXI4InwardNode = { 10 | xing match { 11 | case x: AsynchronousCrossing => 12 | node :*=* scope { AXI4AsyncCrossingSink(x.asSinkParams) :*=* AXI4AsyncNameNode(name) } :*=* AXI4AsyncNameNode(name) :*=* AXI4AsyncCrossingSource(x.sourceSync) 13 | case RationalCrossing(direction) => 14 | throw new IllegalArgumentException("AXI4 Rational crossing unimplemented") 15 | case SynchronousCrossing(buffer) => 16 | node :*=* scope { AXI4Buffer(buffer) :*=* AXI4NameNode(name) } :*=* AXI4NameNode(name) 17 | } 18 | } 19 | } 20 | 21 | case class AXI4OutwardCrossingHelper(name: String, scope: LazyScope, node: AXI4OutwardNode) { 22 | def apply(xing: ClockCrossingType = NoCrossing)(implicit p: Parameters): AXI4OutwardNode = { 23 | xing match { 24 | case x: AsynchronousCrossing => 25 | AXI4AsyncCrossingSink(x.asSinkParams) :*=* AXI4AsyncNameNode(name) :*=* scope { AXI4AsyncNameNode(name) :*=* AXI4AsyncCrossingSource(x.sourceSync) } :*=* node 26 | case RationalCrossing(direction) => 27 | throw new IllegalArgumentException("AXI4 Rational crossing unimplemented") 28 | case SynchronousCrossing(buffer) => 29 | AXI4NameNode(name) :*=* scope { AXI4NameNode(name) :*=* AXI4Buffer(buffer) } :*=* node 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/main/scala/amba/axi4/Dumper.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | 3 | package freechips.rocketchip.amba.axi4 4 | 5 | import Chisel._ 6 | import freechips.rocketchip.config.Parameters 7 | import freechips.rocketchip.diplomacy._ 8 | 9 | class AXI4Dumper()(implicit p: Parameters) extends LazyModule 10 | { 11 | val node = AXI4AdapterNode() 12 | 13 | lazy val module = new LazyModuleImp(this) { 14 | (node.in zip node.out) foreach { case ((in, edgeIn), (out, edgeOut)) => 15 | out <> in 16 | when (in.ar.fire()) { 17 | // printf("dumper: ar[len] = %d [addr] = 0x%x\n", in.ar.bits.len, in.ar.bits.addr) 18 | } 19 | } 20 | } 21 | } 22 | 23 | object AXI4Dumper 24 | { 25 | def apply()(implicit p: Parameters): AXI4Node = 26 | { 27 | val axi4dump = LazyModule(new AXI4Dumper()) 28 | axi4dump.node 29 | } 30 | } 31 | 32 | -------------------------------------------------------------------------------- /src/main/scala/amba/axi4/Protocol.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | 3 | package freechips.rocketchip.amba.axi4 4 | 5 | import Chisel._ 6 | import chisel3.util.{Irrevocable, IrrevocableIO} 7 | 8 | object AXI4Parameters 9 | { 10 | // These are all fixed by the AXI4 standard: 11 | val lenBits = 8 12 | val sizeBits = 3 13 | val burstBits = 2 14 | val lockBits = 1 15 | val cacheBits = 4 16 | val protBits = 3 17 | val qosBits = 4 18 | val respBits = 2 19 | 20 | def CACHE_RALLOCATE = UInt(8, width = cacheBits) 21 | def CACHE_WALLOCATE = UInt(4, width = cacheBits) 22 | def CACHE_MODIFIABLE = UInt(2, width = cacheBits) 23 | def CACHE_BUFFERABLE = UInt(1, width = cacheBits) 24 | 25 | def PROT_PRIVILEDGED = UInt(1, width = protBits) 26 | def PROT_INSECURE = UInt(2, width = protBits) 27 | def PROT_INSTRUCTION = UInt(4, width = protBits) 28 | 29 | def BURST_FIXED = UInt(0, width = burstBits) 30 | def BURST_INCR = UInt(1, width = burstBits) 31 | def BURST_WRAP = UInt(2, width = burstBits) 32 | 33 | def RESP_OKAY = UInt(0, width = respBits) 34 | def RESP_EXOKAY = UInt(1, width = respBits) 35 | def RESP_SLVERR = UInt(2, width = respBits) 36 | def RESP_DECERR = UInt(3, width = respBits) 37 | } 38 | -------------------------------------------------------------------------------- /src/main/scala/amba/axi4/package.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | 3 | package freechips.rocketchip.amba 4 | 5 | import Chisel._ 6 | import freechips.rocketchip.diplomacy._ 7 | 8 | package object axi4 9 | { 10 | type AXI4Node = SimpleNodeHandle[AXI4MasterPortParameters, AXI4SlavePortParameters, AXI4EdgeParameters, AXI4Bundle] 11 | type AXI4OutwardNode = OutwardNodeHandle[AXI4MasterPortParameters, AXI4SlavePortParameters, AXI4EdgeParameters, AXI4Bundle] 12 | type AXI4InwardNode = InwardNodeHandle[AXI4MasterPortParameters, AXI4SlavePortParameters, AXI4EdgeParameters, AXI4Bundle] 13 | 14 | implicit class AXI4ClockDomainCrossing(val x: HasClockDomainCrossing) extends AnyVal { 15 | def crossIn (n: AXI4InwardNode) (implicit valName: ValName) = AXI4InwardCrossingHelper(valName.name, x, n) 16 | def crossOut(n: AXI4OutwardNode)(implicit valName: ValName) = AXI4OutwardCrossingHelper(valName.name, x, n) 17 | def cross(n: AXI4InwardNode) (implicit valName: ValName) = crossIn(n) 18 | def cross(n: AXI4OutwardNode)(implicit valName: ValName) = crossOut(n) 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/main/scala/debug/DebugBundles.scala: -------------------------------------------------------------------------------- 1 | 2 | package freechips.rocketchip.debug 3 | 4 | import chisel3._ 5 | 6 | 7 | class DebugCSRIntIO extends Bundle() { 8 | // from CSR/core's perspective 9 | val dmiInterrupt = Input(Bool()) 10 | val ndmiInterrupts = Output(UInt(16.W)) 11 | val eipOutstanding = Output(Bool()) 12 | val csrOutInt = Output(Bool()) 13 | val reg_mip = Output(UInt(64.W)) 14 | } 15 | 16 | -------------------------------------------------------------------------------- /src/main/scala/debug/Stats.scala: -------------------------------------------------------------------------------- 1 | 2 | package freechips.rocketchip.debug 3 | 4 | import chisel3._ 5 | import chisel3.internal.naming.chiselName 6 | import chisel3.util.experimental.BoringUtils 7 | 8 | @chiselName 9 | class Stats () { 10 | val counter = RegInit(0.U(48.W)) 11 | } 12 | 13 | object Stats { 14 | @chiselName 15 | def apply(stat_name: String, hartId: Int): Stats = { 16 | val c = new freechips.rocketchip.debug.Stats() 17 | val dump_trigger = Wire(Bool()) 18 | dump_trigger := false.B 19 | BoringUtils.addSink(dump_trigger, "DumpFlag" + hartId.toString) 20 | when (dump_trigger) { 21 | printf("Stats::") 22 | stat_name.foreach{c => printf(p"${Character(c.toInt.U)}")} 23 | printf(": %d\n", c.counter) 24 | } 25 | c 26 | } 27 | } -------------------------------------------------------------------------------- /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/tilelink/BusBlocker.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | 3 | package freechips.rocketchip.devices.tilelink 4 | 5 | import Chisel._ 6 | import freechips.rocketchip.config.Parameters 7 | import freechips.rocketchip.diplomacy._ 8 | import freechips.rocketchip.regmapper._ 9 | import freechips.rocketchip.tilelink._ 10 | import freechips.rocketchip.util._ 11 | 12 | /** BasicBusBlocker uses a single bit register to control whether 13 | * accesses of all types are allowed to proceed or bypassed to 14 | * a /dev/null device. It has a second bit register to report 15 | * whether any requests are pending on either path. 16 | */ 17 | 18 | case class BasicBusBlockerParams( 19 | controlAddress: BigInt, 20 | controlBeatBytes: Int, 21 | deviceBeatBytes: Int, 22 | deadlock: Boolean = false) 23 | 24 | class BasicBusBlocker(params: BasicBusBlockerParams)(implicit p: Parameters) 25 | extends TLBusBypassBase(params.deviceBeatBytes, params.deadlock) 26 | { 27 | val device = new SimpleDevice("basic-bus-blocker", Seq("sifive,basic-bus-blocker0")) 28 | 29 | val controlNode = TLRegisterNode( 30 | address = Seq(AddressSet(params.controlAddress, 0xFFF)), 31 | device = device, 32 | beatBytes = params.controlBeatBytes) 33 | 34 | lazy val module = new 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 | } 49 | -------------------------------------------------------------------------------- /src/main/scala/devices/tilelink/CanHaveBuiltInDevices.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | 3 | package freechips.rocketchip.devices.tilelink 4 | 5 | import freechips.rocketchip.config.Parameters 6 | import freechips.rocketchip.diplomacy._ 7 | import freechips.rocketchip.tilelink._ 8 | 9 | trait HasBuiltInDeviceParams { 10 | val zeroDevice: Option[AddressSet] 11 | val errorDevice: Option[DevNullParams] 12 | } 13 | 14 | /* Optionally add some built-in devices to a bus wrapper */ 15 | trait CanHaveBuiltInDevices { this: TLBusWrapper => 16 | 17 | def attachBuiltInDevices(params: HasBuiltInDeviceParams) { 18 | params.errorDevice.foreach { dnp => LazyScope("wrapped_error_device") { 19 | val error = LazyModule(new TLError( 20 | params = dnp, 21 | beatBytes = beatBytes)) 22 | error.node := TLBuffer() := outwardNode 23 | }} 24 | 25 | params.zeroDevice.foreach { addr => LazyScope("wrapped_zero_device") { 26 | val zero = LazyModule(new TLZero( 27 | address = addr, 28 | beatBytes = beatBytes)) 29 | zero.node := TLFragmenter(beatBytes, blockBytes) := TLBuffer() := outwardNode 30 | }} 31 | } 32 | } 33 | 34 | -------------------------------------------------------------------------------- /src/main/scala/devices/tilelink/Deadlock.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | 3 | package freechips.rocketchip.devices.tilelink 4 | 5 | import Chisel._ 6 | import freechips.rocketchip.config.Parameters 7 | import freechips.rocketchip.diplomacy._ 8 | 9 | /** Adds a /dev/null slave that does not raise ready for any incoming traffic. 10 | * !!! WARNING: This device WILL cause your bus to deadlock for as long as you 11 | * continue to send traffic to it !!! 12 | */ 13 | class TLDeadlock(params: DevNullParams, beatBytes: Int = 4)(implicit p: Parameters) 14 | extends DevNullDevice(params, beatBytes, new SimpleDevice("deadlock-device", Seq("sifive,deadlock0"))) 15 | { 16 | lazy val module = new LazyModuleImp(this) { 17 | val (in, _) = node.in(0) 18 | in.a.ready := Bool(false) 19 | in.b.valid := Bool(false) 20 | in.c.ready := Bool(false) 21 | in.d.valid := Bool(false) 22 | in.e.ready := Bool(false) 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/main/scala/devices/tilelink/Zero.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | 3 | package freechips.rocketchip.devices.tilelink 4 | 5 | import Chisel._ 6 | import freechips.rocketchip.config.Parameters 7 | import freechips.rocketchip.diplomacy._ 8 | import freechips.rocketchip.tilelink.TLMessages 9 | 10 | /** This /dev/null device accepts single beat gets/puts, as well as atomics. 11 | * Response data is always 0. Reequests to write data have no effect. 12 | */ 13 | class TLZero(address: AddressSet, beatBytes: Int = 4)(implicit p: Parameters) 14 | extends DevNullDevice( 15 | params = DevNullParams( 16 | address = List(address), 17 | maxAtomic = beatBytes, 18 | maxTransfer = beatBytes, 19 | region = RegionType.UNCACHED, 20 | executable = true, 21 | mayDenyGet = false, 22 | mayDenyPut = false), 23 | beatBytes = beatBytes, 24 | device = new SimpleDevice("rom", Seq("ucbbar,cacheable-zero0"))) { 25 | lazy val module = new LazyModuleImp(this) { 26 | val (in, edge) = node.in(0) 27 | 28 | val a = Queue(in.a, 2) 29 | 30 | a.ready := in.d.ready 31 | in.d.valid := a.valid 32 | in.d.bits := edge.AccessAck(a.bits) 33 | in.d.bits.opcode := TLMessages.adResponse(edge.opcode(a.bits)) 34 | 35 | // Tie off unused channels 36 | in.b.valid := Bool(false) 37 | in.c.ready := Bool(true) 38 | in.e.ready := Bool(true) 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/main/scala/diplomacy/ClockDomain.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | 3 | package freechips.rocketchip.diplomacy 4 | 5 | trait HasClockDomainCrossing extends LazyScope { this: LazyModule => } 6 | -------------------------------------------------------------------------------- /src/main/scala/diplomacy/Clone.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | 3 | package freechips.rocketchip.diplomacy 4 | 5 | import Chisel._ 6 | import chisel3.shim.CloneModule 7 | 8 | final class CloneLazyModule private (val base: LazyModule) 9 | { 10 | // Pay special attention to the .iParams and .oParams of the node, which 11 | // indicate the parameters a stand-in master must supply. 12 | def clone[DI, UI, EI, BI <: Data, DO, UO, EO, BO <: Data](node: NodeHandle[DI, UI, EI, BI, DO, UO, EO, BO])(implicit valName: ValName) = 13 | new MixedTestNode(node, this) 14 | 15 | protected[diplomacy] lazy val io = CloneModule(base.module) 16 | } 17 | 18 | object CloneLazyModule 19 | { 20 | def apply(base: LazyModule) = new CloneLazyModule(base) 21 | } 22 | -------------------------------------------------------------------------------- /src/main/scala/diplomacy/FixedClockResource.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | 3 | package freechips.rocketchip.diplomacy 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) { 17 | ResourceBinding { Resource(dev, "clocks").bind(ResourceReference(device.label)) } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/main/scala/diplomacy/JSON.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | 3 | package freechips.rocketchip.diplomacy 4 | 5 | import scala.collection.immutable.SortedMap 6 | 7 | object JSON 8 | { 9 | def apply(res: ResourceValue): String = { 10 | val root = res match { 11 | case ResourceMap(value, _) => value.toList match { 12 | case Seq(("/", Seq(subtree))) => subtree 13 | case _ => res 14 | } 15 | case _ => res 16 | } 17 | helper(root)(SortedMap(map(root):_*)).mkString 18 | } 19 | 20 | private def map(res: ResourceValue, path: String = ""): Seq[(String, String)] = res match { 21 | case ResourceMap(value, labels) => { 22 | labels.map(_ -> path) ++ 23 | value.flatMap { case (key, seq) => seq.flatMap(map(_, path + "/" + key)) } 24 | } 25 | case _ => Nil 26 | } 27 | 28 | private def helper(res: ResourceValue)(implicit path: Map[String, String]): Seq[String] = res match { 29 | case ResourceAddress(address, ResourcePermissions(r, w, x, c, a)) => 30 | AddressRange.fromSets(address).map { case AddressRange(base, size) => 31 | s"""{"base":${base},"size":${size},"r":${r},"w":${w},"x":${x},"c":${c},"a":${a}}"""} 32 | case ResourceMapping(address, offset, ResourcePermissions(r, w, x, c, a)) => 33 | AddressRange.fromSets(address).map { case AddressRange(base, size) => 34 | s"""{"base":${base},"size":${size},"offset":${offset},"r":${r},"w":${w},"x":${x},"c":${c},"a":${a}}"""} 35 | case ResourceInt(value) => Seq(value.toString) 36 | case ResourceString(value) => Seq("\"" + value + "\"") 37 | case ResourceReference(value) => Seq("\"&" + path(value) + "\"") 38 | case ResourceAlias(value) => Seq("\"&" + path(value) + "\"") 39 | case ResourceMap(value, _) => { 40 | Seq(value.map { 41 | case (key, Seq(v: ResourceMap)) => s""""${key}":${helper(v).mkString}""" 42 | case (key, seq) => s""""${key}":[${seq.flatMap(helper).mkString(",")}]""" 43 | }.mkString("{", ",", "}")) 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/main/scala/diplomacy/ValName.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | 3 | package freechips.rocketchip.diplomacy 4 | 5 | import scala.language.experimental.macros 6 | import freechips.rocketchip.macros.ValNameImpl 7 | 8 | case class ValName(name: String) 9 | 10 | object ValName 11 | { 12 | implicit def materialize(implicit x: ValNameImpl): ValName = ValName(x.name) 13 | } 14 | -------------------------------------------------------------------------------- /src/main/scala/diplomaticobjectmodel/DiplomaticObjectModel.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | 3 | package freechips.rocketchip.diplomaticobjectmodel 4 | 5 | import freechips.rocketchip.diplomaticobjectmodel.model.OMComponent 6 | 7 | import scala.collection.mutable.ListBuffer 8 | 9 | class OMCollector { 10 | def getComponent(): Seq[OMComponent] = Nil 11 | } 12 | 13 | object DiplomaticObjectModel { 14 | private val doms = ListBuffer[OMCollector]() 15 | 16 | def add(d: OMCollector): Unit = { 17 | doms += (d) 18 | } 19 | 20 | def getComponents(): OMComponent = { 21 | doms.flatMap(_.getComponent()).head 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/main/scala/diplomaticobjectmodel/model/ISASpecifications.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | 3 | package freechips.rocketchip.diplomaticobjectmodel.model 4 | 5 | sealed trait PrivilegedArchitectureExtension extends OMEnum 6 | case object MachineLevelISA extends PrivilegedArchitectureExtension 7 | case object SupervisorLevelISA extends PrivilegedArchitectureExtension 8 | 9 | object PrivilegedArchitectureExtensions { 10 | val specifications = Map[PrivilegedArchitectureExtension, String]( 11 | MachineLevelISA -> "Machine-Level ISA", 12 | SupervisorLevelISA -> "Supervisor-Level ISA" 13 | ) 14 | 15 | def specVersion(extension: PrivilegedArchitectureExtension, version: String): OMSpecification = OMSpecification(specifications(extension), version) 16 | } 17 | 18 | object BaseExtensions { 19 | val specifications = Map[OMBaseInstructionSet, String]( 20 | RV32E -> "RV32E Base Integer Instruction Set", 21 | RV32I -> "RV32I Base Integer Instruction Set", 22 | RV64I -> "RV64I Base Integer Instruction Set" 23 | ) 24 | 25 | def specVersion(extension: OMBaseInstructionSet, version: String): OMSpecification = OMSpecification(specifications(extension), version) 26 | } 27 | 28 | object ISAExtensions { 29 | val specifications = Map[OMExtensionType, String]( 30 | M -> "M Standard Extension for Integer Multiplication and Division", 31 | A -> "A Standard Extension for Atomic Instruction", 32 | F -> "F Standard Extension for Single-Precision Floating-Point", 33 | D -> "D Standard Extension for Double-Precision Floating-Point", 34 | C -> "C Standard Extension for Compressed Instruction", 35 | U -> "The RISC‑V Instruction Set Manual, Volume II: Privileged Architecture", 36 | S -> "Supervisor-Level ISA" 37 | ) 38 | 39 | def specVersion(extension: OMExtensionType, version: String): OMSpecification = OMSpecification(specifications(extension), version) 40 | } 41 | -------------------------------------------------------------------------------- /src/main/scala/diplomaticobjectmodel/model/OMBase.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | 3 | package freechips.rocketchip.diplomaticobjectmodel.model 4 | 5 | trait OMBaseType 6 | 7 | trait OMEnum extends OMBaseType 8 | 9 | trait OMCompoundType extends OMBaseType 10 | 11 | trait OMComponent extends OMCompoundType 12 | 13 | -------------------------------------------------------------------------------- /src/main/scala/diplomaticobjectmodel/model/OMBranchPredictor.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | 3 | package freechips.rocketchip.diplomaticobjectmodel.model 4 | 5 | trait OMBranchPredictor extends OMComponent 6 | -------------------------------------------------------------------------------- /src/main/scala/diplomaticobjectmodel/model/OMCLINT.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | 3 | package freechips.rocketchip.diplomaticobjectmodel.model 4 | 5 | case class OMCLINT( 6 | memoryRegions: Seq[OMMemoryRegion], 7 | interrupts: Seq[OMInterrupt], 8 | specifications: List[OMSpecification], 9 | _types: Seq[String] = Seq("OMCLINT", "OMDevice", "OMComponent", "OMCompoundType") 10 | ) extends OMDevice 11 | -------------------------------------------------------------------------------- /src/main/scala/diplomaticobjectmodel/model/OMCaches.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | 3 | package freechips.rocketchip.diplomaticobjectmodel.model 4 | 5 | trait OMCache extends OMDevice { 6 | def memoryRegions(): Seq[OMMemoryRegion] 7 | def interrupts(): Seq[OMInterrupt] 8 | def nSets: Int 9 | def nWays: Int 10 | def blockSizeBytes: Int 11 | def dataMemorySizeBytes: Int 12 | def dataECC: Option[OMECC] 13 | def tagECC: Option[OMECC] 14 | def nTLBEntries: Int 15 | } 16 | 17 | case class OMICache( 18 | memoryRegions: Seq[OMMemoryRegion], 19 | interrupts: Seq[OMInterrupt], 20 | nSets: Int, 21 | nWays: Int, 22 | blockSizeBytes: Int, 23 | dataMemorySizeBytes: Int, 24 | dataECC: Option[OMECC], 25 | tagECC: Option[OMECC], 26 | nTLBEntries: Int, 27 | maxTimSize: Int, 28 | _types: Seq[String] = Seq("OMICache", "OMCache", "OMDevice", "OMComponent", "OMCompoundType") 29 | ) extends OMCache 30 | 31 | case class OMDCache( 32 | memoryRegions: Seq[OMMemoryRegion], 33 | interrupts: Seq[OMInterrupt], 34 | nSets: Int, 35 | nWays: Int, 36 | blockSizeBytes: Int, 37 | dataMemorySizeBytes: Int, 38 | dataECC: Option[OMECC], 39 | tagECC: Option[OMECC], 40 | nTLBEntries: Int, 41 | _types: Seq[String] = Seq("OMDCache", "OMCache", "OMDevice", "OMComponent", "OMCompoundType") 42 | ) extends OMCache 43 | 44 | case class OMECC(code: String) extends OMBaseType 45 | 46 | object OMECC { 47 | val Identity = OMECC("Identity") 48 | val Parity = OMECC("Parity") 49 | val SEC = OMECC("SEC") 50 | val SECDED = OMECC("SECDED") 51 | 52 | def getCode(code: String): OMECC = { 53 | code.toLowerCase match { 54 | case "identity" => OMECC.Identity 55 | case "parity" => OMECC.Parity 56 | case "sec" => OMECC.SEC 57 | case "secded" => OMECC.SECDED 58 | case _ => throw new IllegalArgumentException(s"ERROR: invalid getCode arg: $code") 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/main/scala/diplomaticobjectmodel/model/OMCore.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | 3 | package freechips.rocketchip.diplomaticobjectmodel.model 4 | 5 | trait OMCore extends OMComponent{ 6 | def isa: OMISA 7 | def mulDiv: Option[OMMulDiv] 8 | def performanceMonitor: Option[OMPerformanceMonitor] 9 | def pmp: Option[OMPMP] 10 | def documentationName: String 11 | def hartIds: Seq[Int] 12 | def hasVectoredInterrupts: Boolean 13 | def interruptLatency: Int 14 | def nLocalInterrupts: Int 15 | def nBreakpoints: Int 16 | } 17 | -------------------------------------------------------------------------------- /src/main/scala/diplomaticobjectmodel/model/OMDebug.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | 3 | package freechips.rocketchip.diplomaticobjectmodel.model 4 | 5 | sealed trait DebugInterfaceType extends OMEnum 6 | case object JTAG extends DebugInterfaceType 7 | case object CJTAG extends DebugInterfaceType 8 | case object DMI extends DebugInterfaceType 9 | 10 | case class OMDebug( 11 | memoryRegions: Seq[OMMemoryRegion], 12 | interrupts: Seq[OMInterrupt], 13 | specifications: List[OMSpecification], 14 | nAbstractDataWords: Int, 15 | nProgramBufferWords: Int, 16 | interfaceType: DebugInterfaceType, 17 | _types: Seq[String] = Seq("OMDebug", "OMDevice", "OMComponent", "OMCompoundType") 18 | ) extends OMDevice 19 | 20 | object OMDebug { 21 | 22 | def getDebugInterfaceType(jtag: Boolean, cjtag: Boolean, dmi: Boolean): DebugInterfaceType = { 23 | if (jtag) { JTAG } 24 | else if (cjtag) { CJTAG } 25 | else if (dmi) { DMI } 26 | else { throw new IllegalArgumentException } 27 | } 28 | } -------------------------------------------------------------------------------- /src/main/scala/diplomaticobjectmodel/model/OMDevice.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | 3 | package freechips.rocketchip.diplomaticobjectmodel.model 4 | 5 | trait OMDevice extends OMComponent { 6 | def memoryRegions: Seq[OMMemoryRegion] 7 | def interrupts: Seq[OMInterrupt] 8 | } 9 | 10 | -------------------------------------------------------------------------------- /src/main/scala/diplomaticobjectmodel/model/OMFPU.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | 3 | package freechips.rocketchip.diplomaticobjectmodel.model 4 | 5 | case class OMFPU( 6 | fLen: Int, 7 | _types: Seq[String] = Seq("OMFPU", "OMComponent", "OMCompoundType") 8 | ) extends OMComponent 9 | -------------------------------------------------------------------------------- /src/main/scala/diplomaticobjectmodel/model/OMInterrupts.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | 3 | package freechips.rocketchip.diplomaticobjectmodel.model 4 | 5 | case class OMInterrupt( 6 | receiver: String, // TODO Reference 7 | numberAtReceiver: BigInt, 8 | name: String, 9 | _types: Seq[String] = Seq("OMInterrupt", "OMCompoundType") 10 | ) extends OMCompoundType 11 | 12 | -------------------------------------------------------------------------------- /src/main/scala/diplomaticobjectmodel/model/OMMemory.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | 3 | package freechips.rocketchip.diplomaticobjectmodel.model 4 | 5 | case class OMMemory( 6 | description: String, 7 | addressWidth: Int, 8 | dataWidth: Int, 9 | depth: Int, 10 | writeMaskGranularity: Int, 11 | _types: Seq[String] = Seq("OMMemory") 12 | ) 13 | 14 | -------------------------------------------------------------------------------- /src/main/scala/diplomaticobjectmodel/model/OMMulDiv.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | 3 | package freechips.rocketchip.diplomaticobjectmodel.model 4 | 5 | import freechips.rocketchip.rocket.MulDivParams 6 | 7 | case class OMMulDiv( 8 | divideBitsPerCycle: Int, 9 | divideMaxLatency: Int, 10 | divideMinLatency: Int, 11 | multiplyBitsPerCycle: Int, 12 | multiplyFullyPipelined: Boolean, 13 | multiplyMaxLatency: Int, 14 | multiplyMinLatency: Int, 15 | _types: Seq[String] = Seq("OMMulDiv", "OMComponent", "OMCompoundType") 16 | ) extends OMComponent 17 | 18 | 19 | object OMMulDiv { 20 | def makeOMI(md: MulDivParams, xLen: Int): OMMulDiv = { 21 | val mulMinLatency = 22 | if (md.mulUnroll > 0) { 23 | if (md.mulEarlyOut) { 2 } 24 | else { xLen/md.mulUnroll } 25 | } 26 | else { xLen } 27 | 28 | val divMinLatency = 29 | if (md.divUnroll > 0) { 30 | if (md.divEarlyOut) { 3 } 31 | else { 2 } 32 | } 33 | else { xLen } 34 | 35 | OMMulDiv( 36 | divideBitsPerCycle = md.divUnroll, 37 | divideMaxLatency = xLen / md.divUnroll, 38 | divideMinLatency = divMinLatency, 39 | multiplyBitsPerCycle = md.mulUnroll, 40 | multiplyFullyPipelined = md.mulUnroll == xLen, 41 | multiplyMaxLatency = xLen / md.mulUnroll, 42 | multiplyMinLatency = mulMinLatency 43 | ) 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/main/scala/diplomaticobjectmodel/model/OMPLIC.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | 3 | package freechips.rocketchip.diplomaticobjectmodel.model 4 | 5 | sealed trait OMPrivilegeMode extends OMEnum 6 | case object OMMachineMode extends OMPrivilegeMode 7 | case object OMSupervisorMode extends OMPrivilegeMode 8 | case object OMUserMode extends OMPrivilegeMode 9 | 10 | object OMModes { 11 | def getModes(useVM: Boolean): Seq[OMPrivilegeMode] = { 12 | useVM match { 13 | case false => Seq(OMMachineMode) 14 | case true => Seq(OMMachineMode, OMSupervisorMode) 15 | } 16 | } 17 | } 18 | 19 | case class OMInterruptTarget( 20 | hartId: Int, 21 | modes: Seq[OMPrivilegeMode], 22 | _types: Seq[String] = Seq("OMInterruptTarget", "OMCompoundType") 23 | ) extends OMCompoundType 24 | 25 | case class OMPLIC( 26 | memoryRegions: Seq[OMMemoryRegion], 27 | interrupts: Seq[OMInterrupt], 28 | specifications: Seq[OMSpecification], 29 | latency: Int, 30 | nPriorities: Int, 31 | targets: Seq[OMInterruptTarget], 32 | _types: Seq[String] = Seq("OMPLIC", "OMDevice", "OMComponent", "OMCompoundType") 33 | ) extends OMDevice 34 | 35 | object OMPLIC { 36 | def getMode(length: Int): Seq[OMPrivilegeMode] = { 37 | length match { 38 | case 1 => Seq(OMMachineMode) 39 | case 2 => Seq(OMMachineMode,OMSupervisorMode) 40 | case _ => throw new IllegalArgumentException 41 | } 42 | } 43 | } -------------------------------------------------------------------------------- /src/main/scala/diplomaticobjectmodel/model/OMPMP.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | 3 | package freechips.rocketchip.diplomaticobjectmodel.model 4 | 5 | import freechips.rocketchip.rocket.RocketCoreParams 6 | 7 | case class OMPMP( 8 | specifications: Seq[OMSpecification], 9 | nRegions: Int, 10 | granularity: Int, 11 | _types: Seq[String] = Seq("OMPMP", "OMComponent", "OMCompoundType") 12 | ) extends OMComponent 13 | 14 | object OMPMP { 15 | def pmp(coreParams: RocketCoreParams): Option[OMPMP] = { 16 | if (coreParams.pmpGranularity > 0 || coreParams.nPMPs > 0) { 17 | Some(OMPMP( 18 | specifications = List[OMSpecification](PrivilegedArchitectureExtensions.specVersion(MachineLevelISA, "1.10")), 19 | nRegions = coreParams.nPMPs, 20 | granularity = coreParams.pmpGranularity 21 | )) 22 | } 23 | else { 24 | None 25 | } 26 | } 27 | } -------------------------------------------------------------------------------- /src/main/scala/diplomaticobjectmodel/model/OMPerformanceMonitor.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | 3 | package freechips.rocketchip.diplomaticobjectmodel.model 4 | 5 | import freechips.rocketchip.rocket.RocketCoreParams 6 | 7 | case class OMPerformanceMonitor( 8 | specifications: List[OMSpecification], 9 | hasBasicCounters: Boolean, 10 | nAdditionalCounters: Int, 11 | _types: Seq[String] = Seq("OMPerformanceMonitor", "OMComponent", "OMCompoundType") 12 | ) extends OMComponent 13 | 14 | object PerformanceMonitor { 15 | def permon(coreParams: RocketCoreParams): Option[OMPerformanceMonitor] = { 16 | if (coreParams.haveBasicCounters || coreParams.nPerfCounters > 0) { 17 | Some(OMPerformanceMonitor( 18 | specifications = List[OMSpecification](PrivilegedArchitectureExtensions.specVersion(MachineLevelISA, "1.10")), 19 | hasBasicCounters = coreParams.haveBasicCounters, 20 | nAdditionalCounters = coreParams.nPerfCounters 21 | )) 22 | } 23 | else { 24 | None 25 | } 26 | } 27 | } -------------------------------------------------------------------------------- /src/main/scala/diplomaticobjectmodel/model/OMRTLModule.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | 3 | package freechips.rocketchip.diplomaticobjectmodel.model 4 | 5 | trait RTLComponent extends OMCompoundType 6 | 7 | trait OMSignal extends RTLComponent { 8 | def name: String // This will always be the name of the signal on the top-level module 9 | def description: Option[String] 10 | } 11 | 12 | case class OMClock( 13 | name: String, 14 | description: Option[String] 15 | ) extends OMSignal 16 | 17 | case class OMClockRelationship( 18 | clock0: String, 19 | clock1: String, 20 | relationship: String, 21 | ) extends RTLComponent 22 | 23 | trait OMSignalAssertionLevel extends OMEnum 24 | trait High extends OMSignalAssertionLevel 25 | trait Low extends OMSignalAssertionLevel 26 | 27 | trait Synchronicity extends OMEnum 28 | trait Synchronous extends Synchronicity 29 | trait Asynchronous extends Synchronicity 30 | 31 | case class OMRTLReset( 32 | activeEdge: Option[OMSignalAssertionLevel], 33 | clock: String, // This will always be the name of the clock signal on the to p-level module 34 | synchronicity: Option[Synchronicity] 35 | ) 36 | 37 | case class OMResetVector( 38 | width: Int 39 | ) 40 | 41 | case class OMRTLInterface( 42 | clocks: List[OMClock], 43 | clockRelationships: List[OMClockRelationship], 44 | resets: List[OMRTLReset] 45 | ) extends RTLComponent 46 | 47 | case class OMRTLModule( 48 | moduleName: String, 49 | instanceName: Option[String], // TODO: This does not exist for the top-level module because the top-level module is the only one that is not instantiated 50 | hierarchicalId: Option[String], // Full dotted path from the root, where the root is described as a module name while all other path components are instance names 51 | interface: OMRTLInterface 52 | ) -------------------------------------------------------------------------------- /src/main/scala/diplomaticobjectmodel/model/OMRegFieldAccessType.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | 3 | package freechips.rocketchip.diplomaticobjectmodel.model 4 | 5 | sealed trait OMRegFieldAccessType extends OMEnum 6 | case object R extends OMRegFieldAccessType 7 | case object W extends OMRegFieldAccessType 8 | case object RW extends OMRegFieldAccessType 9 | 10 | -------------------------------------------------------------------------------- /src/main/scala/diplomaticobjectmodel/model/OMRegFieldRdAction.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | 3 | package freechips.rocketchip.diplomaticobjectmodel.model 4 | 5 | sealed trait OMRegFieldRdAction extends OMEnum 6 | case object RFRA_CLEAR extends OMRegFieldRdAction 7 | case object RFRA_SET extends OMRegFieldRdAction 8 | case object RFRA_MODIFY extends OMRegFieldRdAction 9 | 10 | -------------------------------------------------------------------------------- /src/main/scala/diplomaticobjectmodel/model/OMRegFieldWrType.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | 3 | package freechips.rocketchip.diplomaticobjectmodel.model 4 | 5 | /* The following enum names come from IP-XACT */ 6 | sealed trait OMRegFieldWrType extends OMEnum 7 | case object RFWT_ONE_TO_CLEAR extends OMRegFieldWrType 8 | case object RFWT_ONE_TO_SET extends OMRegFieldWrType 9 | case object RFWT_ONE_TO_TOGGLE extends OMRegFieldWrType 10 | case object RFWT_ZERO_TO_CLEAR extends OMRegFieldWrType 11 | case object RFWT_ZERO_TO_SET extends OMRegFieldWrType 12 | case object RFWT_ZERO_TO_TOGGLE extends OMRegFieldWrType 13 | case object RFWT_CLEAR extends OMRegFieldWrType 14 | case object RFWT_SET extends OMRegFieldWrType 15 | case object RFWT_MODIFY extends OMRegFieldWrType 16 | 17 | -------------------------------------------------------------------------------- /src/main/scala/diplomaticobjectmodel/model/OMSpecification.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | 3 | package freechips.rocketchip.diplomaticobjectmodel.model 4 | 5 | case class OMSpecification( 6 | name: String, 7 | version: String, 8 | _types: Seq[String] = Seq("OMSpecification") 9 | ) 10 | -------------------------------------------------------------------------------- /src/main/scala/groundtest/Configs.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | // See LICENSE.Berkeley for license details. 3 | 4 | package freechips.rocketchip.groundtest 5 | 6 | import Chisel._ 7 | import freechips.rocketchip.config.Config 8 | import freechips.rocketchip.subsystem._ 9 | import freechips.rocketchip.rocket.{DCacheParams} 10 | import freechips.rocketchip.tile.{MaxHartIdBits, XLen} 11 | 12 | /** Actual testing target Configs */ 13 | 14 | class TraceGenConfig extends Config(new WithTraceGen(List.fill(2){ DCacheParams(nSets = 16, nWays = 1) }) ++ new BaseSubsystemConfig) 15 | 16 | class TraceGenBufferlessConfig extends Config(new WithBufferlessBroadcastHub ++ new TraceGenConfig) 17 | 18 | /* Composable Configs to set individual parameters */ 19 | 20 | class WithTraceGen(params: Seq[DCacheParams], nReqs: Int = 8192) extends Config((site, here, up) => { 21 | case GroundTestTilesKey => params.map { dcp => TraceGenParams( 22 | dcache = Some(dcp), 23 | wordBits = site(XLen), 24 | addrBits = 32, 25 | addrBag = { 26 | val nSets = 2 27 | val nWays = 1 28 | val blockOffset = site(SystemBusKey).blockOffset 29 | val nBeats = site(SystemBusKey).blockBeats 30 | List.tabulate(4 * nWays) { i => 31 | Seq.tabulate(nBeats) { j => BigInt((j * 8) + ((i * nSets) << blockOffset)) } 32 | }.flatten 33 | }, 34 | maxRequests = nReqs, 35 | memStart = site(ExtMem).get.master.base, 36 | numGens = params.size) 37 | } 38 | case MaxHartIdBits => log2Up(params.size) 39 | }) 40 | -------------------------------------------------------------------------------- /src/main/scala/groundtest/Generator.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | 3 | package freechips.rocketchip.groundtest 4 | 5 | import freechips.rocketchip.util.GeneratorApp 6 | 7 | object Generator extends GeneratorApp { 8 | val longName = names.topModuleProject + "." + names.configs 9 | generateFirrtl 10 | generateAnno 11 | generateTestSuiteMakefrags // TODO: Needed only for legacy make targets 12 | generateArtefacts 13 | } 14 | -------------------------------------------------------------------------------- /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 Chisel._ 6 | import freechips.rocketchip.util.ValidMux 7 | 8 | class GroundTestStatus extends Bundle { 9 | val finished = Bool(OUTPUT) 10 | val timeout = Valid(UInt(width = 4)) 11 | val error = Valid(UInt(width = 4)) 12 | } 13 | 14 | object DebugCombiner { 15 | def apply(debugs: Seq[GroundTestStatus]): GroundTestStatus = { 16 | val out = Wire(new GroundTestStatus) 17 | out.finished := debugs.map(_.finished).reduce(_ && _) 18 | out.timeout := ValidMux(debugs.map(_.timeout)) 19 | out.error := ValidMux(debugs.map(_.error)) 20 | out 21 | } 22 | } 23 | 24 | -------------------------------------------------------------------------------- /src/main/scala/groundtest/TestHarness.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | 3 | package freechips.rocketchip.groundtest 4 | 5 | import Chisel._ 6 | 7 | import freechips.rocketchip.config.Parameters 8 | import freechips.rocketchip.diplomacy.LazyModule 9 | 10 | class TestHarness(implicit p: Parameters) extends Module { 11 | val io = new Bundle { val success = Bool(OUTPUT) } 12 | val dut = Module(LazyModule(new GroundTestSubsystem).module) 13 | io.success := dut.success 14 | dut.connectSimAXIMem() 15 | } 16 | -------------------------------------------------------------------------------- /src/main/scala/interrupts/Bundles.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | 3 | package freechips.rocketchip.interrupts 4 | 5 | import Chisel._ 6 | import freechips.rocketchip.diplomacy._ 7 | import freechips.rocketchip.util._ 8 | 9 | class SyncInterrupts(params: IntEdge) extends GenericParameterizedBundle(params) 10 | { 11 | val sync = Vec(params.source.num, Bool()) 12 | } 13 | -------------------------------------------------------------------------------- /src/main/scala/interrupts/CrossingHelper.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | 3 | package freechips.rocketchip.interrupts 4 | 5 | import freechips.rocketchip.config.Parameters 6 | import freechips.rocketchip.diplomacy._ 7 | 8 | case class IntInwardCrossingHelper(name: String, scope: LazyScope, node: IntInwardNode) { 9 | def apply(xing: ClockCrossingType = NoCrossing, alreadyRegistered: Boolean = false)(implicit p: Parameters): IntInwardNode = { 10 | xing match { 11 | case x: AsynchronousCrossing => 12 | node :*=* scope { IntSyncCrossingSink(x.sinkSync) :*=* IntSyncNameNode(name) } :*=* IntSyncNameNode(name) :*=* IntSyncCrossingSource(alreadyRegistered) 13 | case RationalCrossing(_) => 14 | node :*=* scope { IntSyncCrossingSink(1) :*=* IntSyncNameNode(name) } :*=* IntSyncNameNode(name) :*=* IntSyncCrossingSource(alreadyRegistered) 15 | case SynchronousCrossing(_) => 16 | node :*=* scope { IntSyncCrossingSink(0) :*=* IntSyncNameNode(name) } :*=* IntSyncNameNode(name) :*=* IntSyncCrossingSource(alreadyRegistered) 17 | } 18 | } 19 | } 20 | 21 | case class IntOutwardCrossingHelper(name: String, scope: LazyScope, node: IntOutwardNode) { 22 | def apply(xing: ClockCrossingType = NoCrossing, alreadyRegistered: Boolean = false)(implicit p: Parameters): IntOutwardNode = { 23 | xing match { 24 | case x: AsynchronousCrossing => 25 | IntSyncCrossingSink(x.sinkSync) :*=* IntSyncNameNode(name) :*=* scope { IntSyncNameNode(name) :*=* IntSyncCrossingSource(alreadyRegistered) } :*=* node 26 | case RationalCrossing(_) => 27 | IntSyncCrossingSink(1) :*=* IntSyncNameNode(name) :*=* scope { IntSyncNameNode(name) :*=* IntSyncCrossingSource(alreadyRegistered) } :*=* node 28 | case SynchronousCrossing(buffer) => 29 | IntSyncCrossingSink(0) :*=* IntSyncNameNode(name) :*=* scope { IntSyncNameNode(name) :*=* IntSyncCrossingSource(alreadyRegistered) } :*=* node 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/main/scala/interrupts/NullIntSource.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | 3 | package freechips.rocketchip.interrupts 4 | 5 | import Chisel._ 6 | import freechips.rocketchip.config.Parameters 7 | import freechips.rocketchip.diplomacy._ 8 | 9 | /** Useful for stubbing out parts of an interrupt interface where certain devices might be missing */ 10 | class NullIntSource(num: Int = 1, ports: Int = 1, sources: Int = 1)(implicit p: Parameters) extends LazyModule 11 | { 12 | val intnode = IntSourceNode(IntSourcePortSimple(num, ports, sources)) 13 | 14 | lazy val module = new LazyModuleImp(this) { 15 | intnode.out.foreach { case (o, _) => o.foreach { _ := false.B } } 16 | } 17 | } 18 | 19 | object NullIntSource { 20 | def apply(num: Int = 1, ports: Int = 1, sources: Int = 1)(implicit p: Parameters): IntNode = { 21 | val null_int_source = LazyModule(new NullIntSource(num, ports, sources)) 22 | null_int_source.intnode 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/main/scala/interrupts/RegisterRouter.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | 3 | package freechips.rocketchip.interrupts 4 | 5 | import chisel3._ 6 | import freechips.rocketchip.diplomacy._ 7 | import freechips.rocketchip.regmapper._ 8 | 9 | /** Mix this trait into a RegisterRouter to be able to attach its interrupt sources to an interrupt bus */ 10 | trait HasInterruptSources { this: RegisterRouter[_] => 11 | def nInterrupts: Int 12 | protected val intnode = IntSourceNode(IntSourcePortSimple(num = nInterrupts, resources = Seq(Resource(device, "int")))) 13 | 14 | // Externally, this helper should be used to connect the interrupts to a bus 15 | val intXing: IntOutwardCrossingHelper = this.crossOut(intnode) 16 | 17 | // Internally, this wire should be used to drive interrupt values 18 | val interrupts: ModuleValue[Vec[Bool]] = InModuleBody { if (intnode.out.isEmpty) Vec(0, Bool()) else intnode.out(0)._1 } 19 | } 20 | -------------------------------------------------------------------------------- /src/main/scala/interrupts/Xbar.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | 3 | package freechips.rocketchip.interrupts 4 | 5 | import Chisel._ 6 | import freechips.rocketchip.config.Parameters 7 | import freechips.rocketchip.diplomacy._ 8 | 9 | class IntXbar()(implicit p: Parameters) extends LazyModule 10 | { 11 | val intnode = IntNexusNode( 12 | sinkFn = { _ => IntSinkPortParameters(Seq(IntSinkParameters())) }, 13 | sourceFn = { seq => 14 | IntSourcePortParameters((seq zip seq.map(_.num).scanLeft(0)(_+_).init).map { 15 | case (s, o) => s.sources.map(z => z.copy(range = z.range.offset(o))) 16 | }.flatten) 17 | }) 18 | 19 | lazy val module = new LazyModuleImp(this) { 20 | val cat = intnode.in.map { case (i, e) => i.take(e.source.num) }.flatten 21 | intnode.out.foreach { case (o, _) => o := cat } 22 | } 23 | } 24 | 25 | object IntXbar { 26 | def apply(implicit p: Parameters): IntNode = { 27 | val xbar = LazyModule(new IntXbar) 28 | xbar.intnode 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/main/scala/interrupts/package.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | 3 | package freechips.rocketchip 4 | 5 | import Chisel._ 6 | import freechips.rocketchip.diplomacy._ 7 | 8 | package object interrupts 9 | { 10 | type IntInwardNode = InwardNodeHandle[IntSourcePortParameters, IntSinkPortParameters, IntEdge, Vec[Bool]] 11 | type IntOutwardNode = OutwardNodeHandle[IntSourcePortParameters, IntSinkPortParameters, IntEdge, Vec[Bool]] 12 | type IntNode = SimpleNodeHandle[IntSourcePortParameters, IntSinkPortParameters, IntEdge, Vec[Bool]] 13 | 14 | implicit class IntClockDomainCrossing(val x: HasClockDomainCrossing) extends AnyVal { 15 | def crossIn (n: IntInwardNode) (implicit valName: ValName) = IntInwardCrossingHelper(valName.name, x, n) 16 | def crossOut(n: IntOutwardNode)(implicit valName: ValName) = IntOutwardCrossingHelper(valName.name, x, n) 17 | def cross(n: IntInwardNode) (implicit valName: ValName) = crossIn(n) 18 | def cross(n: IntOutwardNode)(implicit valName: ValName) = crossOut(n) 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/main/scala/jtag/JtagUtils.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.jtag for license details. 2 | 3 | package freechips.rocketchip.jtag 4 | 5 | import Chisel._ 6 | //import chisel3._ 7 | import chisel3.util._ 8 | 9 | class JTAGIdcodeBundle extends Bundle { 10 | val version = UInt(4.W) 11 | val partNumber = UInt(16.W) 12 | val mfrId = UInt(11.W) 13 | val always1 = UInt(1.W) 14 | } 15 | 16 | object JtagIdcode { 17 | /** Generates a JTAG IDCODE as a 32-bit integer, using the format in 12.1.1d. 18 | */ 19 | def apply(version: Int, partNumber: Int, mfrId: Int): BigInt = { 20 | require(version < (1 << 4), "version field must be 4 bits at most") 21 | require(partNumber < (1 << 16), "part number must be 16 bits at most") 22 | require(mfrId < (1 << 11), "manufacturer identity must be 11 bits at most") 23 | BigInt(version) << 28 | BigInt(partNumber) << 12 | BigInt(mfrId) << 1 | 1 24 | } 25 | 26 | /** A dummy manufacturer ID, not to be used per 12.2.1b since bus masters may shift this out to 27 | * determine the end of a bus. 28 | */ 29 | def dummyMfrId: Int = 0x7f 30 | } 31 | -------------------------------------------------------------------------------- /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/lvna/Dirty.scala: -------------------------------------------------------------------------------- 1 | 2 | package freechips.rocketchip.config 3 | 4 | 5 | case object MemInitAddr extends Field[BigInt] 6 | 7 | class LvNADirtyConfig extends Config ((site, here, up) => { 8 | case MemInitAddr => BigInt(0x80000000L) 9 | }) 10 | -------------------------------------------------------------------------------- /src/main/scala/lvna/ILA.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | 3 | package ila 4 | 5 | import Chisel._ 6 | 7 | class ILABundle extends Bundle { 8 | val hartid = UInt(OUTPUT, 2) 9 | 10 | val csr_time = UInt(OUTPUT, 32) 11 | val pc = UInt(OUTPUT, 40) 12 | val instr_valid = Bool(OUTPUT) 13 | val instr = UInt(OUTPUT, 32) 14 | 15 | val rd_wen = Bool(OUTPUT) 16 | val rd_waddr = UInt(OUTPUT, 5) 17 | val rd_wdata = UInt(OUTPUT, 64) 18 | 19 | val rs_raddr = UInt(OUTPUT, 5) 20 | val rs_rdata = UInt(OUTPUT, 64) 21 | val rt_raddr = UInt(OUTPUT, 5) 22 | val rt_rdata = UInt(OUTPUT, 64) 23 | } 24 | 25 | class BoomCSRILABundle extends Bundle { 26 | val trigger = Bool(OUTPUT) 27 | val reg_mip = UInt(OUTPUT, 64) 28 | val csr_rw_cmd = UInt(OUTPUT, 3) 29 | val csr_rw_wdata = UInt(OUTPUT, 64) 30 | val wr_mip = Bool(OUTPUT) 31 | val reg_mbadaddr = UInt(OUTPUT, 64) 32 | } 33 | 34 | class FPGATraceBaseBundle(val commWidth: Int) extends Bundle { 35 | val traces = Vec(commWidth, new Bundle { 36 | val valid = Bool() 37 | val commPriv = UInt(OUTPUT, 2) 38 | val commPC = UInt(OUTPUT, 40) 39 | val commInst = UInt(OUTPUT, 32) 40 | 41 | val isFloat = Bool() 42 | val wbValueValid = Bool() 43 | val wbARFN = UInt(OUTPUT, 6) 44 | val wbValue = UInt(OUTPUT, 64) 45 | 46 | }) 47 | } 48 | 49 | class FPGATraceExtraBundle extends Bundle { // For rocket's delayed wb 50 | val delayedWbValid = Bool() 51 | val wbARFN = UInt(OUTPUT, 6) 52 | val wbValue = UInt(OUTPUT, 64) 53 | } 54 | -------------------------------------------------------------------------------- /src/main/scala/lvna/LvNATop.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | 3 | package freechips.rocketchip.system 4 | 5 | import Chisel._ 6 | import freechips.rocketchip.config.Parameters 7 | import lvna._ 8 | import sifive.blocks.devices.uart._ 9 | 10 | 11 | class LvNABoomEmuTop(implicit p: Parameters) extends ExampleBoomSystem 12 | with HasPeripheryUART 13 | with HasBoomControlPlane 14 | { 15 | override lazy val module = new LvNABoomEmuTopModule(this) 16 | } 17 | 18 | class LvNABoomEmuTopModule[+L <: LvNABoomEmuTop](_outer: L) extends ExampleBoomSystemModuleImp(_outer) 19 | with HasPeripheryUARTModuleImp 20 | with HasControlPlaneBoomModuleImpl 21 | 22 | class LvNAEmuTop(implicit p: Parameters) extends ExampleRocketSystem 23 | with HasPeripheryUART 24 | with HasControlPlane 25 | with BindL2WayMask 26 | { 27 | override lazy val module = new LvNAEmuTopModule(this) 28 | } 29 | 30 | class LvNAEmuTopModule[+L <: LvNAEmuTop](_outer: L) extends ExampleRocketSystemModuleImp(_outer) 31 | with HasPeripheryUARTModuleImp 32 | with HasControlPlaneModuleImpl 33 | with BindL2WayMaskModuleImp 34 | 35 | 36 | class LvNAFPGATop(implicit p: Parameters) extends ExampleRocketSystem 37 | with HasControlPlane 38 | with BindL2WayMask 39 | { 40 | override lazy val module = new LvNAFPGATopModule(this) 41 | } 42 | 43 | class LvNAFPGATopModule[+L <: LvNAFPGATop](_outer: L) extends ExampleRocketSystemModuleImp(_outer) 44 | with HasControlPlaneModuleImpl 45 | with BindL2WayMaskModuleImp 46 | 47 | //class LvNAFPGATopAHB(implicit p: Parameters) extends ExampleRocketSystemAHB 48 | // 49 | //class LvNAFPGATopAHBModule[+L <: LvNAFPGATopAHB](_outer: L) extends ExampleRocketSystemModuleAHBImp(_outer) 50 | 51 | class LvNABoomFPGATopModule[+L <: LvNABoomFPGATop](_outer: L) extends ExampleBoomSystemModuleImp(_outer) 52 | with HasControlPlaneBoomModuleImpl 53 | 54 | class LvNABoomFPGATop(implicit p: Parameters) extends ExampleBoomSystem 55 | with HasBoomControlPlane 56 | { 57 | override lazy val module = new LvNABoomFPGATopModule(this) 58 | } 59 | 60 | -------------------------------------------------------------------------------- /src/main/scala/lvna/controlplane/TokenBucketNode.scala: -------------------------------------------------------------------------------- 1 | package lvna 2 | 3 | import chisel3._ 4 | import freechips.rocketchip.config._ 5 | import freechips.rocketchip.diplomacy._ 6 | import freechips.rocketchip.tilelink._ 7 | import freechips.rocketchip.util._ 8 | import boom.common._ 9 | 10 | class TokenBucketNode(implicit p: Parameters) extends LazyModule { 11 | val node = TLIdentityNode() 12 | lazy val module = new TokenBucketNodeImp(this) 13 | } 14 | 15 | class TokenBucketNodeImp(outer: TokenBucketNode) extends LazyModuleImp(outer) { 16 | val (bundleIn, _) = outer.node.in.unzip 17 | val (bundleOut, _) = outer.node.out.unzip 18 | 19 | val bucketIO = IO(Flipped(new BucketIO())) 20 | 21 | // require(bundleIn.size == 1, s"[TokenBucket] Only expect one link for a hart, current link count is ${bundleIn.size}") 22 | val (in, out) = (bundleIn zip bundleOut).head 23 | 24 | val phy = in.a.bits.address < p(MemInitAddr).U 25 | 26 | bucketIO.dsid := in.a.bits.dsid 27 | bucketIO.fire := out.a.ready && out.a.valid && !phy 28 | bucketIO.size := (1.U << in.a.bits.size) >> 6 29 | 30 | out.a.valid := in.a.valid && (phy || bucketIO.enable) 31 | in.a.ready := out.a.ready && (phy || bucketIO.enable) 32 | if (DEBUG_TB_FETCH) { 33 | when(in.a.valid && !out.a.valid) { 34 | printf(p"request blocked by token bucket: 0x${Hexadecimal(in.a.bits.address)}\n") 35 | } 36 | when(out.a.valid && !in.a.ready) { 37 | printf(p"response blocked by token bucket: 0x${Hexadecimal(in.a.bits.address)}\n") 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/main/scala/regmapper/Annotation.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | 3 | package freechips.rocketchip.regmapper 4 | 5 | import chisel3.experimental.{ChiselAnnotation, RawModule, RunFirrtlTransform} 6 | import firrtl.annotations._ 7 | import firrtl.{CircuitForm, CircuitState, LowForm, Transform} 8 | 9 | case class RegFieldDescSer( 10 | byteOffset: String, 11 | bitOffset: Int, 12 | bitWidth: Int, 13 | name: String, 14 | resetValue: BigInt, 15 | accessType: String, 16 | wrType: String, 17 | rdAction: String, 18 | desc: String, 19 | group: String, 20 | groupDesc: String, 21 | volatile: Boolean = false, 22 | hasReset: Boolean = false, 23 | enumerations: Map[BigInt, (String, String)] = Map() 24 | ) 25 | 26 | case class RegistersSer( 27 | displayName: String, 28 | deviceName: String, 29 | baseAddress: BigInt, 30 | regFields: Seq[RegFieldDescSer] 31 | ) 32 | -------------------------------------------------------------------------------- /src/main/scala/regmapper/DescribedReg.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE for license details. 2 | package freechips.rocketchip.regmapper 3 | 4 | import Chisel._ 5 | import chisel3.experimental._ 6 | import chisel3.{Input, Output} 7 | import freechips.rocketchip.util.{AsyncResetRegVec, SimpleRegIO} 8 | 9 | object DescribedReg { 10 | import freechips.rocketchip.regmapper.RegFieldAccessType._ 11 | import freechips.rocketchip.regmapper.RegFieldWrType._ 12 | import freechips.rocketchip.regmapper.RegFieldRdAction._ 13 | 14 | def apply[T <: Data]( 15 | gen: => T, 16 | name: String, 17 | desc: String, 18 | reset: Option[T], 19 | access: RegFieldAccessType = RW, 20 | wrType: Option[RegFieldWrType] = None, 21 | rdAction: Option[RegFieldRdAction] = None, 22 | volatile: Boolean = false, 23 | enumerations: Map[BigInt, (String, String)] = Map()): (T, RegFieldDesc) = { 24 | val rdesc = RegFieldDesc(name, desc, None, None, 25 | access, wrType, rdAction, volatile, reset.map{_.litValue}, enumerations) 26 | val reg = reset.map{i => RegInit(i)}.getOrElse(Reg(gen)) 27 | reg.suggestName(name + "_reg") 28 | (reg, rdesc) 29 | } 30 | 31 | def async( 32 | width: Int, 33 | name: String, 34 | desc: String, 35 | reset: Int, 36 | access: RegFieldAccessType = RW, 37 | wrType: Option[RegFieldWrType] = None, 38 | rdAction: Option[RegFieldRdAction] = None, 39 | volatile: Boolean = false, 40 | enumerations: Map[BigInt, (String, String)] = Map()): (SimpleRegIO, RegFieldDesc) = { 41 | val rdesc = RegFieldDesc(name, desc, None, None, 42 | access, wrType, rdAction, volatile, Some(reset), enumerations) 43 | val reg = Module(new AsyncResetRegVec(w = width, init = reset)) 44 | reg.suggestName(name + "_reg") 45 | (reg.io, rdesc) 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/main/scala/regmapper/RegisterRouter.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | 3 | package freechips.rocketchip.regmapper 4 | 5 | import Chisel._ 6 | import freechips.rocketchip.config.Parameters 7 | import freechips.rocketchip.diplomacy._ 8 | import freechips.rocketchip.interrupts._ 9 | import freechips.rocketchip.tilelink._ 10 | 11 | case class RegisterRouterParams( 12 | name: String, 13 | compat: Seq[String], 14 | base: BigInt, 15 | size: BigInt = 4096, 16 | concurrency: Int = 0, 17 | beatBytes: Int = 4, 18 | undefZero: Boolean = true, 19 | executable: Boolean = false) 20 | 21 | abstract class RegisterRouter[T <: Data](devParams: RegisterRouterParams)(implicit p: Parameters) 22 | extends LazyModule 23 | with HasClockDomainCrossing { 24 | 25 | require (isPow2(devParams.size)) 26 | val address = Seq(AddressSet(devParams.base, devParams.size-1)) 27 | val concurrency = devParams.concurrency 28 | val beatBytes = devParams.beatBytes 29 | val undefZero = devParams.undefZero 30 | val executable = devParams.executable 31 | val device = new SimpleDevice(devParams.name, devParams.compat) { 32 | override def describe(resources: ResourceBindings): Description = { 33 | val Description(name, mapping) = super.describe(resources) 34 | Description(name, mapping ++ extraResources(resources)) 35 | } 36 | } 37 | // Allow devices to extend the DTS mapping 38 | def extraResources(resources: ResourceBindings) = Map[String, Seq[ResourceValue]]() 39 | 40 | protected def regmap(mapping: RegField.Map*): Unit 41 | } 42 | 43 | abstract class IORegisterRouter[T <: Data](devParams: RegisterRouterParams, portBundle: => T)(implicit p: Parameters) 44 | extends RegisterRouter(devParams) { 45 | val ioNode = BundleBridgeSource(() => portBundle.cloneType) 46 | val port = InModuleBody { ioNode.bundle } 47 | } 48 | -------------------------------------------------------------------------------- /src/main/scala/rocket/Events.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.Berkeley for license details. 2 | // See LICENSE.SiFive for license details. 3 | 4 | package freechips.rocketchip.rocket 5 | 6 | import Chisel._ 7 | import freechips.rocketchip.util._ 8 | import freechips.rocketchip.util.property._ 9 | 10 | class EventSet(gate: (UInt, UInt) => Bool, events: Seq[(String, () => Bool)]) { 11 | def size = events.size 12 | def hits = events.map(_._2()).asUInt 13 | def check(mask: UInt) = gate(mask, hits) 14 | def dump() { 15 | for (((name, _), i) <- events.zipWithIndex) 16 | when (check(1.U << i)) { printf(s"Event $name\n") } 17 | } 18 | def withCovers { 19 | events.zipWithIndex.foreach { 20 | case ((name, func), i) => cover(gate((1.U << i), (func() << i)), name) 21 | } 22 | } 23 | } 24 | 25 | class EventSets(val eventSets: Seq[EventSet]) { 26 | def maskEventSelector(eventSel: UInt): UInt = { 27 | // allow full associativity between counters and event sets (for now?) 28 | val setMask = (BigInt(1) << log2Ceil(eventSets.size)) - 1 29 | val maskMask = ((BigInt(1) << eventSets.map(_.size).max) - 1) << eventSetIdBits 30 | eventSel & (setMask | maskMask).U 31 | } 32 | 33 | private def decode(counter: UInt): (UInt, UInt) = { 34 | require(eventSets.size <= (1 << eventSetIdBits)) 35 | (counter(log2Ceil(eventSets.size)-1, 0), counter >> eventSetIdBits) 36 | } 37 | 38 | def evaluate(eventSel: UInt): Bool = { 39 | val (set, mask) = decode(eventSel) 40 | val sets = eventSets map (_ check mask) 41 | sets(set) 42 | } 43 | 44 | def cover() = eventSets.foreach { _ withCovers } 45 | 46 | private def eventSetIdBits = 8 47 | } 48 | -------------------------------------------------------------------------------- /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/sifive-blocks/devices/uart/UARTCtrlRegs.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE for license details. 2 | package sifive.blocks.devices.uart 3 | 4 | object UARTCtrlRegs { 5 | val rxfifo = 0x00 6 | val txfifo = 0x04 7 | val stat = 0x08 8 | val ctrl = 0x0c 9 | 10 | /* 11 | val txfifo = 0x00 12 | val rxfifo = 0x04 13 | val txctrl = 0x08 14 | val txmark = 0x0a 15 | val rxctrl = 0x0c 16 | val rxmark = 0x0e 17 | 18 | val ie = 0x10 19 | val ip = 0x14 20 | val div = 0x18 21 | */ 22 | } 23 | -------------------------------------------------------------------------------- /src/main/scala/sifive-blocks/devices/uart/UARTPeriphery.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE for license details. 2 | package sifive.blocks.devices.uart 3 | 4 | import Chisel._ 5 | import freechips.rocketchip.tilelink._ 6 | import freechips.rocketchip.config.Field 7 | import freechips.rocketchip.subsystem._ 8 | import freechips.rocketchip.diplomacy.{LazyModule, LazyModuleImp} 9 | 10 | //case object PeripheryUARTKey extends Field[Seq[UARTParams]] 11 | 12 | trait HasPeripheryUART { this: BaseSubsystem => 13 | val uartParams = Seq.tabulate(p(NTiles)) { i => //p(PeripheryUARTKey) 14 | UARTParams(address = BigInt(0x60000000L + i * 0x1000L)) 15 | } 16 | val uarts = uartParams map { params => 17 | val uart = LazyModule(new TLUART(pbus.beatBytes, params)) 18 | 19 | pbus.toVariableWidthSlave(Some("uart")) { uart.node } 20 | ibus.fromSync := uart.intnode 21 | uart 22 | } 23 | } 24 | 25 | trait HasPeripheryUARTModuleImp extends LazyModuleImp { 26 | val outer: HasPeripheryUART 27 | val io = IO(new Bundle { 28 | val uarts = Vec(outer.uartParams.size, new UARTPortIO) 29 | }) 30 | (io.uarts zip outer.uarts).foreach { case (io, device) => 31 | io <> device.module.io.port 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/main/scala/sifive-blocks/devices/uart/UARTPrinter.scala: -------------------------------------------------------------------------------- 1 | package sifive.blocks.devices.uart 2 | 3 | import chisel3._ 4 | 5 | // if you have a clock 6 | // use UARTPrinter 7 | // if do not have a clock(eg: you can not extend Module) 8 | // you can use UARTPrinterWrapper 9 | class UARTPrinter(filename: String) extends BlackBox( 10 | Map("FILENAME" -> chisel3.core.StringParam(filename))) { 11 | val io = IO(new Bundle { 12 | val clock = Input(Clock()) 13 | val valid = Input(Bool()) 14 | val data = Input(UInt(8.W)) // Always expect an ASCII character 15 | }) 16 | } 17 | 18 | class UARTPrinterWrapper(filename: String) extends Module { 19 | val io = IO(new Bundle { 20 | val valid = Input(Bool()) 21 | val data = Input(UInt(8.W)) // Always expect an ASCII character 22 | }) 23 | 24 | val printer = Module(new UARTPrinter(filename)) 25 | printer.io.clock := clock; 26 | printer.io.valid := io.valid; 27 | printer.io.data := io.data; 28 | } 29 | -------------------------------------------------------------------------------- /src/main/scala/sifive-blocks/util/DeglitchShiftRegister.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE for license details. 2 | package sifive.blocks.util 3 | 4 | import Chisel._ 5 | 6 | //Allows us to specify a different clock for a shift register 7 | // and to force input to be high for > 1 cycle. 8 | class DeglitchShiftRegister(shift: Int) extends Module { 9 | val io = new Bundle { 10 | val d = Bool(INPUT) 11 | val q = Bool(OUTPUT) 12 | } 13 | val sync = ShiftRegister(io.d, shift) 14 | val last = ShiftRegister(sync, 1) 15 | io.q := sync & last 16 | } 17 | 18 | object DeglitchShiftRegister { 19 | def apply (shift: Int, d: Bool, clock: Clock, 20 | name: Option[String] = None): Bool = { 21 | val deglitch = Module (new DeglitchShiftRegister(shift)) 22 | name.foreach(deglitch.suggestName(_)) 23 | deglitch.clock := clock 24 | deglitch.reset := Bool(false) 25 | deglitch.io.d := d 26 | deglitch.io.q 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/main/scala/sifive-blocks/util/RegMapFIFO.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE for license details. 2 | package sifive.blocks.util 3 | 4 | import Chisel._ 5 | import freechips.rocketchip.regmapper._ 6 | 7 | // MSB indicates full status 8 | object NonBlockingEnqueue { 9 | def apply(enq: DecoupledIO[UInt], regWidth: Int = 32): Seq[RegField] = { 10 | val enqWidth = enq.bits.getWidth 11 | require(enqWidth > 0) 12 | require(regWidth > enqWidth) 13 | Seq( 14 | RegField(enqWidth, 15 | RegReadFn(UInt(0)), 16 | RegWriteFn((valid, data) => { 17 | enq.valid := valid 18 | enq.bits := data 19 | Bool(true) 20 | })), 21 | RegField(regWidth - enqWidth - 1), 22 | RegField.r(1, !enq.ready)) 23 | } 24 | } 25 | 26 | // MSB indicates empty status 27 | object NonBlockingDequeue { 28 | def apply(deq: DecoupledIO[UInt], regWidth: Int = 32): Seq[RegField] = { 29 | val deqWidth = deq.bits.getWidth 30 | require(deqWidth > 0) 31 | require(regWidth > deqWidth) 32 | Seq( 33 | RegField.r(deqWidth, 34 | RegReadFn(ready => { 35 | deq.ready := ready 36 | (Bool(true), deq.bits) 37 | })), 38 | RegField(regWidth - deqWidth - 1), 39 | RegField.r(1, !deq.valid)) 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/main/scala/sifive-blocks/util/ResetCatchAndSync.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE for license details. 2 | package sifive.blocks.util 3 | 4 | import Chisel._ 5 | import freechips.rocketchip.util.AsyncResetRegVec 6 | 7 | /** Reset: asynchronous assert, 8 | * synchronous de-assert 9 | * 10 | */ 11 | 12 | class ResetCatchAndSync (sync: Int = 3) extends Module { 13 | 14 | val io = new Bundle { 15 | val sync_reset = Bool(OUTPUT) 16 | } 17 | 18 | val reset_n_catch_reg = Module (new AsyncResetRegVec(sync, 0)) 19 | 20 | reset_n_catch_reg.io.en := Bool(true) 21 | reset_n_catch_reg.io.d := Cat(Bool(true), reset_n_catch_reg.io.q >> 1) 22 | 23 | io.sync_reset := ~reset_n_catch_reg.io.q(0) 24 | 25 | } 26 | 27 | object ResetCatchAndSync { 28 | 29 | def apply(clk: Clock, rst: Bool, sync: Int = 3, name: Option[String] = None): Bool = { 30 | 31 | val catcher = Module (new ResetCatchAndSync(sync)) 32 | if (name.isDefined) {catcher.suggestName(name.get)} 33 | catcher.clock := clk 34 | catcher.reset := rst 35 | 36 | catcher.io.sync_reset 37 | } 38 | 39 | def apply(clk: Clock, rst: Bool, sync: Int, name: String): Bool = apply(clk, rst, sync, Some(name)) 40 | def apply(clk: Clock, rst: Bool, name: String): Bool = apply(clk, rst, name = Some(name)) 41 | 42 | } 43 | -------------------------------------------------------------------------------- /src/main/scala/sifive-blocks/util/SRLatch.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE for license details. 2 | package sifive.blocks.util 3 | 4 | import Chisel._ 5 | 6 | class SRLatch extends BlackBox { 7 | val io = new Bundle { 8 | val set = Bool(INPUT) 9 | val reset = Bool(INPUT) 10 | val q = Bool(OUTPUT) 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/main/scala/sifive-blocks/util/ShiftReg.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE for license details. 2 | package sifive.blocks.util 3 | 4 | import Chisel._ 5 | 6 | object ShiftRegisterInit { 7 | def apply[T <: Data](in: T, n: Int, init: T): T = 8 | (0 until n).foldLeft(in) { 9 | case (next, _) => Reg(next, next = next, init = init) 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/main/scala/sifive-blocks/vsrc/SRLatch.v: -------------------------------------------------------------------------------- 1 | // See LICENSE for license details. 2 | module SRLatch ( 3 | input set, 4 | input reset, 5 | output q 6 | ); 7 | 8 | reg latch; 9 | 10 | // synopsys async_set_reset "set" 11 | // synopsys one_hot "set, reset" 12 | always @(set or reset) 13 | begin 14 | if (set) 15 | latch <= 1'b1; 16 | else if (reset) 17 | latch <= 1'b0; 18 | end 19 | 20 | assign q = latch; 21 | 22 | endmodule 23 | -------------------------------------------------------------------------------- /src/main/scala/subsystem/FrontBus.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | 3 | package freechips.rocketchip.subsystem 4 | 5 | import freechips.rocketchip.config.{Parameters} 6 | import freechips.rocketchip.devices.tilelink._ 7 | import freechips.rocketchip.diplomacy._ 8 | import freechips.rocketchip.tilelink._ 9 | 10 | case class FrontBusParams( 11 | beatBytes: Int, 12 | blockBytes: Int, 13 | zeroDevice: Option[AddressSet] = None, 14 | errorDevice: Option[DevNullParams] = None) 15 | extends HasTLBusParams with HasBuiltInDeviceParams 16 | 17 | class FrontBus(params: FrontBusParams)(implicit p: Parameters) 18 | extends TLBusWrapper(params, "front_bus") 19 | with CanHaveBuiltInDevices 20 | with CanAttachTLMasters 21 | with HasTLXbarPhy { 22 | attachBuiltInDevices(params) 23 | } 24 | -------------------------------------------------------------------------------- /src/main/scala/subsystem/RTC.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | 3 | package freechips.rocketchip.subsystem 4 | 5 | import Chisel._ 6 | import freechips.rocketchip.config._ 7 | import freechips.rocketchip.diplomacy.{LazyModuleImp, DTSTimebase} 8 | import freechips.rocketchip.devices.tilelink.CanHavePeripheryCLINT 9 | 10 | case object RTCPeriod extends Field[Int] 11 | 12 | trait HasRTCModuleImp extends LazyModuleImp { 13 | val outer: BaseSubsystem with CanHavePeripheryCLINT 14 | private val pbusFreq = outer.p(PeripheryBusKey).frequency 15 | private val rtcFreq = outer.p(DTSTimebase) 16 | private val internalPeriod: BigInt = pbusFreq / rtcFreq 17 | 18 | // check whether pbusFreq >= rtcFreq 19 | require(internalPeriod > 0) 20 | // check wehther the integer division is within 5% of the real division 21 | require((pbusFreq - rtcFreq * internalPeriod) * 100 / pbusFreq <= 5) 22 | 23 | // Use the static period to toggle the RTC 24 | val (_, int_rtc_tick) = Counter(true.B, internalPeriod.toInt) 25 | //val (_, int_rtc_tick) = Counter(true.B, p(RTCPeriod)) 26 | 27 | outer.clintOpt.foreach { clint => 28 | clint.module.io.rtcTick := int_rtc_tick 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/main/scala/subsystem/ResetVector.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | 3 | package freechips.rocketchip.subsystem 4 | 5 | import Chisel._ 6 | 7 | /** A single place for all tiles to find out the reset vector */ 8 | trait HasResetVectorWire { 9 | def resetVectorBits: Int 10 | val global_reset_vector = Wire(UInt(width = resetVectorBits)) 11 | } 12 | -------------------------------------------------------------------------------- /src/main/scala/subsystem/SystemBus.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | 3 | package freechips.rocketchip.subsystem 4 | 5 | import Chisel._ 6 | import freechips.rocketchip.config.{Parameters} 7 | import freechips.rocketchip.devices.tilelink._ 8 | import freechips.rocketchip.diplomacy._ 9 | import freechips.rocketchip.tilelink._ 10 | import freechips.rocketchip.util._ 11 | import lvna.TokenBucketNode 12 | 13 | case class SystemBusParams( 14 | beatBytes: Int, 15 | blockBytes: Int, 16 | policy: TLArbiter.Policy = TLArbiter.roundRobin, 17 | zeroDevice: Option[AddressSet] = None, 18 | errorDevice: Option[DevNullParams] = None) 19 | extends HasTLBusParams with HasBuiltInDeviceParams 20 | 21 | class SystemBus(params: SystemBusParams)(implicit p: Parameters) 22 | extends TLBusWrapper(params, "system_bus") 23 | with CanHaveBuiltInDevices 24 | with CanAttachTLSlaves 25 | with CanAttachTLMasters 26 | with HasTLXbarPhy { 27 | attachBuiltInDevices(params) 28 | 29 | def fromTile 30 | (name: Option[String], buffer: BufferParams = BufferParams.none, cork: Option[Boolean] = None, token: Option[TokenBucketNode] = None) 31 | (gen: => TLOutwardNode): NoHandle = { 32 | // println(s"inward node size: ${inwardNode.inward.inputs.size}") 33 | // println(s"outward node size: ${gen.outward.outputs.size}") 34 | from("tile" named name) { 35 | if (token.isDefined) { 36 | inwardNode := token.get.node :=* TLBuffer(buffer) :=* TLFIFOFixer(TLFIFOFixer.allUncacheable) :=* gen 37 | } 38 | else { 39 | inwardNode :=* TLBuffer(buffer) :=* TLFIFOFixer(TLFIFOFixer.allUncacheable) :=* gen 40 | } 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/main/scala/tile/CustomCSRs.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | 3 | package freechips.rocketchip.tile 4 | 5 | import chisel3._ 6 | 7 | import freechips.rocketchip.config.Parameters 8 | 9 | case class CustomCSR(id: Int, mask: BigInt, init: Option[BigInt]) 10 | 11 | object CustomCSR { 12 | def constant(id: Int, value: BigInt): CustomCSR = CustomCSR(id, BigInt(0), Some(value)) 13 | } 14 | 15 | class CustomCSRIO(implicit p: Parameters) extends CoreBundle { 16 | val wen = Bool() 17 | val wdata = UInt(xLen.W) 18 | val value = UInt(xLen.W) 19 | } 20 | 21 | class CustomCSRs(implicit p: Parameters) extends CoreBundle { 22 | // Not all cores have these CSRs, but those that do should follow the same 23 | // numbering conventions. So we list them here but default them to None. 24 | protected def bpmCSRId = 0x7c0 25 | protected def bpmCSR: Option[CustomCSR] = None 26 | 27 | protected def chickenCSRId = 0x7c1 28 | protected def chickenCSR: Option[CustomCSR] = None 29 | 30 | // If you override this, you'll want to concatenate super.decls 31 | def decls: Seq[CustomCSR] = bpmCSR.toSeq ++ chickenCSR 32 | 33 | val csrs = Vec(decls.size, new CustomCSRIO) 34 | 35 | def flushBTB = getOrElse(bpmCSR, _.wen, false.B) 36 | def bpmStatic = getOrElse(bpmCSR, _.value(0), false.B) 37 | def disableDCacheClockGate = getOrElse(chickenCSR, _.value(0), true.B) 38 | def disableICacheClockGate = getOrElse(chickenCSR, _.value(1), true.B) 39 | def disableCoreClockGate = getOrElse(chickenCSR, _.value(2), true.B) 40 | 41 | protected def getByIdOrElse[T](id: Int, f: CustomCSRIO => T, alt: T): T = { 42 | val idx = decls.indexWhere(_.id == id) 43 | if (idx < 0) alt else f(csrs(idx)) 44 | } 45 | 46 | protected def getOrElse[T](csr: Option[CustomCSR], f: CustomCSRIO => T, alt: T): T = 47 | csr.map(c => getByIdOrElse(c.id, f, alt)).getOrElse(alt) 48 | } 49 | -------------------------------------------------------------------------------- /src/main/scala/tile/L1Cache.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | 3 | package freechips.rocketchip.tile 4 | 5 | import Chisel._ 6 | 7 | import freechips.rocketchip.config.{Parameters, Field} 8 | import freechips.rocketchip.subsystem.CacheBlockBytes 9 | import freechips.rocketchip.tilelink.ClientMetadata 10 | import freechips.rocketchip.util._ 11 | 12 | trait L1CacheParams { 13 | def nSets: Int 14 | def nWays: Int 15 | def rowBits: Int 16 | def nTLBEntries: Int 17 | def blockBytes: Int // TODO this is ignored in favor of p(CacheBlockBytes) in BaseTile 18 | } 19 | 20 | trait HasL1CacheParameters extends HasTileParameters { 21 | val cacheParams: L1CacheParams 22 | private val bundleParams = p(SharedMemoryTLEdge).bundle 23 | 24 | def nSets = cacheParams.nSets 25 | def blockOffBits = lgCacheBlockBytes 26 | def idxBits = log2Up(cacheParams.nSets) 27 | def untagBits = blockOffBits + idxBits 28 | def tagBits = bundleParams.addressBits - (if (usingVM) untagBits min pgIdxBits else untagBits) 29 | def nWays = cacheParams.nWays 30 | def wayBits = log2Up(nWays) 31 | def isDM = nWays == 1 32 | def rowBits = cacheParams.rowBits 33 | def rowBytes = rowBits/8 34 | def rowOffBits = log2Up(rowBytes) 35 | def nTLBEntries = cacheParams.nTLBEntries 36 | 37 | def cacheDataBits = bundleParams.dataBits 38 | def cacheDataBeats = (cacheBlockBytes * 8) / cacheDataBits 39 | def refillCycles = cacheDataBeats 40 | } 41 | 42 | abstract class L1CacheModule(implicit val p: Parameters) extends Module 43 | with HasL1CacheParameters 44 | 45 | abstract class L1CacheBundle(implicit val p: Parameters) extends ParameterizedBundle()(p) 46 | with HasL1CacheParameters 47 | -------------------------------------------------------------------------------- /src/main/scala/tilelink/CrossingHelper.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | 3 | package freechips.rocketchip.tilelink 4 | 5 | import freechips.rocketchip.config.Parameters 6 | import freechips.rocketchip.diplomacy._ 7 | import freechips.rocketchip.util.RationalDirection 8 | 9 | case class TLInwardCrossingHelper(name: String, scope: LazyScope, node: TLInwardNode) { 10 | def apply(xing: ClockCrossingType = NoCrossing)(implicit p: Parameters): TLInwardNode = { 11 | xing match { 12 | case x: AsynchronousCrossing => 13 | node :*=* scope { TLAsyncCrossingSink(x.asSinkParams) :*=* TLAsyncNameNode(name) } :*=* TLAsyncNameNode(name) :*=* TLAsyncCrossingSource(x.sourceSync) 14 | case RationalCrossing(direction) => 15 | node :*=* scope { TLRationalCrossingSink(direction.flip) :*=* TLRationalNameNode(name) } :*=* TLRationalNameNode(name) :*=* TLRationalCrossingSource() 16 | case SynchronousCrossing(buffer) => 17 | node :*=* scope { TLBuffer(buffer) :*=* TLNameNode(name) } :*=* TLNameNode(name) 18 | } 19 | } 20 | } 21 | 22 | case class TLOutwardCrossingHelper(name: String, scope: LazyScope, node: TLOutwardNode) { 23 | def apply(xing: ClockCrossingType = NoCrossing)(implicit p: Parameters): TLOutwardNode = { 24 | xing match { 25 | case x: AsynchronousCrossing => 26 | TLAsyncCrossingSink(x.asSinkParams) :*=* TLAsyncNameNode(name) :*=* scope { TLAsyncNameNode(name) :*=* TLAsyncCrossingSource(x.sourceSync) } :*=* node 27 | case RationalCrossing(direction) => 28 | TLRationalCrossingSink(direction) :*=* TLRationalNameNode(name) :*=* scope { TLRationalNameNode(name) :*=* TLRationalCrossingSource() } :*=* node 29 | case SynchronousCrossing(buffer) => 30 | TLNameNode(name) :*=* scope { TLNameNode(name) :*=* TLBuffer(buffer) } :*=* node 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/main/scala/tilelink/Dumper.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | 3 | package freechips.rocketchip.tilelink 4 | 5 | import Chisel._ 6 | import freechips.rocketchip.config.Parameters 7 | import freechips.rocketchip.diplomacy._ 8 | 9 | class TLDumper()(implicit p: Parameters) extends LazyModule 10 | { 11 | val node = TLAdapterNode() 12 | 13 | lazy val module = new LazyModuleImp(this) { 14 | (node.in zip node.out) foreach { case ((in, edgeIn), (out, edgeOut)) => 15 | out <> in 16 | } 17 | } 18 | } 19 | 20 | object TLDumper 21 | { 22 | def apply()(implicit p: Parameters): TLNode = 23 | { 24 | val tldump = LazyModule(new TLDumper()) 25 | tldump.node 26 | } 27 | } 28 | 29 | -------------------------------------------------------------------------------- /src/main/scala/tilelink/Example.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | 3 | package freechips.rocketchip.tilelink 4 | 5 | import Chisel._ 6 | import freechips.rocketchip.config.Parameters 7 | import freechips.rocketchip.regmapper._ 8 | 9 | case class ExampleParams(num: Int, address: BigInt) 10 | 11 | trait ExampleBundle 12 | { 13 | val params: ExampleParams 14 | val gpio = UInt(width = params.num) 15 | } 16 | 17 | trait ExampleModule extends HasRegMap 18 | { 19 | val params: ExampleParams 20 | val io: ExampleBundle 21 | val interrupts: Vec[Bool] 22 | 23 | val state = RegInit(UInt(0, width = params.num)) 24 | val pending = RegInit(UInt(0xf, width = 4)) 25 | 26 | io.gpio := state 27 | interrupts := pending.asBools 28 | 29 | regmap( 30 | 0 -> Seq( 31 | RegField(params.num, state, 32 | RegFieldDesc("state", "State: Example of a R/W Register with description.", reset = Some(0)))), 33 | 4 -> Seq( 34 | RegField.w1ToClear(4, pending, state, 35 | Some(RegFieldDesc("pending", "Pending: Example of a special (W1ToC) Register. " + 36 | "Writing a bit here causes it to be reset to 0. " + 37 | "The bits are set when the corresponding bit in 'state' is high.", 38 | reset=Some(0xF), volatile=true)))) 39 | ) 40 | } 41 | 42 | // Create a concrete TL2 version of the abstract Example slave 43 | class TLExample(params: ExampleParams)(implicit p: Parameters) 44 | extends TLRegisterRouter(params.address, "somedev", Seq("ucbbar,random-interface"), 4)( 45 | new TLRegBundle(params, _) with ExampleBundle)( 46 | new TLRegModule(params, _, _) with ExampleModule) 47 | -------------------------------------------------------------------------------- /src/main/scala/tilelink/Map.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | 3 | package freechips.rocketchip.tilelink 4 | 5 | import Chisel._ 6 | import freechips.rocketchip.config.Parameters 7 | import freechips.rocketchip.diplomacy._ 8 | import scala.math.{min,max} 9 | 10 | // Moves the AddressSets of slave devices around 11 | // Combine with TLFilter to remove slaves or reduce their size 12 | class TLMap(fn: AddressSet => BigInt)(implicit p: Parameters) extends LazyModule 13 | { 14 | val node = TLAdapterNode( 15 | clientFn = { cp => cp }, 16 | managerFn = { mp => 17 | mp.copy(managers = mp.managers.map(m => 18 | m.copy(address = m.address.map(a => 19 | AddressSet(fn(a), a.mask)))))}) 20 | 21 | lazy val module = new LazyModuleImp(this) { 22 | (node.in zip node.out) foreach { case ((in, edgeIn), (out, edgeOut)) => 23 | out <> in 24 | val convert = edgeIn.manager.managers.flatMap(_.address) zip edgeOut.manager.managers.flatMap(_.address) 25 | def forward(x: UInt) = 26 | convert.map { case (i, o) => Mux(i.contains(x), UInt(o.base) | (x & UInt(o.mask)), UInt(0)) }.reduce(_ | _) 27 | def backward(x: UInt) = 28 | convert.map { case (i, o) => Mux(o.contains(x), UInt(i.base) | (x & UInt(i.mask)), UInt(0)) }.reduce(_ | _) 29 | 30 | out.a.bits.address := forward(in.a.bits.address) 31 | if (edgeOut.manager.anySupportAcquireB && edgeOut.client.anySupportProbe) { 32 | out.c.bits.address := forward(in.c.bits.address) 33 | in.b.bits.address := backward(out.b.bits.address) 34 | } 35 | } 36 | } 37 | } 38 | 39 | object TLMap 40 | { 41 | def apply(fn: AddressSet => BigInt)(implicit p: Parameters): TLNode = 42 | { 43 | val map = LazyModule(new TLMap(fn)) 44 | map.node 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/main/scala/tilelink/RegionReplication.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | 3 | package freechips.rocketchip.tilelink 4 | 5 | import chisel3._ 6 | import freechips.rocketchip.config._ 7 | import freechips.rocketchip.diplomacy._ 8 | 9 | case object MultiChipMaskKey extends Field[BigInt](0) 10 | 11 | trait HasRegionReplicatorParams { 12 | val replicatorMask: BigInt 13 | } 14 | 15 | // Replicate all devices below this adapter to multiple addreses. 16 | // If a device was at 0x4000-0x4fff and mask=0x10000, it will now be at 0x04000-0x04fff and 0x14000-0x14fff. 17 | class RegionReplicator(mask: BigInt = 0)(implicit p: Parameters) extends LazyModule { 18 | def ids = AddressSet.enumerateMask(mask) 19 | 20 | val node = TLAdapterNode( 21 | clientFn = { cp => cp }, 22 | managerFn = { mp => mp.copy(managers = mp.managers.map { m => m.copy( 23 | address = m.address.flatMap { a => ids.map { id => 24 | AddressSet(a.base | id, a.mask) } })})}) 25 | 26 | lazy val module = new LazyModuleImp(this) { 27 | (node.in zip node.out) foreach { case ((in, edgeIn), (out, edgeOut)) => 28 | out <> in 29 | out.a.bits.address := ~(~in.a.bits.address | mask.U) 30 | 31 | // We can't support probes; we don't have the required information 32 | edgeOut.manager.managers.foreach { m => 33 | require (m.regionType < RegionType.TRACKED, s"${m.name} has regionType ${m.regionType}, which requires Probe support a RegionReplicator cannot provide") 34 | } 35 | } 36 | } 37 | } 38 | 39 | object RegionReplicator { 40 | def apply(mask: BigInt = 0)(implicit p: Parameters): TLNode = { 41 | val replicator = LazyModule(new RegionReplicator(mask)) 42 | replicator.node 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/main/scala/tilelink/package.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | 3 | package freechips.rocketchip 4 | 5 | import Chisel._ 6 | import freechips.rocketchip.diplomacy._ 7 | 8 | package object tilelink 9 | { 10 | type TLInwardNode = InwardNodeHandle[TLClientPortParameters, TLManagerPortParameters, TLEdgeIn, TLBundle] 11 | type TLOutwardNode = OutwardNodeHandle[TLClientPortParameters, TLManagerPortParameters, TLEdgeOut, TLBundle] 12 | type TLNode = NodeHandle[TLClientPortParameters, TLManagerPortParameters, TLEdgeIn, TLBundle, TLClientPortParameters, TLManagerPortParameters, TLEdgeOut, TLBundle] 13 | 14 | implicit class TLClockDomainCrossing(val x: HasClockDomainCrossing) extends AnyVal { 15 | def crossIn (n: TLInwardNode) (implicit valName: ValName) = TLInwardCrossingHelper (valName.name, x, n) 16 | def crossOut(n: TLOutwardNode)(implicit valName: ValName) = TLOutwardCrossingHelper(valName.name, x, n) 17 | def cross(n: TLInwardNode) (implicit valName: ValName) = crossIn(n) 18 | def cross(n: TLOutwardNode)(implicit valName: ValName) = crossOut(n) 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/main/scala/unittest/Generator.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | 3 | package freechips.rocketchip.unittest 4 | 5 | object Generator extends freechips.rocketchip.util.GeneratorApp { 6 | val longName = names.topModuleProject + "." + names.configs 7 | generateFirrtl 8 | generateAnno 9 | generateTestSuiteMakefrags // TODO: Needed only for legacy make targets 10 | generateArtefacts 11 | } 12 | -------------------------------------------------------------------------------- /src/main/scala/unittest/TestGenerator.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | 3 | package freechips.rocketchip.unittest 4 | 5 | import Chisel._ 6 | import freechips.rocketchip.config._ 7 | import freechips.rocketchip.diplomacy._ 8 | 9 | abstract class LazyUnitTest(implicit p: Parameters) extends LazyModule 10 | { self => 11 | protected def finished: Bool 12 | 13 | lazy val module = new LazyModuleImp(this) { 14 | val finished = IO(Bool(OUTPUT)) 15 | finished := self.finished 16 | } 17 | } 18 | 19 | // FYI, you can call .finished on a Seq[LazyUnitTest] 20 | class TestGenerator(gen: LazyModule => Seq[LazyUnitTest]) 21 | { 22 | def apply(lm: LazyModule) = gen(lm) 23 | def ++ (other: TestGenerator) = new TestGenerator(gen = lm => gen(lm) ++ other(lm)) 24 | } 25 | 26 | object TestGenerator 27 | { 28 | def apply(matcher: PartialFunction[LazyModule, Seq[LazyUnitTest]]): TestGenerator = 29 | new TestGenerator(gen = matcher.lift(_).getOrElse(Nil)) 30 | def recurse(other: TestGenerator): TestGenerator = { 31 | def helper(lm: LazyModule, tail: Seq[LazyUnitTest]): Seq[LazyUnitTest] = 32 | lm.getChildren.foldLeft(other(lm) ++ tail) { case (tail, child) => helper(child, tail) } 33 | new TestGenerator(gen = helper(_, Nil)) 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/main/scala/unittest/TestHarness.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | 3 | package freechips.rocketchip.unittest 4 | 5 | import Chisel._ 6 | import freechips.rocketchip.config.Parameters 7 | 8 | class TestHarness(implicit val p: Parameters) extends Module { 9 | val io = new Bundle { val success = Bool(OUTPUT) } 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 Chisel._ 6 | import chisel3.experimental.MultiIOModule 7 | import freechips.rocketchip.config._ 8 | import freechips.rocketchip.util._ 9 | 10 | trait UnitTestIO { 11 | val finished = Bool(OUTPUT) 12 | val start = Bool(INPUT) 13 | } 14 | 15 | trait HasUnitTestIO { 16 | val io: UnitTestIO 17 | } 18 | 19 | trait UnitTestLegacyModule extends HasUnitTestIO { 20 | val io = new Bundle with UnitTestIO 21 | } 22 | 23 | trait UnitTestModule extends MultiIOModule 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 = new Bundle { 41 | val finished = Bool(OUTPUT) 42 | } 43 | 44 | val tests = p(UnitTests)(p) 45 | 46 | val s_idle :: s_start :: s_busy :: s_done :: Nil = Enum(Bits(), 4) 47 | val state = Reg(init = s_idle) 48 | val tests_finished = Vec(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 Chisel._ 6 | 7 | package object unittest 8 | { 9 | implicit class LazyUnitTestSeq(val seq: Seq[LazyUnitTest]) { 10 | def finished = seq.map(_.module.finished).foldLeft(Bool(true))(_ && _) 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /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 Chisel._ 7 | 8 | /** Takes in data on one decoupled interface and broadcasts it 9 | * to N decoupled output interfaces. 10 | */ 11 | class Broadcaster[T <: Data](typ: T, n: Int) extends Module { 12 | val io = new Bundle { 13 | val in = Decoupled(typ).flip 14 | val out = Vec(n, Decoupled(typ)) 15 | } 16 | 17 | require (n > 0) 18 | 19 | if (n == 1) { 20 | io.out.head <> io.in 21 | } else { 22 | val idx = Reg(init = UInt(0, log2Up(n))) 23 | val save = Reg(typ) 24 | 25 | io.out.head.valid := idx === UInt(0) && io.in.valid 26 | io.out.head.bits := io.in.bits 27 | for (i <- 1 until n) { 28 | io.out(i).valid := idx === UInt(i) 29 | io.out(i).bits := save 30 | } 31 | io.in.ready := io.out.head.ready && idx === UInt(0) 32 | 33 | when (io.in.fire()) { save := io.in.bits } 34 | 35 | when (io.out(idx).fire()) { 36 | when (idx === UInt(n - 1)) { idx := UInt(0) } 37 | .otherwise { idx := idx + UInt(1) } 38 | } 39 | } 40 | } 41 | 42 | object Broadcaster { 43 | def apply[T <: Data](in: DecoupledIO[T], n: Int): Vec[DecoupledIO[T]] = { 44 | val split = Module(new Broadcaster(in.bits, n)) 45 | split.io.in <> in 46 | split.io.out 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/main/scala/util/CRC.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | 3 | package freechips.rocketchip.util 4 | 5 | import Chisel._ 6 | 7 | object CRC 8 | { 9 | // A divisor of 0x1d5 is interpretted to be x^8 + x^7 + x^6 + x^4 + x^2 + 1 10 | // Let n be the highest term in the divisor; n=8 in 0x1d5. 11 | // Then, this function calculates c mod d, returning an n-bit UInt. 12 | // coefficient.width must be <= width 13 | def apply(divisor: BigInt, coefficient: UInt, width: Integer): UInt = { 14 | require (divisor > 0 && divisor.testBit(0)) 15 | require (width > 0) 16 | assert (coefficient >> width === UInt(0)) 17 | val n = log2Floor(divisor) 18 | val m = width 19 | if (m <= n) return coefficient 20 | 21 | // Initialize the reduction matrix 22 | val array = Array.tabulate(m) { BigInt(1) << _ } 23 | // Reduce the matrix of terms larger than n 24 | for { 25 | i <- (n until m).reverse 26 | j <- 0 to n 27 | if divisor.testBit(j) 28 | } array(i-(n-j)) ^= array(i) 29 | // Construct the circuit 30 | Cat(Seq.tabulate(n) { i => (UInt(array(i)) & coefficient).xorR } .reverse) 31 | } 32 | 33 | // Find more great CRC polynomials here: https://users.ece.cmu.edu/~koopman/crc/ 34 | val CRC_16F_4_2 = BigInt(0x1a2eb) // HD=4 for <32751 bits and HD=6 for <93 bits 35 | } 36 | -------------------------------------------------------------------------------- /src/main/scala/util/CheckOneHot.scala: -------------------------------------------------------------------------------- 1 | package freechips.rocketchip.util 2 | 3 | import Chisel._ 4 | 5 | object CheckOneHot { 6 | def apply(in: Seq[Bool]): Unit = { 7 | val value = Vec(in).asUInt 8 | val length = in.length 9 | def bitMap[T <: Data](f: Int => T) = Vec((0 until length).map(f)) 10 | val bitOneHot = bitMap((w: Int) => value === (1 << w).asUInt(length.W)).asUInt 11 | val oneHot = bitOneHot.orR 12 | val noneHot = value === 0.U 13 | assert(oneHot || noneHot) 14 | } 15 | } 16 | 17 | // a and b must be both hot or none hot 18 | object bothHotOrNoneHot { 19 | def apply(a: Bool, b: Bool, str: String): Unit = { 20 | val cond = (a === b) 21 | assert(cond, str) 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/main/scala/util/ClockDivider.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.Berkeley for license details. 2 | 3 | package freechips.rocketchip.util 4 | 5 | import Chisel._ 6 | import chisel3.util.HasBlackBoxResource 7 | import chisel3.experimental.withClock 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 = new Bundle { 20 | val clk_out = Clock(OUTPUT) 21 | val clk_in = Clock(INPUT) 22 | } 23 | 24 | setResource("/vsrc/ClockDivider2.v") 25 | } 26 | class ClockDivider3 extends BlackBox with HasBlackBoxResource { 27 | val io = new Bundle { 28 | val clk_out = Clock(OUTPUT) 29 | val clk_in = Clock(INPUT) 30 | } 31 | 32 | setResource("/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 = new Bundle { 39 | val clock_out = Clock(OUTPUT) 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 freechips.rocketchip.config.{Field, Parameters} 7 | 8 | case object ClockGateImpl extends Field[() => ClockGate](() => new EICG_wrapper) 9 | 10 | abstract class ClockGate extends BlackBox { 11 | val io = IO(new Bundle{ 12 | val in = Input(Clock()) 13 | val en = Input(Bool()) 14 | val out = Output(Clock()) 15 | }) 16 | } 17 | 18 | object ClockGate { 19 | def apply[T <: ClockGate]( 20 | in: Clock, 21 | en: Bool, 22 | name: Option[String] = None)(implicit p: Parameters): Clock = { 23 | val cg = Module(p(ClockGateImpl)()) 24 | name.foreach(cg.suggestName(_)) 25 | cg.io.in := in 26 | cg.io.en := en 27 | cg.io.out 28 | } 29 | 30 | def apply[T <: ClockGate]( 31 | in: Clock, 32 | en: Bool, 33 | name: String)(implicit p: Parameters): Clock = 34 | apply(in, en, Some(name)) 35 | } 36 | 37 | // behavioral model of Integrated Clock Gating cell 38 | class EICG_wrapper extends ClockGate 39 | -------------------------------------------------------------------------------- /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) extends Bundle with Clocked { 11 | val hartid = UInt(width = xLen.W) 12 | val timer = UInt(width = 32.W) 13 | val valid = Bool() 14 | val pc = UInt(width = xLen.W) 15 | val wrdst = UInt(width = 5.W) 16 | val wrdata = UInt(width = xLen.W) 17 | val wren = Bool() 18 | val rd0src = UInt(width = 5.W) 19 | val rd0val = UInt(width = xLen.W) 20 | val rd1src = UInt(width = 5.W) 21 | val rd1val = UInt(width = xLen.W) 22 | val inst = UInt(width = 32.W) 23 | } 24 | 25 | // mark a module that has cores with CoreMonitorBundles 26 | trait HasCoreMonitorBundles { 27 | def coreMonitorBundles: List[CoreMonitorBundle] 28 | } 29 | -------------------------------------------------------------------------------- /src/main/scala/util/Crossing.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | 3 | package freechips.rocketchip.util 4 | 5 | import Chisel._ 6 | import chisel3.util.{DecoupledIO, Decoupled, Irrevocable, IrrevocableIO, ReadyValidIO} 7 | 8 | class CrossingIO[T <: Data](gen: T) extends Bundle { 9 | // Enqueue clock domain 10 | val enq_clock = Clock(INPUT) 11 | val enq_reset = Bool(INPUT) // synchronously deasserted wrt. enq_clock 12 | val enq = Decoupled(gen).flip 13 | // Dequeue clock domain 14 | val deq_clock = Clock(INPUT) 15 | val deq_reset = Bool(INPUT) // synchronously deasserted wrt. deq_clock 16 | val deq = Decoupled(gen) 17 | } 18 | 19 | abstract class Crossing[T <: Data] extends Module { 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.internal.InstanceId 7 | import freechips.rocketchip.util.Annotated 8 | import freechips.rocketchip.diplomacy.DiplomaticSRAM 9 | import Chisel._ 10 | import chisel3.SyncReadMem 11 | import freechips.rocketchip.amba.axi4.AXI4RAM 12 | 13 | import scala.math.log10 14 | 15 | object DescribedSRAM { 16 | def apply[T <: Data]( 17 | name: String, 18 | desc: String, 19 | size: Int, // depth 20 | data: T 21 | ): SyncReadMem[T] = { 22 | 23 | val mem = SeqMem(size, data) 24 | 25 | mem.suggestName(name) 26 | 27 | val granWidth = data match { 28 | case v: Vec[_] => v.head.getWidth 29 | case d => d.getWidth 30 | } 31 | 32 | Annotated.srams( 33 | component = mem, 34 | name = name, 35 | address_width = log2Ceil(size), 36 | data_width = data.getWidth, 37 | depth = size, 38 | description = desc, 39 | write_mask_granularity = granWidth) 40 | 41 | mem 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /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 Chisel._ 7 | 8 | /** Given a list of (frequency, value) pairs, return a random value 9 | * according to the frequency distribution. The sum of the 10 | * frequencies in the distribution must be a power of two. 11 | */ 12 | object Frequency { 13 | def apply(dist : List[(Int, Bits)]) : Bits = { 14 | // Distribution must be non-empty 15 | require(dist.length > 0) 16 | 17 | // Require that the frequencies sum to a power of two 18 | val (freqs, vals) = dist.unzip 19 | val total = freqs.sum 20 | require(isPow2(total)) 21 | 22 | // First item in the distribution 23 | val (firstFreq, firstVal) = dist.head 24 | 25 | // Result wire 26 | val result = Wire(Bits(width = firstVal.getWidth)) 27 | result := UInt(0) 28 | 29 | // Random value 30 | val randVal = LCG(log2Up(total)) 31 | 32 | // Pick return value 33 | var count = firstFreq 34 | var select = when (randVal < UInt(firstFreq)) { result := firstVal } 35 | for (p <- dist.drop(1)) { 36 | count = count + p._1 37 | select = select.elsewhen(randVal < UInt(count)) { result := p._2 } 38 | } 39 | 40 | return result 41 | } 42 | } 43 | 44 | -------------------------------------------------------------------------------- /src/main/scala/util/GenericParameterizedBundle.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | 3 | package freechips.rocketchip.util 4 | 5 | import Chisel._ 6 | 7 | abstract class GenericParameterizedBundle[+T <: Object](val params: T) extends Bundle 8 | { 9 | override def cloneType = { 10 | try { 11 | this.getClass.getConstructors.head.newInstance(params).asInstanceOf[this.type] 12 | } catch { 13 | case e: java.lang.IllegalArgumentException => 14 | throw new Exception("Unable to use GenericParameterizedBundle.cloneType on " + 15 | this.getClass + ", probably because " + this.getClass + 16 | "() takes more than one argument. Consider overriding " + 17 | "cloneType() on " + this.getClass, e) 18 | } 19 | } 20 | } 21 | 22 | -------------------------------------------------------------------------------- /src/main/scala/util/GlobalTimer.scala: -------------------------------------------------------------------------------- 1 | package freechips.rocketchip.util 2 | 3 | import Chisel._ 4 | 5 | object GTimer { 6 | def apply(): UInt = { 7 | val (t, c) = Counter(Bool(true), 0x7fffffff) 8 | t 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/main/scala/util/HeterogeneousBag.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | 3 | package freechips.rocketchip.util 4 | 5 | import Chisel._ 6 | import chisel3.core.Record 7 | import scala.collection.immutable.ListMap 8 | 9 | final case class HeterogeneousBag[T <: Data](elts: Seq[T]) extends Record with collection.IndexedSeq[T] { 10 | def apply(x: Int) = elts(x) 11 | def length = elts.length 12 | 13 | val elements = ListMap(elts.zipWithIndex.map { case (n,i) => (i.toString, n) }:_*) 14 | override def cloneType: this.type = (new HeterogeneousBag(elts.map(_.chiselCloneType))).asInstanceOf[this.type] 15 | 16 | // IndexedSeq has its own hashCode/equals that we must not use 17 | override def hashCode: Int = super[Record].hashCode 18 | override def equals(that: Any): Boolean = super[Record].equals(that) 19 | } 20 | 21 | object HeterogeneousBag 22 | { 23 | def fromNode[D <: Data, E](elts: Seq[(D, E)]) = new HeterogeneousBag(elts.map(_._1.cloneType)) 24 | } 25 | -------------------------------------------------------------------------------- /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) 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 = Irrevocable(UInt(idWidth.W)) 15 | }) 16 | 17 | // True indicates that the id is available 18 | val bitmap = RegInit(~0.U(numIds.W)) 19 | val select = RegInit(0.U(idWidth.W)) 20 | val valid = RegInit(true.B) 21 | 22 | io.alloc.valid := valid 23 | io.alloc.bits := select 24 | 25 | val taken = (io.alloc.ready << io.alloc.bits)(numIds-1, 0) 26 | val given = (io.free .valid << io.free .bits)(numIds-1, 0) 27 | val bitmap1 = (bitmap & ~taken) | given 28 | val select1 = OHToUInt(~(leftOR(bitmap1, numIds) << 1) & bitmap1, numIds) 29 | val valid1 = bitmap1.orR 30 | 31 | // Clock gate the bitmap 32 | when (io.alloc.ready || io.free.valid) { 33 | bitmap := bitmap1 34 | valid := valid1 35 | } 36 | 37 | // Make select irrevocable 38 | when (io.alloc.ready || (!io.alloc.valid && io.free.valid)) { 39 | select := select1 40 | } 41 | 42 | // No double freeing 43 | assert (!io.free.valid || !(bitmap & ~taken)(io.free.bits)) 44 | } 45 | -------------------------------------------------------------------------------- /src/main/scala/util/IdentityModule.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | 3 | package freechips.rocketchip.tilelink 4 | 5 | import Chisel._ 6 | 7 | class IdentityModule[T <: Data](gen: T) extends Module 8 | { 9 | val io = new Bundle { 10 | val in = gen.cloneType.flip 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 Chisel._ 7 | 8 | /** A 16-bit psuedo-random generator based on a linear conguential 9 | * generator (LCG). The state is stored in an unitialised register. 10 | * When using the C++ backend, it is straigtforward to arrange a 11 | * random initial value for each uninitialised register, effectively 12 | * seeding each LCG16 instance with a different seed. 13 | */ 14 | class LCG16 extends Module { 15 | val io = new Bundle { 16 | val out = UInt(OUTPUT, 16) 17 | val inc = Bool(INPUT) 18 | } 19 | val state = Reg(UInt(width = 32)) 20 | when (io.inc) { 21 | state := state * UInt(1103515245, 32) + UInt(12345, 32) 22 | } 23 | io.out := state(30, 15) 24 | } 25 | 26 | /** An n-bit psuedo-random generator made from many instances of a 27 | * 16-bit LCG. Parameter 'width' must be larger than 0. 28 | */ 29 | class LCG(val w: Int) extends Module { 30 | val io = new Bundle { 31 | val out = UInt(OUTPUT, w) 32 | val inc = Bool(INPUT) 33 | } 34 | require(w > 0) 35 | val numLCG16s : Int = (w+15)/16 36 | val outs = Seq.fill(numLCG16s) { LCG16(io.inc) } 37 | io.out := Cat(outs) 38 | } 39 | 40 | object LCG16 { 41 | def apply(inc: Bool = Bool(true)): UInt = { 42 | val lcg = Module(new LCG16) 43 | lcg.io.inc := inc 44 | lcg.io.out 45 | } 46 | } 47 | 48 | object LCG { 49 | def apply(w: Int, inc: Bool = Bool(true)): UInt = { 50 | val lcg = Module(new LCG(w)) 51 | lcg.io.inc := inc 52 | lcg.io.out 53 | } 54 | } 55 | 56 | -------------------------------------------------------------------------------- /src/main/scala/util/LatencyPipe.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.Berkeley for license details. 2 | 3 | package freechips.rocketchip.util 4 | 5 | import Chisel._ 6 | import chisel3.util.{Irrevocable, IrrevocableIO} 7 | 8 | class LatencyPipe[T <: Data](typ: T, latency: Int) extends Module { 9 | val io = new Bundle { 10 | val in = Decoupled(typ).flip 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, pipe=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(in.bits, latency)) 23 | pipe.io.in <> in 24 | pipe.io.out 25 | } 26 | } 27 | 28 | class LatencyPipeIrrevocable[T <: Data](typ: T, latency: Int) extends Module { 29 | val io = new Bundle { 30 | val in = Irrevocable(typ).flip 31 | val out = Irrevocable(typ) 32 | } 33 | 34 | def doN[T](n: Int, func: T => T, in: T): T = 35 | (0 until n).foldLeft(in)((last, _) => func(last)) 36 | 37 | io.out <> doN(latency, (last: IrrevocableIO[T]) => Queue.irrevocable(last, 1, pipe=true), io.in) 38 | } 39 | 40 | object LatencyPipeIrrevocable { 41 | def apply[T <: Data](in: IrrevocableIO[T], latency: Int): IrrevocableIO[T] = { 42 | val pipe = Module(new LatencyPipeIrrevocable(in.bits, latency)) 43 | pipe.io.in <> in 44 | pipe.io.out 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/main/scala/util/PSDTestMode.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | 3 | package freechips.rocketchip.util 4 | 5 | import Chisel._ 6 | import freechips.rocketchip.config._ 7 | import freechips.rocketchip.diplomacy.BundleBridgeNexus 8 | 9 | case object IncludePSDTest extends Field[Boolean](false) 10 | //Note: one should never have `IncludePSDTest without 11 | // PSDTestModeBroadcastKey defined everywhere one wants to use it. 12 | // One could just use the PSDTestModeBroadcastKey.isDefined directly, 13 | // but it's a more error prone process to instantiate it and pass it in an 14 | // altered Parameters so the API is to have both. 15 | case object PSDTestModeBroadcastKey extends Field[Option[BundleBridgeNexus[PSDTestMode]]](None) 16 | 17 | class PSDTestMode extends Bundle { 18 | val test_mode = Bool() 19 | val test_mode_reset = Bool() 20 | // TODO: Clocks? 21 | } 22 | 23 | trait CanHavePSDTestModeIO { 24 | implicit val p: Parameters 25 | val psd = p(IncludePSDTest).option(new PSDTestMode().asInput) 26 | } 27 | -------------------------------------------------------------------------------- /src/main/scala/util/ROMGenerator.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | 3 | package freechips.rocketchip.util 4 | 5 | import Chisel._ 6 | import scala.collection.mutable.{HashMap} 7 | 8 | case class ROMConfig(name: String, depth: Int, width: Int) 9 | 10 | class BlackBoxedROM(c: ROMConfig) extends BlackBox { 11 | val io = new Bundle { 12 | val clock = Clock(INPUT) 13 | val address = UInt(INPUT, log2Ceil(c.depth)) 14 | val oe = Bool(INPUT) 15 | val me = Bool(INPUT) 16 | val q = UInt(OUTPUT, c.width) 17 | } 18 | 19 | override def desiredName: String = c.name 20 | } 21 | 22 | object ROMGenerator { 23 | private var finalized = false 24 | private val roms = HashMap[BlackBoxedROM, ROMConfig]() 25 | def apply(c: ROMConfig): BlackBoxedROM = { 26 | require(!finalized) 27 | val m = Module(new BlackBoxedROM(c)) 28 | roms(m) = c 29 | m 30 | } 31 | def lookup(m: BlackBoxedROM): ROMConfig = { 32 | finalized = true 33 | roms(m) 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/main/scala/util/ReduceOthers.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | 3 | package freechips.rocketchip.util 4 | 5 | import Chisel._ 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) { Bool(false) } 16 | } else if (falses == 1) { 17 | x.map { b => 18 | if (b.isLit && b.litValue == 0) { 19 | variables.foldLeft(Bool(true))(_ && _) 20 | } else { 21 | Bool(false) 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)]) { 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) { Bool(true) }, x.headOption.getOrElse(Bool(true))) 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 Chisel._ 6 | 7 | // A Repeater passes it's input to it's output, unless repeat is asserted. 8 | // When repeat is asserted, the Repeater copies the input and repeats it next cycle. 9 | class Repeater[T <: Data](gen: T) extends Module 10 | { 11 | val io = new Bundle { 12 | val repeat = Bool(INPUT) 13 | val full = Bool(OUTPUT) 14 | val enq = Decoupled(gen).flip 15 | val deq = Decoupled(gen) 16 | } 17 | 18 | val full = RegInit(Bool(false)) 19 | val saved = Reg(gen) 20 | 21 | // When !full, a repeater is pass-through 22 | io.deq.valid := io.enq.valid || full 23 | io.enq.ready := io.deq.ready && !full 24 | io.deq.bits := Mux(full, saved, io.enq.bits) 25 | io.full := full 26 | 27 | when (io.enq.fire() && io.repeat) { full := Bool(true); saved := io.enq.bits } 28 | when (io.deq.fire() && !io.repeat) { full := Bool(false) } 29 | } 30 | 31 | object Repeater 32 | { 33 | def apply[T <: Data](enq: DecoupledIO[T], repeat: Bool): DecoupledIO[T] = { 34 | val repeater = Module(new Repeater(enq.bits)) 35 | repeater.io.repeat := repeat 36 | repeater.io.enq := enq 37 | repeater.io.deq 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/main/scala/util/ResetCatchAndSync.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | 3 | package freechips.rocketchip.util 4 | 5 | import Chisel._ 6 | import chisel3.experimental.{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 = new Bundle { 18 | val sync_reset = Bool(OUTPUT) 19 | val psd = new PSDTestMode().asInput 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) 27 | withReset(post_psd_reset) { 28 | io.sync_reset := Mux(io.psd.test_mode, io.psd.test_mode_reset, 29 | ~AsyncResetSynchronizerShiftReg(Bool(true), 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(Wire(new PSDTestMode()).fromBits(UInt(0))) 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 | -------------------------------------------------------------------------------- /vsim/.gitignore: -------------------------------------------------------------------------------- 1 | simv* 2 | csrc 3 | *.vpd 4 | *.key 5 | DVE* 6 | .vcs* 7 | timestamp 8 | *.out 9 | *.h 10 | *.log 11 | *.cmd 12 | *.daidir 13 | *.ucli 14 | *.a 15 | *.vcd 16 | generated-src 17 | output 18 | -------------------------------------------------------------------------------- /vsim/Makefile: -------------------------------------------------------------------------------- 1 | #======================================================================= 2 | # Makefile for Verilog simulation w/ VCS 3 | #----------------------------------------------------------------------- 4 | # Yunsup Lee (yunsup@cs.berkeley.edu) 5 | # 6 | # This makefile will build a rtl simulator and run various tests to 7 | # verify proper functionality. 8 | # 9 | 10 | default: all 11 | 12 | base_dir = $(abspath ..) 13 | generated_dir = $(abspath ./generated-src) 14 | mem_gen = $(VLSI_MEM_GEN) 15 | sim_dir = . 16 | output_dir = $(sim_dir)/output 17 | 18 | BACKEND ?= v 19 | TB ?= TestDriver 20 | 21 | include $(base_dir)/Makefrag 22 | include $(sim_dir)/Makefrag 23 | ifneq ($(filter run% %.run %.out %.vpd %.vcd,$(MAKECMDGOALS)),) 24 | -include $(generated_dir)/$(long_name).d 25 | endif 26 | include $(base_dir)/vsim/Makefrag-verilog 27 | 28 | all: $(simv) 29 | debug: $(simv_debug) 30 | 31 | clean: 32 | rm -rf $(junk) simv* csrc *.key DVE* *.h *.a *.daidir $(generated_dir) 33 | 34 | .PHONY: default all debug clean 35 | --------------------------------------------------------------------------------