Add CsrInterface to allow custom CSR addition

Add CustomCsrDemoPlugin as a show case
This commit is contained in:
Dolu1990 2018-01-31 18:13:42 +01:00
parent 42e677ec0d
commit 30b05eaf96
17 changed files with 470 additions and 43 deletions

View File

@ -84,7 +84,6 @@ VexRiscv full max perf -> (RV32IM, 1.40 DMIPS/Mhz, 16KB-I$,16KB-D$, single cycle
Cyclone V -> 90 Mhz 1,261 ALMs
Cyclone IV -> 88 Mhz 2,780 LUT 1,788 FF
VexRiscv full with MMU (RV32IM, 1.17 DMIPS/Mhz with cache trashing, 4KB-I$, 4KB-D$, single cycle barrel shifter, debug module, catch exceptions, dynamic branch, MMU) ->
Artix 7 -> 223 Mhz 2085 LUT 2020 FF
Cyclone V -> 110 Mhz 1,503 ALMs

View File

@ -0,0 +1,36 @@
package vexriscv.demo
import spinal.core._
import vexriscv.plugin.{CsrInterface, Plugin}
import vexriscv.{DecoderService, Stageable, VexRiscv}
case class CustomCsrDemoArea(csrService : CsrInterface) extends Area{
val instructionCounter = Reg(UInt(32 bits))
val cycleCounter = Reg(UInt(32 bits))
csrService.rw(0xB04, instructionCounter)
csrService.r(0xB05, cycleCounter)
}
class CustomCsrDemoPlugin extends Plugin[VexRiscv]{
var csrStruct : CustomCsrDemoArea = null
//Callback to setup the plugin and ask for different services
override def setup(pipeline: VexRiscv): Unit = {
import pipeline.config._
val csrService = pipeline.service(classOf[CsrInterface])
csrStruct = pipeline plug CustomCsrDemoArea(csrService)
}
override def build(pipeline: VexRiscv): Unit = {
import pipeline._
import pipeline.config._
csrStruct.cycleCounter := csrStruct.cycleCounter + 1
when(writeBack.arbitration.isFiring) {
csrStruct.instructionCounter := csrStruct.instructionCounter + 1
}
}
}

View File

@ -50,17 +50,22 @@ object DhrystoneBench extends App{
)
getDmips(
name = "GenFullNoMmu",
gen = GenFullNoMmu.main(null),
test = "make clean run REDO=0 MMU=no "
name = "GenNoCacheNoMmuMaxPerf",
gen = GenNoCacheNoMmuMaxPerf.main(null),
test = "make clean run REDO=0 MMU=no CSR=no DBUS=SIMPLE IBUS=SIMPLE"
)
getDmips(
name = "GenFullNoMmuMaxPerf",
gen = GenFullNoMmuMaxPerf.main(null),
test = "make clean run REDO=0 MMU=no"
)
getDmips(
name = "GenFullNoMmu",
gen = GenFullNoMmu.main(null),
test = "make clean run REDO=0 MMU=no "
)
getDmips(
name = "GenFull",

View File

@ -0,0 +1,62 @@
package vexriscv.demo
import spinal.core._
import vexriscv.plugin._
import vexriscv.{VexRiscv, VexRiscvConfig, plugin}
/**
* Created by spinalvm on 15.06.17.
*/
//make clean run DBUS=SIMPLE IBUS=SIMPLE CSR=no MMU=no DEBUG_PLUGIN=no MUL=no DIV=no
object GenCustomCsr extends App{
def cpu() = new VexRiscv(
config = VexRiscvConfig(
plugins = List(
new CustomCsrDemoPlugin,
new CsrPlugin(CsrPluginConfig.small),
new PcManagerSimplePlugin(
resetVector = 0x00000000l,
relaxedPcCalculation = false
),
new IBusSimplePlugin(
interfaceKeepData = false,
catchAccessFault = false
),
new DBusSimplePlugin(
catchAddressMisaligned = false,
catchAccessFault = false
),
new DecoderSimplePlugin(
catchIllegalInstruction = false
),
new RegFilePlugin(
regFileReadyKind = plugin.SYNC,
zeroBoot = false
),
new IntAluPlugin,
new SrcPlugin(
separatedAddSub = false,
executeInsertion = false
),
new FullBarrielShifterPlugin,
new HazardSimplePlugin(
bypassExecute = true,
bypassMemory = true,
bypassWriteBack = true,
bypassWriteBackBuffer = true,
pessimisticUseSrc = false,
pessimisticWriteRegFile = false,
pessimisticAddressMatch = false
),
new BranchPlugin(
earlyBranch = false,
catchAddressMisaligned = false,
prediction = NONE
),
new YamlPlugin("cpu0.yaml")
)
)
)
SpinalVerilog(cpu())
}

View File

@ -0,0 +1,69 @@
package vexriscv.demo
import spinal.core._
import vexriscv.ip.{DataCacheConfig, InstructionCacheConfig}
import vexriscv.plugin._
import vexriscv.{VexRiscv, VexRiscvConfig, plugin}
/**
* Created by spinalvm on 15.06.17.
*/
object GenNoCacheNoMmuMaxPerf extends App{
def cpu() = new VexRiscv(
config = VexRiscvConfig(
plugins = List(
new PcManagerSimplePlugin(
resetVector = 0x80000000l,
relaxedPcCalculation = false
),
new IBusSimplePlugin(
interfaceKeepData = false,
catchAccessFault = true
),
new DBusSimplePlugin(
catchAddressMisaligned = true,
catchAccessFault = true,
earlyInjection = false
),
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 FullBarrielShifterPlugin(earlyInjection = true),
new HazardSimplePlugin(
bypassExecute = true,
bypassMemory = true,
bypassWriteBack = true,
bypassWriteBackBuffer = true,
pessimisticUseSrc = false,
pessimisticWriteRegFile = false,
pessimisticAddressMatch = false
),
new MulPlugin,
new DivPlugin,
new CsrPlugin(CsrPluginConfig.small),
new DebugPlugin(ClockDomain.current.clone(reset = Bool().setName("debugReset"))),
new BranchPlugin(
earlyBranch = true,
catchAddressMisaligned = true,
prediction = DYNAMIC_TARGET,
historyRamSizeLog2 = 8
),
new YamlPlugin("cpu0.yaml")
)
)
)
SpinalVerilog(cpu())
}

View File

@ -37,6 +37,12 @@ object VexRiscvSynthesisBench {
SpinalVerilog(GenFullNoMmu.cpu().setDefinitionName(getRtlPath().split("\\.").head))
}
val noCacheNoMmuMaxPerf= new Rtl {
override def getName(): String = "VexRiscv no cache no MMU max perf"
override def getRtlPath(): String = "VexRiscvNoCacheNoMmuMaxPerf.v"
SpinalVerilog(GenNoCacheNoMmuMaxPerf.cpu().setDefinitionName(getRtlPath().split("\\.").head))
}
val fullNoMmuMaxPerf= new Rtl {
override def getName(): String = "VexRiscv full no MMU max perf"
override def getRtlPath(): String = "VexRiscvFullNoMmuMaxPerf.v"
@ -49,8 +55,8 @@ object VexRiscvSynthesisBench {
SpinalVerilog(GenFull.cpu().setDefinitionName(getRtlPath().split("\\.").head))
}
// val rtls = List(smallestNoCsr, smallest, smallAndProductive, fullNoMmuNoCache, fullNoMmuMaxPerf, fullNoMmu, full)
val rtls = List(fullNoMmuMaxPerf)
// val rtls = List(smallestNoCsr, smallest, smallAndProductive, fullNoMmuNoCache, noCacheNoMmuMaxPerf, fullNoMmuMaxPerf, fullNoMmu, full)
val rtls = List(noCacheNoMmuMaxPerf, fullNoMmuMaxPerf)
val targets = XilinxStdTargets(
vivadoArtix7Path = "/eda/Xilinx/Vivado/2017.2/bin"

View File

@ -9,8 +9,8 @@ import scala.collection.mutable.ArrayBuffer
import scala.collection.mutable
/**
* Created by spinalvm on 21.03.17.
*/
* Created by spinalvm on 21.03.17.
*/
trait CsrAccess{
def canWrite : Boolean = false
@ -32,25 +32,25 @@ object CsrAccess {
case class ExceptionPortInfo(port : Flow[ExceptionCause],stage : Stage, priority : Int)
case class CsrPluginConfig(
catchIllegalAccess : Boolean,
mvendorid : BigInt,
marchid : BigInt,
mimpid : BigInt,
mhartid : BigInt,
misaExtensionsInit : Int,
misaAccess : CsrAccess,
mtvecAccess : CsrAccess,
mtvecInit : BigInt,
mepcAccess : CsrAccess,
mscratchGen : Boolean,
mcauseAccess : CsrAccess,
mbadaddrAccess : CsrAccess,
mcycleAccess : CsrAccess,
minstretAccess : CsrAccess,
ucycleAccess : CsrAccess,
wfiGen : Boolean,
ecallGen : Boolean
){
catchIllegalAccess : Boolean,
mvendorid : BigInt,
marchid : BigInt,
mimpid : BigInt,
mhartid : BigInt,
misaExtensionsInit : Int,
misaAccess : CsrAccess,
mtvecAccess : CsrAccess,
mtvecInit : BigInt,
mepcAccess : CsrAccess,
mscratchGen : Boolean,
mcauseAccess : CsrAccess,
mbadaddrAccess : CsrAccess,
mcycleAccess : CsrAccess,
minstretAccess : CsrAccess,
ucycleAccess : CsrAccess,
wfiGen : Boolean,
ecallGen : Boolean
){
assert(!ucycleAccess.canWrite)
}
@ -121,11 +121,22 @@ object CsrPluginConfig{
}
case class CsrWrite(that : Data, bitOffset : Int)
case class CsrRead(that : Data , bitOffset : Int)
case class CsrMapping(){
case class CsrMapping() extends CsrInterface{
val mapping = mutable.HashMap[Int,ArrayBuffer[Any]]()
def addMappingAt(address : Int,that : Any) = mapping.getOrElseUpdate(address,new ArrayBuffer[Any]) += that
def r(csrAddress : Int, bitOffset : Int, that : Data): Unit = addMappingAt(csrAddress, CsrRead(that,bitOffset))
def w(csrAddress : Int, bitOffset : Int, that : Data): Unit = addMappingAt(csrAddress, CsrWrite(that,bitOffset))
}
trait IContextSwitching{
def isContextSwitching : Bool
}
trait CsrInterface{
def r(csrAddress : Int, bitOffset : Int, that : Data): Unit
def w(csrAddress : Int, bitOffset : Int, that : Data): Unit
def rw(csrAddress : Int, bitOffset : Int,that : Data): Unit ={
r(csrAddress,bitOffset,that)
w(csrAddress,bitOffset,that)
@ -138,13 +149,7 @@ case class CsrMapping(){
}
trait IContextSwitching{
def isContextSwitching : Bool
}
class CsrPlugin(config : CsrPluginConfig) extends Plugin[VexRiscv] with ExceptionService with PrivilegeService with InterruptionInhibitor with ExceptionInhibitor with IContextSwitching{
class CsrPlugin(config : CsrPluginConfig) extends Plugin[VexRiscv] with ExceptionService with PrivilegeService with InterruptionInhibitor with ExceptionInhibitor with IContextSwitching with CsrInterface{
import config._
import CsrAccess._
@ -179,6 +184,13 @@ class CsrPlugin(config : CsrPluginConfig) extends Plugin[VexRiscv] with Exceptio
var allowInterrupts : Bool = null
var allowException : Bool = null
val csrMapping = new CsrMapping()
override def r(csrAddress: Int, bitOffset: Int, that: Data): Unit = csrMapping.r(csrAddress, bitOffset, that)
override def w(csrAddress: Int, bitOffset: Int, that: Data): Unit = csrMapping.w(csrAddress, bitOffset, that)
override def setup(pipeline: VexRiscv): Unit = {
import pipeline.config._
@ -210,7 +222,7 @@ class CsrPlugin(config : CsrPluginConfig) extends Plugin[VexRiscv] with Exceptio
CSRRWI -> immediatActions,
CSRRSI -> immediatActions,
CSRRCI -> immediatActions,
// EBREAK -> (defaultEnv ++ List(ENV_CTRL -> EnvCtrlEnum.EBREAK)), //TODO
// EBREAK -> (defaultEnv ++ List(ENV_CTRL -> EnvCtrlEnum.EBREAK)), //TODO
MRET -> (defaultEnv ++ List(ENV_CTRL -> EnvCtrlEnum.MRET))
))
if(wfiGen) decoderService.add(WFI, defaultEnv ++ List(ENV_CTRL -> EnvCtrlEnum.WFI))
@ -252,7 +264,6 @@ class CsrPlugin(config : CsrPluginConfig) extends Plugin[VexRiscv] with Exceptio
pipeline plug new Area{
//Define CSR mapping utilities
val csrMapping = new CsrMapping()
implicit class CsrAccessPimper(csrAccess : CsrAccess){
def apply(csrAddress : Int, thats : (Int, Data)*) : Unit = {
if(csrAccess == `WRITE_ONLY` || csrAccess == `READ_WRITE`) for(that <- thats) csrMapping.w(csrAddress,that._1, that._2)
@ -452,11 +463,9 @@ class CsrPlugin(config : CsrPluginConfig) extends Plugin[VexRiscv] with Exceptio
execute plug new Area {
import execute._
val illegalAccess = arbitration.isValid && input(IS_CSR)
val illegalAccess = True
if(catchIllegalAccess) {
val illegalInstruction = arbitration.isValid && privilege === 0 && (input(ENV_CTRL) === EnvCtrlEnum.EBREAK || input(ENV_CTRL) === EnvCtrlEnum.MRET)
selfException.valid := illegalAccess || illegalInstruction
selfException.valid := arbitration.isValid && input(IS_CSR) && illegalAccess
selfException.code := 2
selfException.badAddr.assignDontCare()
}
@ -471,7 +480,7 @@ class CsrPlugin(config : CsrPluginConfig) extends Plugin[VexRiscv] with Exceptio
True -> Mux(input(INSTRUCTION)(12), readDataReg & ~writeSrc, readDataReg | writeSrc)
)
val writeOpcode = (!((input(INSTRUCTION)(14 downto 13) === "01" && input(INSTRUCTION)(rs1Range) === 0)
|| (input(INSTRUCTION)(14 downto 13) === "11" && imm.z === 0)))
|| (input(INSTRUCTION)(14 downto 13) === "11" && imm.z === 0)))
val writeInstruction = arbitration.isValid && input(IS_CSR) && writeOpcode
arbitration.haltItself setWhen(writeInstruction && !readDataRegValid)

View File

@ -0,0 +1,44 @@
build/custom_csr.elf: file format elf32-littleriscv
Disassembly of section .crt_section:
00000000 <_start>:
0: 00100e13 li t3,1
4: b04020f3 csrr ra,mhpmcounter4
8: b0402173 csrr sp,mhpmcounter4
c: b04021f3 csrr gp,mhpmcounter4
10: 00208093 addi ra,ra,2
14: 00110113 addi sp,sp,1
18: 02309e63 bne ra,gp,54 <fail>
1c: 02311c63 bne sp,gp,54 <fail>
20: 00200e13 li t3,2
24: 005dc0b7 lui ra,0x5dc
28: 98a08093 addi ra,ra,-1654 # 5db98a <pass+0x5db92a>
2c: b0409073 csrw mhpmcounter4,ra
30: b0402173 csrr sp,mhpmcounter4
34: 02209063 bne ra,sp,54 <fail>
38: 00300e13 li t3,3
3c: b05020f3 csrr ra,mhpmcounter5
40: b0502173 csrr sp,mhpmcounter5
44: b05021f3 csrr gp,mhpmcounter5
48: 0020d663 ble sp,ra,54 <fail>
4c: 00315463 ble gp,sp,54 <fail>
50: 0100006f j 60 <pass>
00000054 <fail>:
54: f0100137 lui sp,0xf0100
58: f2410113 addi sp,sp,-220 # f00fff24 <pass+0xf00ffec4>
5c: 01c12023 sw t3,0(sp)
00000060 <pass>:
60: f0100137 lui sp,0xf0100
64: f2010113 addi sp,sp,-224 # f00fff20 <pass+0xf00ffec0>
68: 00012023 sw zero,0(sp)
6c: 00000013 nop
70: 00000013 nop
74: 00000013 nop
78: 00000013 nop
7c: 00000013 nop
80: 00000013 nop

Binary file not shown.

View File

@ -0,0 +1,10 @@
:10000000130E1000F32040B0732140B0F32140B034
:100010009380200013011100639E3002631C3102A3
:10002000130E2000B7C05D009380A098739040B07D
:10003000732140B063902002130E3000F32050B0C3
:10004000732150B0F32150B063D6200063543100C7
:100050006F000001370110F0130141F22320C101AC
:10006000370110F0130101F22320010013000000FA
:100070001300000013000000130000001300000034
:040080001300000069
:00000001FF

View File

@ -0,0 +1,30 @@
Memory Configuration
Name Origin Length Attributes
onChipRam 0x0000000000000000 0x0000000000002000 w !xr
*default* 0x0000000000000000 0xffffffffffffffff
Linker script and memory map
LOAD build/src/crt.o
LOAD /opt/riscv/bin/../lib/gcc/riscv64-unknown-elf/7.1.1/rv32i/ilp32/libgcc.a
START GROUP
LOAD /opt/riscv/bin/../lib/gcc/riscv64-unknown-elf/7.1.1/../../../../riscv64-unknown-elf/lib/rv32i/ilp32/libc.a
LOAD /opt/riscv/bin/../lib/gcc/riscv64-unknown-elf/7.1.1/../../../../riscv64-unknown-elf/lib/rv32i/ilp32/libgloss.a
END GROUP
LOAD /opt/riscv/bin/../lib/gcc/riscv64-unknown-elf/7.1.1/rv32i/ilp32/libgcc.a
0x0000000000000000 . = 0x0
.crt_section 0x0000000000000000 0x84
0x0000000000000000 . = ALIGN (0x4)
*crt.o(.text)
.text 0x0000000000000000 0x84 build/src/crt.o
0x0000000000000000 _start
OUTPUT(build/custom_csr.elf elf32-littleriscv)
.data 0x0000000000000084 0x0
.data 0x0000000000000084 0x0 build/src/crt.o
.bss 0x0000000000000084 0x0
.bss 0x0000000000000084 0x0 build/src/crt.o

View File

@ -0,0 +1,10 @@
@00000000
13 0E 10 00 F3 20 40 B0 73 21 40 B0 F3 21 40 B0
93 80 20 00 13 01 11 00 63 9E 30 02 63 1C 31 02
13 0E 20 00 B7 C0 5D 00 93 80 A0 98 73 90 40 B0
73 21 40 B0 63 90 20 02 13 0E 30 00 F3 20 50 B0
73 21 50 B0 F3 21 50 B0 63 D6 20 00 63 54 31 00
6F 00 00 01 37 01 10 F0 13 01 41 F2 23 20 C1 01
37 01 10 F0 13 01 01 F2 23 20 01 00 13 00 00 00
13 00 00 00 13 00 00 00 13 00 00 00 13 00 00 00
13 00 00 00

View File

@ -0,0 +1,73 @@
PROJ_NAME=custom_csr
RISCV_PATH=/opt/riscv/
CFLAGS += -march=rv32i -mabi=ilp32
RISCV_NAME = riscv64-unknown-elf
RISCV_OBJCOPY = $(RISCV_PATH)/bin/$(RISCV_NAME)-objcopy
RISCV_OBJDUMP = $(RISCV_PATH)/bin/$(RISCV_NAME)-objdump
RISCV_CLIB=$(RISCV_PATH)$(RISCV_NAME)/lib/
RISCV_CC=$(RISCV_PATH)/bin/$(RISCV_NAME)-gcc
LDSCRIPT=src/ld
SRCS = $(wildcard src/*.c) \
$(wildcard src/*.cpp) \
$(wildcard src/*.S)
CFLAGS += -static
LDFLAGS += -e_start -T $(LDSCRIPT) -nostartfiles -Wl,-Map,$(OBJDIR)/$(PROJ_NAME).map -Wl,--print-memory-usage
OBJDIR = build
OBJS := $(SRCS)
OBJS := $(OBJS:.c=.o)
OBJS := $(OBJS:.cpp=.o)
OBJS := $(OBJS:.S=.o)
OBJS := $(addprefix $(OBJDIR)/,$(OBJS))
all: $(OBJDIR)/$(PROJ_NAME).elf $(OBJDIR)/$(PROJ_NAME).hex $(OBJDIR)/$(PROJ_NAME).asm $(OBJDIR)/$(PROJ_NAME).v
@echo "done"
$(OBJDIR)/%.elf: $(OBJS) | $(OBJDIR)
$(RISCV_CC) $(CFLAGS) -o $@ $^ $(LDFLAGS) $(LIBS)
%.hex: %.elf
$(RISCV_OBJCOPY) -O ihex $^ $@
%.bin: %.elf
$(RISCV_OBJCOPY) -O binary $^ $@
%.v: %.elf
$(RISCV_OBJCOPY) -O verilog $^ $@
%.asm: %.elf
$(RISCV_OBJDUMP) -S -d $^ > $@
$(OBJDIR)/%.o: %.c
mkdir -p $(dir $@)
$(RISCV_CC) -c $(CFLAGS) $(INC) -o $@ $^
$(OBJDIR)/%.o: %.cpp
mkdir -p $(dir $@)
$(RISCV_CC) -c $(CFLAGS) $(INC) -o $@ $^
$(OBJDIR)/%.o: %.S
mkdir -p $(dir $@)
$(RISCV_CC) -c $(CFLAGS) -o $@ $^ -D__ASSEMBLY__=1
$(OBJDIR):
mkdir -p $@
clean:
rm -f $(OBJDIR)/$(PROJ_NAME).elf
rm -f $(OBJDIR)/$(PROJ_NAME).hex
rm -f $(OBJDIR)/$(PROJ_NAME).map
rm -f $(OBJDIR)/$(PROJ_NAME).v
rm -f $(OBJDIR)/$(PROJ_NAME).asm
find $(OBJDIR) -type f -name '*.o' -print0 | xargs -0 -r rm
.SECONDARY: $(OBJS)

View File

@ -0,0 +1,48 @@
.globl _start
_start:
//Test 1
li x28, 1
csrr x1, 0xB04
csrr x2, 0xB04
csrr x3, 0xB04
add x1, x1, 2
add x2, x2, 1
bne x1, x3, fail
bne x2, x3, fail
//Test 2
li x28, 2
li x1, 6142346
csrw 0xB04, x1
csrr x2, 0xB04
bne x1, x2, fail
//Test 3
li x28, 3
csrr x1, 0xB05
csrr x2, 0xB05
csrr x3, 0xB05
bge x1, x2, fail
bge x2, x3, fail
j pass
fail: //x28 => error code
li x2, 0xF00FFF24
sw x28, 0(x2)
pass:
li x2, 0xF00FFF20
sw x0, 0(x2)
nop
nop
nop
nop
nop
nop

View File

@ -0,0 +1,17 @@
OUTPUT_ARCH( "riscv" )
MEMORY {
onChipRam (W!RX)/*(RX)*/ : ORIGIN = 0x00000000, LENGTH = 8K
}
SECTIONS
{
. = 0x000;
.crt_section :
{
. = ALIGN(4);
*crt.o(.text)
} > onChipRam
}

View File

@ -1725,6 +1725,10 @@ int main(int argc, char **argv, char **env) {
redo(REDO,Workspace("custom_simd_add").loadHex("../custom/simd_add/build/custom_simd_add.hex")->bootAt(0x00000000u)->run(50e3););
#endif
#ifdef CUSTOM_CSR
redo(REDO,Workspace("custom_csr").loadHex("../custom/custom_csr/build/custom_csr.hex")->bootAt(0x00000000u)->run(50e3););
#endif
#ifdef ATOMIC
redo(REDO,Workspace("atomic").loadHex("../custom/atomic/build/atomic.hex")->bootAt(0x00000000u)->run(10e3););

View File

@ -12,6 +12,7 @@ ATOMIC?=no
DEBUG_PLUGIN?=STD
DEBUG_PLUGIN_EXTERNAL?=no
CUSTOM_SIMD_ADD?=no
CUSTOM_CSR?=no
DHRYSTONE=yes
FREERTOS=no
REDO?=10
@ -48,6 +49,10 @@ ifeq ($(CUSTOM_SIMD_ADD),yes)
ADDCFLAGS += -CFLAGS -DCUSTOM_SIMD_ADD
endif
ifeq ($(CUSTOM_CSR),yes)
ADDCFLAGS += -CFLAGS -DCUSTOM_CSR
endif
ifeq ($(TRACE_WITH_TIME),yes)
ADDCFLAGS += -CFLAGS -DTRACE_WITH_TIME
endif