Add unpipelined Wishbone support for uncached version

This commit is contained in:
Dolu1990 2018-08-24 12:20:14 +02:00
parent 304c8156a0
commit 0255f51cc5
4 changed files with 152 additions and 59 deletions

View File

@ -24,16 +24,16 @@ object VexRiscvCachedWishboneForSim{
//CPU configuration //CPU configuration
val cpuConfig = VexRiscvConfig( val cpuConfig = VexRiscvConfig(
plugins = List( plugins = List(
new PcManagerSimplePlugin(0x00000000l, false),
// new IBusSimplePlugin( // new IBusSimplePlugin(
// interfaceKeepData = false, // resetVector = 0x80000000l,
// catchAccessFault = false // prediction = STATIC
// ), // ),
// new DBusSimplePlugin( // new DBusSimplePlugin(
// catchAddressMisaligned = false, // catchAddressMisaligned = false,
// catchAccessFault = false // catchAccessFault = false
// ), // ),
new IBusCachedPlugin( new IBusCachedPlugin(
resetVector = 0x80000000l,
prediction = STATIC, prediction = STATIC,
config = InstructionCacheConfig( config = InstructionCacheConfig(
cacheSize = 4096, cacheSize = 4096,
@ -79,7 +79,7 @@ object VexRiscvCachedWishboneForSim{
), ),
new RegFilePlugin( new RegFilePlugin(
regFileReadyKind = plugin.SYNC, regFileReadyKind = plugin.SYNC,
zeroBoot = false zeroBoot = true
), ),
new IntAluPlugin, new IntAluPlugin,
new SrcPlugin( new SrcPlugin(
@ -117,36 +117,22 @@ object VexRiscvCachedWishboneForSim{
//cpu.setDefinitionName("VexRiscvAvalon") //cpu.setDefinitionName("VexRiscvAvalon")
cpu.rework { cpu.rework {
for (plugin <- cpuConfig.plugins) plugin match { for (plugin <- cpuConfig.plugins) plugin match {
// case plugin: IBusSimplePlugin => { case plugin: IBusSimplePlugin => {
// plugin.iBus.asDirectionLess() //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: IBusCachedPlugin => {
plugin.iBus.asDirectionLess() //Unset IO properties of iBus plugin.iBus.asDirectionLess() //Unset IO properties of iBus
master(plugin.iBus.toWishbone()).setName("iBusWishbone") master(plugin.iBus.toWishbone()).setName("iBusWishbone")
} }
// case plugin: DBusSimplePlugin => { case plugin: IBusCachedPlugin => {
// plugin.dBus.asDirectionLess() plugin.iBus.asDirectionLess()
// master(plugin.dBus.toAvalon()) master(plugin.iBus.toWishbone()).setName("iBusWishbone")
// .setName("dBusAvalon") }
// .addTag(ClockDomainTag(ClockDomain.current)) case plugin: DBusSimplePlugin => {
// } plugin.dBus.asDirectionLess()
master(plugin.dBus.toWishbone()).setName("dBusWishbone")
}
case plugin: DBusCachedPlugin => { case plugin: DBusCachedPlugin => {
plugin.dBus.asDirectionLess() plugin.dBus.asDirectionLess()
master(plugin.dBus.toWishbone()).setName("dBusWishbone") master(plugin.dBus.toWishbone()).setName("dBusWishbone")
} }
// case plugin: DebugPlugin => {
// plugin.io.bus.asDirectionLess()
// slave(plugin.io.bus.fromAvalon())
// .setName("debugBusAvalon")
// .addTag(ClockDomainTag(plugin.debugClockDomain))
// .parent = null //Avoid the io bundle to be interpreted as a QSys conduit
// plugin.io.resetOut
// .addTag(ResetEmitterTag(plugin.debugClockDomain))
// .parent = null //Avoid the io bundle to be interpreted as a QSys conduit
// }
case _ => case _ =>
} }
} }

View File

@ -4,7 +4,9 @@ import vexriscv._
import spinal.core._ import spinal.core._
import spinal.lib._ import spinal.lib._
import spinal.lib.bus.amba4.axi._ import spinal.lib.bus.amba4.axi._
import spinal.lib.bus.avalon.{AvalonMMConfig, AvalonMM} import spinal.lib.bus.avalon.{AvalonMM, AvalonMMConfig}
import spinal.lib.bus.wishbone.{Wishbone, WishboneConfig}
import vexriscv.ip.DataCacheMemCmd
case class DBusSimpleCmd() extends Bundle{ case class DBusSimpleCmd() extends Bundle{
@ -45,6 +47,21 @@ object DBusSimpleBus{
useResponse = true, useResponse = true,
maximumPendingReadTransactions = 1 maximumPendingReadTransactions = 1
) )
def getWishboneConfig() = WishboneConfig(
addressWidth = 30,
dataWidth = 32,
selWidth = 4,
useSTALL = false,
useLOCK = false,
useERR = true,
useRTY = false,
tgaWidth = 0,
tgcWidth = 0,
tgdWidth = 0,
useBTE = true,
useCTI = true
)
} }
case class DBusSimpleBus() extends Bundle with IMasterSlave{ case class DBusSimpleBus() extends Bundle with IMasterSlave{
@ -133,6 +150,35 @@ case class DBusSimpleBus() extends Bundle with IMasterSlave{
mm mm
} }
def toWishbone(): Wishbone = {
val wishboneConfig = DBusSimpleBus.getWishboneConfig()
val bus = Wishbone(wishboneConfig)
val cmdStage = cmd.halfPipe()
bus.ADR := cmdStage.address >> 2
bus.CTI :=B"000"
bus.BTE := "00"
bus.SEL := (cmdStage.size.mux (
U(0) -> B"0001",
U(1) -> B"0011",
default -> B"1111"
) << cmdStage.address(1 downto 0)).resized
when(!cmdStage.wr) {
bus.SEL := "1111"
}
bus.WE := cmdStage.wr
bus.DAT_MOSI := cmdStage.data
cmdStage.ready := cmdStage.valid && bus.ACK
bus.CYC := cmdStage.valid
bus.STB := cmdStage.valid
rsp.ready := cmdStage.valid && !bus.WE && bus.ACK
rsp.data := bus.DAT_MISO
rsp.error := False //TODO
bus
}
} }

View File

@ -5,6 +5,7 @@ import spinal.core._
import spinal.lib._ import spinal.lib._
import spinal.lib.bus.amba4.axi._ import spinal.lib.bus.amba4.axi._
import spinal.lib.bus.avalon.{AvalonMM, AvalonMMConfig} import spinal.lib.bus.avalon.{AvalonMM, AvalonMMConfig}
import spinal.lib.bus.wishbone.{Wishbone, WishboneConfig}
@ -43,6 +44,21 @@ object IBusSimpleBus{
useResponse = true, useResponse = true,
maximumPendingReadTransactions = 8 maximumPendingReadTransactions = 8
) )
def getWishboneConfig() = WishboneConfig(
addressWidth = 30,
dataWidth = 32,
selWidth = 4,
useSTALL = false,
useLOCK = false,
useERR = true,
useRTY = false,
tgaWidth = 0,
tgcWidth = 0,
tgdWidth = 0,
useBTE = true,
useCTI = true
)
} }
@ -96,6 +112,29 @@ case class IBusSimpleBus(interfaceKeepData : Boolean) extends Bundle with IMaste
mm mm
} }
def toWishbone(): Wishbone = {
val wishboneConfig = IBusSimpleBus.getWishboneConfig()
val bus = Wishbone(wishboneConfig)
val cmdPipe = cmd.stage()
bus.ADR := (cmdPipe.pc >> 2)
bus.CTI := B"000"
bus.BTE := "00"
bus.SEL := "1111"
bus.WE := False
bus.DAT_MOSI.assignDontCare()
bus.CYC := cmdPipe.valid
bus.STB := cmdPipe.valid
cmdPipe.ready := cmdPipe.valid && bus.ACK
rsp.valid := bus.CYC && bus.ACK
rsp.inst := bus.DAT_MISO
rsp.error := False //TODO
bus
}
} }

View File

@ -624,6 +624,8 @@ public:
bool error; bool error;
}; };
uint32_t periphWriteTimer = 0;
queue<MemWrite> periphWritesGolden;
queue<MemWrite> periphWrites; queue<MemWrite> periphWrites;
queue<MemRead> periphRead; queue<MemRead> periphRead;
Workspace *ws; Workspace *ws;
@ -663,11 +665,11 @@ public:
} }
virtual void dWrite(int32_t address, int32_t size, uint32_t data){ virtual void dWrite(int32_t address, int32_t size, uint32_t data){
if((address & 0xF0000000) == 0xF0000000){ if((address & 0xF0000000) == 0xF0000000){
MemWrite t = periphWrites.front(); MemWrite w;
if(t.address != address || t.size != size || t.data != data){ w.address = address;
fail(); w.size = size;
} w.data = data;
periphWrites.pop(); periphWritesGolden.push(w);
}else { }else {
mem.write(address, size, (uint8_t*)&data); mem.write(address, size, (uint8_t*)&data);
} }
@ -677,6 +679,23 @@ public:
void step() { void step() {
rfWriteValid = false; rfWriteValid = false;
RiscvGolden::step(); RiscvGolden::step();
switch(periphWrites.empty() + uint32_t(periphWritesGolden.empty())*2){
case 3: periphWriteTimer = 0; break;
case 1: case 2: if(periphWriteTimer++ == 20){ cout << "periphWrite timout" << endl; fail();} break;
case 0:
MemWrite t = periphWrites.front();
MemWrite t2 = periphWritesGolden.front();
if(t.address != t2.address || t.size != t2.size || t.data != t2.data){
cout << "periphWrite missmatch" << endl;
fail();
}
periphWrites.pop();
periphWritesGolden.pop();
break;
}
} }
}; };
@ -903,7 +922,7 @@ public:
if(bootPc != -1) top->VexRiscv->core->prefetch_pc = bootPc; if(bootPc != -1) top->VexRiscv->core->prefetch_pc = bootPc;
#else #else
if(bootPc != -1) { if(bootPc != -1) {
#ifdef IBUS_SIMPLE #if defined(IBUS_SIMPLE) || defined(IBUS_SIMPLE_WISHBONE)
top->VexRiscv->IBusSimplePlugin_fetchPc_pcReg = bootPc; top->VexRiscv->IBusSimplePlugin_fetchPc_pcReg = bootPc;
#ifdef COMPRESSED #ifdef COMPRESSED
top->VexRiscv->IBusSimplePlugin_decodePc_pcReg = bootPc; top->VexRiscv->IBusSimplePlugin_decodePc_pcReg = bootPc;
@ -1261,10 +1280,9 @@ public:
#endif #endif
#ifdef IBUS_CACHED_WISHBONE #if defined(IBUS_CACHED_WISHBONE) || defined(IBUS_SIMPLE_WISHBONE)
#include <queue> #include <queue>
class IBusCachedWishbone : public SimElement{ class IBusCachedWishbone : public SimElement{
public: public:
@ -1282,21 +1300,24 @@ public:
} }
virtual void preCycle(){ virtual void preCycle(){
top->iBusWishbone_DAT_MISO = VL_RANDOM_I(32);
if (top->iBusWishbone_CYC && top->iBusWishbone_STB && top->iBusWishbone_ACK) {
if(top->iBusWishbone_WE){
} else {
bool error;
ws->iBusAccess(top->iBusWishbone_ADR << 2,&top->iBusWishbone_DAT_MISO,&error);
top->iBusWishbone_ERR = error;
}
}
} }
virtual void postCycle(){ virtual void postCycle(){
if(ws->iStall) if(ws->iStall)
top->iBusWishbone_ACK = VL_RANDOM_I(7) < 100; top->iBusWishbone_ACK = VL_RANDOM_I(7) < 100;
top->iBusWishbone_DAT_MISO = VL_RANDOM_I(32);
if (top->iBusWishbone_CYC && top->iBusWishbone_STB && top->iBusWishbone_ACK) {
if(top->iBusWishbone_WE){
} else {
bool error;
ws->iBusAccess(top->iBusWishbone_ADR << 2,&top->iBusWishbone_DAT_MISO,&error);
top->iBusWishbone_ERR = error;
}
}
} }
}; };
#endif #endif
@ -1398,7 +1419,7 @@ public:
}; };
#endif #endif
#ifdef DBUS_CACHED_WISHBONE #if defined(DBUS_CACHED_WISHBONE) || defined(DBUS_SIMPLE_WISHBONE)
#include <queue> #include <queue>
@ -1419,22 +1440,23 @@ public:
} }
virtual void preCycle(){ virtual void preCycle(){
top->dBusWishbone_DAT_MISO = VL_RANDOM_I(32);
if (top->dBusWishbone_CYC && top->dBusWishbone_STB && top->dBusWishbone_ACK) {
if(top->dBusWishbone_WE){
bool dummy;
ws->dBusAccess(top->dBusWishbone_ADR << 2 ,1,2,top->dBusWishbone_SEL,&top->dBusWishbone_DAT_MOSI,&dummy);
} else {
bool error;
ws->dBusAccess(top->dBusWishbone_ADR << 2,0,2,0xF,&top->dBusWishbone_DAT_MISO,&error);
top->dBusWishbone_ERR = error;
}
}
} }
virtual void postCycle(){ virtual void postCycle(){
if(ws->iStall) if(ws->iStall)
top->dBusWishbone_ACK = VL_RANDOM_I(7) < 100; top->dBusWishbone_ACK = VL_RANDOM_I(7) < 100;
top->dBusWishbone_DAT_MISO = VL_RANDOM_I(32);
if (top->dBusWishbone_CYC && top->dBusWishbone_STB && top->dBusWishbone_ACK) {
if(top->dBusWishbone_WE){
bool dummy;
ws->dBusAccess(top->dBusWishbone_ADR << 2 ,1,2,top->dBusWishbone_SEL,&top->dBusWishbone_DAT_MOSI,&dummy);
} else {
bool error;
ws->dBusAccess(top->dBusWishbone_ADR << 2,0,2,0xF,&top->dBusWishbone_DAT_MISO,&error);
top->dBusWishbone_ERR = error;
}
}
} }
}; };
#endif #endif
@ -1871,7 +1893,7 @@ void Workspace::fillSimELements(){
#ifdef IBUS_CACHED_AVALON #ifdef IBUS_CACHED_AVALON
simElements.push_back(new IBusCachedAvalon(this)); simElements.push_back(new IBusCachedAvalon(this));
#endif #endif
#ifdef IBUS_CACHED_WISHBONE #if defined(IBUS_CACHED_WISHBONE) || defined(IBUS_SIMPLE_WISHBONE)
simElements.push_back(new IBusCachedWishbone(this)); simElements.push_back(new IBusCachedWishbone(this));
#endif #endif
#ifdef DBUS_SIMPLE #ifdef DBUS_SIMPLE
@ -1886,7 +1908,7 @@ void Workspace::fillSimELements(){
#ifdef DBUS_CACHED_AVALON #ifdef DBUS_CACHED_AVALON
simElements.push_back(new DBusCachedAvalon(this)); simElements.push_back(new DBusCachedAvalon(this));
#endif #endif
#ifdef DBUS_CACHED_WISHBONE #if defined(DBUS_CACHED_WISHBONE) || defined(DBUS_SIMPLE_WISHBONE)
simElements.push_back(new DBusCachedWishbone(this)); simElements.push_back(new DBusCachedWishbone(this));
#endif #endif
#ifdef DEBUG_PLUGIN_STD #ifdef DEBUG_PLUGIN_STD