Merge branch 'AHB' into dev

# Conflicts:
#	src/main/scala/vexriscv/plugin/DBusSimplePlugin.scala
#	src/main/scala/vexriscv/plugin/IBusSimplePlugin.scala
This commit is contained in:
Charles Papon 2019-05-07 17:21:52 +02:00
commit db307075cf
4 changed files with 360 additions and 1 deletions

View File

@ -0,0 +1,174 @@
package vexriscv.demo
import spinal.core._
import spinal.lib._
import spinal.lib.bus.avalon.AvalonMM
import spinal.lib.com.jtag.Jtag
import spinal.lib.eda.altera.{InterruptReceiverTag, QSysify, ResetEmitterTag}
import vexriscv.ip.{DataCacheConfig, InstructionCacheConfig}
import vexriscv.plugin._
import vexriscv.{VexRiscv, VexRiscvConfig, plugin}
/**
* Created by spinalvm on 14.07.17.
*/
//class VexRiscvAvalon(debugClockDomain : ClockDomain) extends Component{
//
//}
//make clean run DBUS=SIMPLE_AHBLITE3 IBUS=SIMPLE_AHBLITE3 MMU=no CSR=no DEBUG_PLUGIN=STD
object VexRiscvAhbLite3{
def main(args: Array[String]) {
val report = SpinalConfig(mode = if(args.contains("--vhdl")) VHDL else Verilog).generate{
//CPU configuration
val cpuConfig = VexRiscvConfig(
plugins = List(
new IBusSimplePlugin(
resetVector = 0x80000000l,
cmdForkOnSecondStage = false,
cmdForkPersistence = true,
prediction = STATIC,
catchAccessFault = false,
compressedGen = false
),
new DBusSimplePlugin(
catchAddressMisaligned = false,
catchAccessFault = false
),
// new IBusCachedPlugin(
// config = InstructionCacheConfig(
// cacheSize = 4096,
// bytePerLine =32,
// wayCount = 1,
// addressWidth = 32,
// cpuDataWidth = 32,
// memDataWidth = 32,
// catchIllegalAccess = true,
// catchAccessFault = true,
// catchMemoryTranslationMiss = true,
// asyncTagMemory = false,
// twoCycleRam = true
// )
// // askMemoryTranslation = true,
// // memoryTranslatorPortConfig = MemoryTranslatorPortConfig(
// // portTlbSize = 4
// // )
// ),
// new DBusCachedPlugin(
// config = new DataCacheConfig(
// cacheSize = 4096,
// bytePerLine = 32,
// wayCount = 1,
// addressWidth = 32,
// cpuDataWidth = 32,
// memDataWidth = 32,
// catchAccessError = true,
// catchIllegal = true,
// catchUnaligned = true,
// catchMemoryTranslationMiss = true
// ),
// memoryTranslatorPortConfig = null
// // memoryTranslatorPortConfig = MemoryTranslatorPortConfig(
// // portTlbSize = 6
// // )
// ),
new StaticMemoryTranslatorPlugin(
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 MulPlugin,
new DivPlugin,
new HazardSimplePlugin(
bypassExecute = true,
bypassMemory = true,
bypassWriteBack = true,
bypassWriteBackBuffer = true,
pessimisticUseSrc = false,
pessimisticWriteRegFile = false,
pessimisticAddressMatch = false
),
new DebugPlugin(ClockDomain.current.clone(reset = Bool().setName("debugReset"))),
new BranchPlugin(
earlyBranch = false,
catchAddressMisaligned = true
),
new CsrPlugin(
config = CsrPluginConfig(
catchIllegalAccess = false,
mvendorid = null,
marchid = null,
mimpid = null,
mhartid = null,
misaExtensionsInit = 66,
misaAccess = CsrAccess.NONE,
mtvecAccess = CsrAccess.NONE,
mtvecInit = 0x00000020l,
mepcAccess = CsrAccess.READ_WRITE,
mscratchGen = false,
mcauseAccess = CsrAccess.READ_ONLY,
mbadaddrAccess = CsrAccess.READ_ONLY,
mcycleAccess = CsrAccess.NONE,
minstretAccess = CsrAccess.NONE,
ecallGen = false,
wfiGenAsWait = false,
ucycleAccess = CsrAccess.NONE
)
),
new YamlPlugin("cpu0.yaml")
)
)
//CPU instanciation
val cpu = new VexRiscv(cpuConfig)
//CPU modifications to be an AhbLite3 one
cpu.rework {
for (plugin <- cpuConfig.plugins) plugin match {
case plugin: IBusSimplePlugin => {
plugin.iBus.setAsDirectionLess() //Unset IO properties of iBus
master(plugin.iBus.toAhbLite3Master()).setName("iBusAhbLite3")
}
case plugin: DBusSimplePlugin => {
plugin.dBus.setAsDirectionLess()
master(plugin.dBus.toAhbLite3Master(avoidWriteToReadHazard = true)).setName("dBusAhbLite3")
}
// case plugin: IBusCachedPlugin => {
// plugin.iBus.setAsDirectionLess() //Unset IO properties of iBus
// iBus = master(plugin.iBus.toAvalon())
// .setName("iBusAvalon")
// .addTag(ClockDomainTag(ClockDomain.current)) //Specify a clock domain to the iBus (used by QSysify)
// }
// case plugin: DBusCachedPlugin => {
// plugin.dBus.setAsDirectionLess()
// master(plugin.dBus.toAvalon())
// .setName("dBusAvalon")
// .addTag(ClockDomainTag(ClockDomain.current))
// }
case plugin: DebugPlugin if args.contains("--jtag")=> plugin.debugClockDomain {
plugin.io.bus.setAsDirectionLess()
val jtag = slave(new Jtag()).setName("jtag")
jtag <> plugin.io.bus.fromJtag()
}
case _ =>
}
}
cpu
}
}
}

View File

@ -3,6 +3,7 @@ package vexriscv.plugin
import vexriscv._
import spinal.core._
import spinal.lib._
import spinal.lib.bus.amba3.ahblite.{AhbLite3Config, AhbLite3Master}
import spinal.lib.bus.amba4.axi._
import spinal.lib.bus.avalon.{AvalonMM, AvalonMMConfig}
import spinal.lib.bus.wishbone.{Wishbone, WishboneConfig}
@ -71,6 +72,10 @@ object DBusSimpleBus{
dataWidth = 32
)
def getAhbLite3Config() = AhbLite3Config(
addressWidth = 32,
dataWidth = 32
)
}
case class DBusSimpleBus() extends Bundle with IMasterSlave{
@ -82,6 +87,13 @@ case class DBusSimpleBus() extends Bundle with IMasterSlave{
slave(rsp)
}
def cmdS2mPipe() : DBusSimpleBus = {
val s = DBusSimpleBus()
s.cmd << this.cmd.s2mPipe()
this.rsp := s.rsp
s
}
def toAxi4Shared(stageCmd : Boolean = false): Axi4Shared = {
val axi = Axi4Shared(DBusSimpleBus.getAxi4Config())
val pendingWritesMax = 7
@ -195,6 +207,37 @@ case class DBusSimpleBus() extends Bundle with IMasterSlave{
bus
}
def toAhbLite3Master(avoidWriteToReadHazard : Boolean): AhbLite3Master = {
val bus = AhbLite3Master(DBusSimpleBus.getAhbLite3Config())
bus.HADDR := this.cmd.address
bus.HWRITE := this.cmd.wr
bus.HSIZE := B(this.cmd.size, 3 bits)
bus.HBURST := 0
bus.HPROT := "1111"
bus.HTRANS := this.cmd.valid ## B"0"
bus.HMASTLOCK := False
bus.HWDATA := RegNextWhen(this.cmd.data, bus.HREADY)
this.cmd.ready := bus.HREADY
val pending = RegInit(False) clearWhen(bus.HREADY) setWhen(this.cmd.fire && !this.cmd.wr)
this.rsp.ready := bus.HREADY && pending
this.rsp.data := bus.HRDATA
this.rsp.error := bus.HRESP
if(avoidWriteToReadHazard) {
val writeDataPhase = RegNextWhen(bus.HTRANS === 2 && bus.HWRITE, bus.HREADY) init (False)
val potentialHazard = this.cmd.valid && !this.cmd.wr && writeDataPhase
when(potentialHazard) {
bus.HTRANS := 0
this.cmd.ready := False
}
}
bus
}
}

View File

@ -3,6 +3,7 @@ package vexriscv.plugin
import vexriscv._
import spinal.core._
import spinal.lib._
import spinal.lib.bus.amba3.ahblite.{AhbLite3, AhbLite3Config, AhbLite3Master}
import spinal.lib.bus.amba4.axi._
import spinal.lib.bus.avalon.{AvalonMM, AvalonMMConfig}
import spinal.lib.bus.wishbone.{Wishbone, WishboneConfig}
@ -65,6 +66,11 @@ object IBusSimpleBus{
addressWidth = 32,
dataWidth = 32
)
def getAhbLite3Config() = AhbLite3Config(
addressWidth = 32,
dataWidth = 32
)
}
@ -78,6 +84,14 @@ case class IBusSimpleBus(cmdIsPersistente : Boolean = false) extends Bundle with
}
def cmdS2mPipe() : IBusSimpleBus = {
val s = IBusSimpleBus()
s.cmd << this.cmd.s2mPipe()
this.rsp << s.rsp
s
}
def toAxi4ReadOnly(): Axi4ReadOnly = {
assert(cmdIsPersistente)
val axi = Axi4ReadOnly(IBusSimpleBus.getAxi4Config())
@ -148,6 +162,26 @@ case class IBusSimpleBus(cmdIsPersistente : Boolean = false) extends Bundle with
rsp.error := False
bus
}
//cmdForkPersistence need to bet set
def toAhbLite3Master(): AhbLite3Master = {
val bus = AhbLite3Master(IBusSimpleBus.getAhbLite3Config())
bus.HADDR := this.cmd.pc
bus.HWRITE := False
bus.HSIZE := 2
bus.HBURST := 0
bus.HPROT := "1110"
bus.HTRANS := this.cmd.valid ## B"0"
bus.HMASTLOCK := False
bus.HWDATA.assignDontCare()
this.cmd.ready := bus.HREADY
val pending = RegInit(False) clearWhen(bus.HREADY) setWhen(this.cmd.fire)
this.rsp.valid := bus.HREADY && pending
this.rsp.inst := bus.HRDATA
this.rsp.error := bus.HRESP
bus
}
}

View File

@ -1475,7 +1475,7 @@ public:
if(bootPc != -1) top->VexRiscv->core->prefetch_pc = bootPc;
#else
if(bootPc != -1) {
#if defined(IBUS_SIMPLE) || defined(IBUS_SIMPLE_WISHBONE)
#if defined(IBUS_SIMPLE) || defined(IBUS_SIMPLE_WISHBONE) || defined(IBUS_SIMPLE_AHBLITE3)
top->VexRiscv->IBusSimplePlugin_fetchPc_pcReg = bootPc;
#ifdef COMPRESSED
top->VexRiscv->IBusSimplePlugin_decodePc_pcReg = bootPc;
@ -1924,6 +1924,52 @@ public:
#endif
#ifdef IBUS_SIMPLE_AHBLITE3
class IBusSimpleAhbLite3 : public SimElement{
public:
Workspace *ws;
VVexRiscv* top;
uint32_t iBusAhbLite3_HRDATA;
bool iBusAhbLite3_HRESP;
bool pending;
IBusSimpleAhbLite3(Workspace* ws){
this->ws = ws;
this->top = ws->top;
}
virtual void onReset(){
pending = false;
top->iBusAhbLite3_HREADY = 1;
top->iBusAhbLite3_HRESP = 0;
}
virtual void preCycle(){
if (top->iBusAhbLite3_HTRANS == 2 && top->iBusAhbLite3_HREADY && !top->iBusAhbLite3_HWRITE) {
ws->iBusAccess(top->iBusAhbLite3_HADDR,&iBusAhbLite3_HRDATA,&iBusAhbLite3_HRESP);
pending = true;
}
}
virtual void postCycle(){
if(ws->iStall)
top->iBusAhbLite3_HREADY = (!ws->iStall || VL_RANDOM_I(7) < 100);
if(pending && top->iBusAhbLite3_HREADY){
top->iBusAhbLite3_HRDATA = iBusAhbLite3_HRDATA;
top->iBusAhbLite3_HRESP = iBusAhbLite3_HRESP;
pending = false;
} else {
top->iBusAhbLite3_HRDATA = VL_RANDOM_I(32);
top->iBusAhbLite3_HRESP = VL_RANDOM_I(1);
}
}
};
#endif
#ifdef IBUS_CACHED
class IBusCached : public SimElement{
public:
@ -2171,6 +2217,60 @@ public:
};
#endif
#ifdef DBUS_SIMPLE_AHBLITE3
class DBusSimpleAhbLite3 : public SimElement{
public:
Workspace *ws;
VVexRiscv* top;
uint32_t dBusAhbLite3_HADDR, dBusAhbLite3_HSIZE, dBusAhbLite3_HTRANS, dBusAhbLite3_HWRITE;
DBusSimpleAhbLite3(Workspace* ws){
this->ws = ws;
this->top = ws->top;
}
virtual void onReset(){
top->dBusAhbLite3_HREADY = 1;
top->dBusAhbLite3_HRESP = 0;
dBusAhbLite3_HTRANS = 0;
}
virtual void preCycle(){
if(top->dBusAhbLite3_HREADY && dBusAhbLite3_HTRANS == 2 && dBusAhbLite3_HWRITE){
uint32_t data = top->dBusAhbLite3_HWDATA;
bool error;
ws->dBusAccess(dBusAhbLite3_HADDR, 1, dBusAhbLite3_HSIZE, ((1 << (1 << dBusAhbLite3_HSIZE))-1) << (dBusAhbLite3_HADDR & 0x3),&data,&error);
}
if(top->dBusAhbLite3_HREADY){
dBusAhbLite3_HADDR = top->dBusAhbLite3_HADDR ;
dBusAhbLite3_HSIZE = top->dBusAhbLite3_HSIZE ;
dBusAhbLite3_HTRANS = top->dBusAhbLite3_HTRANS ;
dBusAhbLite3_HWRITE = top->dBusAhbLite3_HWRITE ;
}
}
virtual void postCycle(){
if(ws->iStall)
top->dBusAhbLite3_HREADY = (!ws->iStall || VL_RANDOM_I(7) < 100);
top->dBusAhbLite3_HRDATA = VL_RANDOM_I(32);
top->dBusAhbLite3_HRESP = VL_RANDOM_I(1);
if(top->dBusAhbLite3_HREADY && dBusAhbLite3_HTRANS == 2 && !dBusAhbLite3_HWRITE){
bool error;
ws->dBusAccess(dBusAhbLite3_HADDR, 0, dBusAhbLite3_HSIZE, ((1 << (1 << dBusAhbLite3_HSIZE))-1) << (dBusAhbLite3_HADDR & 0x3),&top->dBusAhbLite3_HRDATA,&error);
top->dBusAhbLite3_HRESP = error;
}
}
};
#endif
#if defined(DBUS_CACHED_WISHBONE) || defined(DBUS_SIMPLE_WISHBONE)
#include <queue>
@ -2639,6 +2739,11 @@ void Workspace::fillSimELements(){
#ifdef IBUS_SIMPLE_AVALON
simElements.push_back(new IBusSimpleAvalon(this));
#endif
#ifdef IBUS_SIMPLE_AHBLITE3
simElements.push_back(new IBusSimpleAhbLite3(this));
#endif
#ifdef IBUS_CACHED
simElements.push_back(new IBusCached(this));
#endif
@ -2659,6 +2764,9 @@ void Workspace::fillSimELements(){
#ifdef DBUS_SIMPLE_AVALON
simElements.push_back(new DBusSimpleAvalon(this));
#endif
#ifdef DBUS_SIMPLE_AHBLITE3
simElements.push_back(new DBusSimpleAhbLite3(this));
#endif
#ifdef DBUS_CACHED
simElements.push_back(new DBusCached(this));
#endif