Add full avalon support (pass regression)
This commit is contained in:
parent
52f5020e64
commit
54f785b1a3
|
@ -20,6 +20,7 @@ This repository host an RISC-V implementation written in SpinalHDL. There is som
|
|||
- Pipelined on 5 stages (Fetch, Decode, Execute, Memory, WriteBack)
|
||||
- 1.16 DMIPS/Mhz when all features are enabled
|
||||
- Optimized for FPGA
|
||||
- AXI4 and Avalon ready
|
||||
- Optional MUL/DIV extension
|
||||
- Optional instruction and data caches
|
||||
- Optional MMU
|
||||
|
|
|
@ -4,6 +4,7 @@ import VexRiscv._
|
|||
import spinal.core._
|
||||
import spinal.lib._
|
||||
import spinal.lib.bus.amba4.axi._
|
||||
import spinal.lib.bus.avalon.{AvalonMMConfig, AvalonMM}
|
||||
|
||||
|
||||
case class DBusSimpleCmd() extends Bundle{
|
||||
|
@ -36,6 +37,13 @@ object DBusSimpleBus{
|
|||
useLen = false,
|
||||
useResp = true
|
||||
)
|
||||
|
||||
def getAvalonConfig() = AvalonMMConfig.pipelined(
|
||||
addressWidth = 32,
|
||||
dataWidth = 32).copy(
|
||||
useByteEnable = true,
|
||||
maximumPendingReadTransactions = 1
|
||||
)
|
||||
}
|
||||
case class DBusSimpleBus() extends Bundle with IMasterSlave{
|
||||
val cmd = Stream(DBusSimpleCmd())
|
||||
|
@ -92,6 +100,35 @@ case class DBusSimpleBus() extends Bundle with IMasterSlave{
|
|||
// axi2 << axi
|
||||
axi2
|
||||
}
|
||||
|
||||
|
||||
|
||||
def toAvalon(stageCmd : Boolean = true): AvalonMM = {
|
||||
val avalonConfig = DBusSimpleBus.getAvalonConfig()
|
||||
val mm = AvalonMM(avalonConfig)
|
||||
val cmdStage = if(stageCmd) cmd.stage else cmd
|
||||
mm.read := cmdStage.valid && !cmdStage.wr
|
||||
mm.write := cmdStage.valid && cmdStage.wr
|
||||
mm.address := (cmdStage.address >> 2) @@ U"00"
|
||||
mm.writeData := cmdStage.size.mux (
|
||||
U(0) -> cmdStage.data(7 downto 0) ## cmdStage.data(7 downto 0) ## cmdStage.data(7 downto 0) ## cmdStage.data(7 downto 0),
|
||||
U(1) -> cmdStage.data(15 downto 0) ## cmdStage.data(15 downto 0),
|
||||
default -> cmdStage.data(31 downto 0)
|
||||
)
|
||||
mm.byteEnable := (cmdStage.size.mux (
|
||||
U(0) -> B"0001",
|
||||
U(1) -> B"0011",
|
||||
default -> B"1111"
|
||||
) << cmdStage.address(1 downto 0)).resized
|
||||
|
||||
|
||||
cmdStage.ready := mm.waitRequestn
|
||||
rsp.ready :=mm.readDataValid
|
||||
rsp.error := False //TODO
|
||||
rsp.data := mm.readData
|
||||
|
||||
mm
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@ import VexRiscv.{Stageable, ExceptionService, ExceptionCause, VexRiscv}
|
|||
import spinal.core._
|
||||
import spinal.lib._
|
||||
import spinal.lib.bus.amba4.axi._
|
||||
import spinal.lib.bus.avalon.{AvalonMMConfig, AvalonMM}
|
||||
|
||||
|
||||
case class IBusSimpleCmd() extends Bundle{
|
||||
|
@ -33,6 +34,13 @@ object IBusSimpleBus{
|
|||
useResp = true,
|
||||
useSize = false
|
||||
)
|
||||
|
||||
def getAvalonConfig() = AvalonMMConfig.pipelined(
|
||||
addressWidth = 32,
|
||||
dataWidth = 32
|
||||
).getReadOnlyConfig.copy(
|
||||
maximumPendingReadTransactions = 1
|
||||
)
|
||||
}
|
||||
case class IBusSimpleBus(interfaceKeepData : Boolean) extends Bundle with IMasterSlave{
|
||||
var cmd = Stream(IBusSimpleCmd())
|
||||
|
@ -68,6 +76,22 @@ case class IBusSimpleBus(interfaceKeepData : Boolean) extends Bundle with IMaste
|
|||
// axi2 << axi
|
||||
axi2
|
||||
}
|
||||
|
||||
def toAvalon(): AvalonMM = {
|
||||
assert(!interfaceKeepData)
|
||||
val avalonConfig = IBusSimpleBus.getAvalonConfig()
|
||||
val mm = AvalonMM(avalonConfig)
|
||||
|
||||
mm.read := cmd.valid
|
||||
mm.address := (cmd.pc >> 2) @@ U"00"
|
||||
cmd.ready := mm.waitRequestn
|
||||
|
||||
rsp.ready := mm.readDataValid
|
||||
rsp.inst := mm.readData
|
||||
rsp.error := False //TODO
|
||||
|
||||
mm
|
||||
}
|
||||
}
|
||||
|
||||
class IBusSimplePlugin(interfaceKeepData : Boolean, catchAccessFault : Boolean) extends Plugin[VexRiscv]{
|
||||
|
|
|
@ -33,7 +33,7 @@ object TestsWorkspace {
|
|||
plugins = List(
|
||||
new PcManagerSimplePlugin(0x00000000l, false),
|
||||
// new IBusSimplePlugin(
|
||||
// interfaceKeepData = true,
|
||||
// interfaceKeepData = false,
|
||||
// catchAccessFault = true
|
||||
// ),
|
||||
new IBusCachedPlugin(
|
||||
|
@ -229,12 +229,24 @@ object TestsWorkspace {
|
|||
toplevel.rework {
|
||||
var iBus : AvalonMM = null
|
||||
for (plugin <- toplevel.config.plugins) plugin match {
|
||||
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
|
||||
iBus = master(plugin.iBus.toAvalon())
|
||||
.setName("iBusAvalon")
|
||||
.addTag(ClockDomainTag(ClockDomain.current)) //Specify a clock domain to the iBus (used by QSysify)
|
||||
}
|
||||
case plugin: DBusSimplePlugin => {
|
||||
plugin.dBus.asDirectionLess()
|
||||
master(plugin.dBus.toAvalon())
|
||||
.setName("dBusAvalon")
|
||||
.addTag(ClockDomainTag(ClockDomain.current))
|
||||
}
|
||||
case plugin: DBusCachedPlugin => {
|
||||
plugin.dBus.asDirectionLess()
|
||||
master(plugin.dBus.toAvalon())
|
||||
|
|
|
@ -131,12 +131,24 @@ object VexRiscvAvalon{
|
|||
cpu.rework {
|
||||
var iBus : AvalonMM = null
|
||||
for (plugin <- cpuConfig.plugins) plugin match {
|
||||
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
|
||||
iBus = master(plugin.iBus.toAvalon())
|
||||
.setName("iBusAvalon")
|
||||
.addTag(ClockDomainTag(ClockDomain.current)) //Specify a clock domain to the iBus (used by QSysify)
|
||||
}
|
||||
case plugin: DBusSimplePlugin => {
|
||||
plugin.dBus.asDirectionLess()
|
||||
master(plugin.dBus.toAvalon())
|
||||
.setName("dBusAvalon")
|
||||
.addTag(ClockDomainTag(ClockDomain.current))
|
||||
}
|
||||
case plugin: DBusCachedPlugin => {
|
||||
plugin.dBus.asDirectionLess()
|
||||
master(plugin.dBus.toAvalon())
|
||||
|
|
|
@ -491,6 +491,53 @@ public:
|
|||
};
|
||||
#endif
|
||||
|
||||
#ifdef IBUS_SIMPLE_AVALON
|
||||
#include <queue>
|
||||
struct IBusSimpleAvalonRsp{
|
||||
uint32_t data;
|
||||
bool error;
|
||||
};
|
||||
|
||||
|
||||
class IBusSimpleAvalon : public SimElement{
|
||||
public:
|
||||
queue<IBusSimpleAvalonRsp> rsps;
|
||||
|
||||
Workspace *ws;
|
||||
VVexRiscv* top;
|
||||
IBusSimpleAvalon(Workspace* ws){
|
||||
this->ws = ws;
|
||||
this->top = ws->top;
|
||||
}
|
||||
|
||||
virtual void onReset(){
|
||||
top->iBusAvalon_waitRequestn = 1;
|
||||
top->iBusAvalon_readDataValid = 0;
|
||||
}
|
||||
|
||||
virtual void preCycle(){
|
||||
if (top->iBusAvalon_read && top->iBusAvalon_waitRequestn) {
|
||||
IBusSimpleAvalonRsp rsp;
|
||||
ws->iBusAccess(top->iBusAvalon_address,&rsp.data,&rsp.error);
|
||||
rsps.push(rsp);
|
||||
}
|
||||
}
|
||||
//TODO doesn't catch when instruction removed ?
|
||||
virtual void postCycle(){
|
||||
if(!rsps.empty() && (!ws->iStall || VL_RANDOM_I(7) < 100)){
|
||||
IBusSimpleAvalonRsp rsp = rsps.front(); rsps.pop();
|
||||
top->iBusAvalon_readDataValid = 1;
|
||||
top->iBusAvalon_readData = rsp.data;
|
||||
} else {
|
||||
top->iBusAvalon_readDataValid = 0;
|
||||
top->iBusAvalon_readData = VL_RANDOM_I(32);
|
||||
}
|
||||
if(ws->iStall)
|
||||
top->iBusAvalon_waitRequestn = VL_RANDOM_I(7) < 100;
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef IBUS_CACHED
|
||||
class IBusCached : public SimElement{
|
||||
|
@ -635,6 +682,59 @@ public:
|
|||
};
|
||||
#endif
|
||||
|
||||
#ifdef DBUS_SIMPLE_AVALON
|
||||
#include <queue>
|
||||
struct DBusSimpleAvalonRsp{
|
||||
uint32_t data;
|
||||
bool error;
|
||||
};
|
||||
|
||||
|
||||
class DBusSimpleAvalon : public SimElement{
|
||||
public:
|
||||
queue<DBusSimpleAvalonRsp> rsps;
|
||||
|
||||
Workspace *ws;
|
||||
VVexRiscv* top;
|
||||
DBusSimpleAvalon(Workspace* ws){
|
||||
this->ws = ws;
|
||||
this->top = ws->top;
|
||||
}
|
||||
|
||||
virtual void onReset(){
|
||||
top->dBusAvalon_waitRequestn = 1;
|
||||
top->dBusAvalon_readDataValid = 0;
|
||||
}
|
||||
|
||||
virtual void preCycle(){
|
||||
if (top->dBusAvalon_write && top->dBusAvalon_waitRequestn) {
|
||||
bool dummy;
|
||||
ws->dBusAccess(top->dBusAvalon_address,1,2,top->dBusAvalon_byteEnable,&top->dBusAvalon_writeData,&dummy);
|
||||
}
|
||||
if (top->dBusAvalon_read && top->dBusAvalon_waitRequestn) {
|
||||
DBusSimpleAvalonRsp rsp;
|
||||
ws->dBusAccess(top->dBusAvalon_address,0,2,0xF,&rsp.data,&rsp.error);
|
||||
rsps.push(rsp);
|
||||
}
|
||||
}
|
||||
//TODO doesn't catch when instruction removed ?
|
||||
virtual void postCycle(){
|
||||
if(!rsps.empty() && (!ws->iStall || VL_RANDOM_I(7) < 100)){
|
||||
DBusSimpleAvalonRsp rsp = rsps.front(); rsps.pop();
|
||||
top->dBusAvalon_readDataValid = 1;
|
||||
top->dBusAvalon_readData = rsp.data;
|
||||
} else {
|
||||
top->dBusAvalon_readDataValid = 0;
|
||||
top->dBusAvalon_readData = VL_RANDOM_I(32);
|
||||
}
|
||||
if(ws->iStall)
|
||||
top->dBusAvalon_waitRequestn = VL_RANDOM_I(7) < 100;
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#ifdef DBUS_CACHED
|
||||
class DBusCached : public SimElement{
|
||||
public:
|
||||
|
@ -1039,6 +1139,9 @@ void Workspace::fillSimELements(){
|
|||
#ifdef IBUS_SIMPLE
|
||||
simElements.push_back(new IBusSimple(this));
|
||||
#endif
|
||||
#ifdef IBUS_SIMPLE_AVALON
|
||||
simElements.push_back(new IBusSimpleAvalon(this));
|
||||
#endif
|
||||
#ifdef IBUS_CACHED
|
||||
simElements.push_back(new IBusCached(this));
|
||||
#endif
|
||||
|
@ -1048,6 +1151,9 @@ void Workspace::fillSimELements(){
|
|||
#ifdef DBUS_SIMPLE
|
||||
simElements.push_back(new DBusSimple(this));
|
||||
#endif
|
||||
#ifdef DBUS_SIMPLE_AVALON
|
||||
simElements.push_back(new DBusSimpleAvalon(this));
|
||||
#endif
|
||||
#ifdef DBUS_CACHED
|
||||
simElements.push_back(new DBusCached(this));
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue