diff --git a/README.md b/README.md index 28bace2..30c814e 100644 --- a/README.md +++ b/README.md @@ -72,6 +72,7 @@ This repository hosts a RISC-V implementation written in SpinalHDL. Here are som - Linux compatible (SoC : https://github.com/enjoy-digital/linux-on-litex-vexriscv) - Zephyr compatible - [FreeRTOS port](https://github.com/Dolu1990/FreeRTOS-RISCV) +- Support tightly coupled memory on I$ D$ (see GenFullWithTcm) The hardware description of this CPU is done by using a very software oriented approach (without any overhead in the generated hardware). Here is a list of software concepts used: diff --git a/src/main/scala/vexriscv/demo/GenFullWithTcm.scala b/src/main/scala/vexriscv/demo/GenFullWithTcm.scala new file mode 100644 index 0000000..0b7618e --- /dev/null +++ b/src/main/scala/vexriscv/demo/GenFullWithTcm.scala @@ -0,0 +1,100 @@ +package vexriscv.demo + +import spinal.core._ +import vexriscv.ip.{DataCacheConfig, InstructionCacheConfig} +import vexriscv.plugin._ +import vexriscv.{VexRiscv, VexRiscvConfig, plugin} + +/** + * Both iBusTc and dBusTc assume + * - 1 cycle read latency + * - read_data stay on the port until the next access + * - writes should only occure when dBusTc_enable && dBusTc_write_enable + * - address is in byte, don't care about the 2 LSB + */ +object GenFullWithTcm extends App{ + def config = VexRiscvConfig( + plugins = List( + new IBusCachedPlugin( + prediction = DYNAMIC, + config = InstructionCacheConfig( + cacheSize = 4096, + bytePerLine =32, + wayCount = 1, + addressWidth = 32, + cpuDataWidth = 32, + memDataWidth = 32, + catchIllegalAccess = true, + catchAccessFault = true, + asyncTagMemory = false, + twoCycleRam = true, + twoCycleCache = true + ), + memoryTranslatorPortConfig = MmuPortConfig( + portTlbSize = 4 + ) + ).newTightlyCoupledPort( + TightlyCoupledPortParameter("iBusTc", a => a(31 downto 28) === 0x2) + ), + new DBusCachedPlugin( + config = new DataCacheConfig( + cacheSize = 4096, + bytePerLine = 32, + wayCount = 1, + addressWidth = 32, + cpuDataWidth = 32, + memDataWidth = 32, + catchAccessError = true, + catchIllegal = true, + catchUnaligned = true + ), + memoryTranslatorPortConfig = MmuPortConfig( + portTlbSize = 6 + ) + ).newTightlyCoupledPort( + TightlyCoupledDataPortParameter("dBusTc", a => a(31 downto 28) === 0x3) + ), + new MmuPlugin( + virtualRange = _(31 downto 28) === 0xC, + ioRange = _(31 downto 28) === 0xF + ), + new DecoderSimplePlugin( + catchIllegalInstruction = true + ), + new RegFilePlugin( + regFileReadyKind = plugin.SYNC, + zeroBoot = false + ), + new IntAluPlugin, + new SrcPlugin( + separatedAddSub = false, + executeInsertion = true + ), + new FullBarrelShifterPlugin, + new HazardSimplePlugin( + bypassExecute = true, + bypassMemory = true, + bypassWriteBack = true, + bypassWriteBackBuffer = true, + pessimisticUseSrc = false, + pessimisticWriteRegFile = false, + pessimisticAddressMatch = false + ), + new MulPlugin, + new DivPlugin, + new CsrPlugin(CsrPluginConfig.small(0x80000020l)), + new DebugPlugin(ClockDomain.current.clone(reset = Bool().setName("debugReset"))), + new BranchPlugin( + earlyBranch = false, + catchAddressMisaligned = true + ), + new YamlPlugin("cpu0.yaml") + ) + ) + + def cpu() = new VexRiscv( + config + ) + + SpinalVerilog(cpu()) +} diff --git a/src/main/scala/vexriscv/plugin/DBusCachedPlugin.scala b/src/main/scala/vexriscv/plugin/DBusCachedPlugin.scala index 593eb91..e32ff96 100644 --- a/src/main/scala/vexriscv/plugin/DBusCachedPlugin.scala +++ b/src/main/scala/vexriscv/plugin/DBusCachedPlugin.scala @@ -87,6 +87,12 @@ class DBusCachedPlugin(val config : DataCacheConfig, val tightlyCoupledPorts = ArrayBuffer[TightlyCoupledDataPort]() def tightlyGen = tightlyCoupledPorts.nonEmpty + def newTightlyCoupledPort(p: TightlyCoupledDataPortParameter) = { + val port = TightlyCoupledDataPort(p, null) + tightlyCoupledPorts += port + this + } + def newTightlyCoupledPort(mapping : UInt => Bool) = { val port = TightlyCoupledDataPort(TightlyCoupledDataPortParameter(null, mapping), TightlyCoupledDataBus()) tightlyCoupledPorts += port @@ -173,6 +179,9 @@ class DBusCachedPlugin(val config : DataCacheConfig, import Riscv._ import pipeline.config._ + + tightlyCoupledPorts.filter(_.bus == null).foreach(p => p.bus = master(TightlyCoupledDataBus()).setName(p.p.name)) + dBus = master(DataCacheMemBus(this.config)).setName("dBus") val decoderService = pipeline.service(classOf[DecoderService])