diff --git a/.gitignore b/.gitignore index 938d762..b1d0ac7 100644 --- a/.gitignore +++ b/.gitignore @@ -34,4 +34,5 @@ bin/ *.json *.vcd !tester/src/test/resources/*.vhd +obj_dir diff --git a/sim/tester.cpp b/sim/tester.cpp index ea3793c..69bd5ca 100644 --- a/sim/tester.cpp +++ b/sim/tester.cpp @@ -1,11 +1,12 @@ #include "VVexRiscv.h" #include "verilated.h" #include "verilated_vcd_c.h" - +#include int main(int argc, char **argv, char **env) { int i; int clk; + printf("start\n"); Verilated::commandArgs(argc, argv); // init top verilog instance VVexRiscv* top = new VVexRiscv; @@ -34,5 +35,6 @@ int main(int argc, char **argv, char **env) { if (Verilated::gotFinish()) exit(0); } tfp->close(); + printf("done\n"); exit(0); } diff --git a/src/main/scala/SpinalRiscv/Pipeline.scala b/src/main/scala/SpinalRiscv/Pipeline.scala index d36e53d..8ee3be8 100644 --- a/src/main/scala/SpinalRiscv/Pipeline.scala +++ b/src/main/scala/SpinalRiscv/Pipeline.scala @@ -107,8 +107,11 @@ trait Pipeline { val stageBefore = stages(stageIndex - 1) val stage = stages(stageIndex) - when(!stageBefore.arbitration.isStuck) { - stage.arbitration.isValid := stage.arbitration.isValid && !stage.arbitration.removeIt + when(!stage.arbitration.isStuck) { + stage.arbitration.isValid := False + } + when(!stageBefore.arbitration.isStuck && !stageBefore.arbitration.removeIt) { + stage.arbitration.isValid := stageBefore.arbitration.isValid } when(stage.arbitration.removeIt){ stage.arbitration.isValid := False diff --git a/src/main/scala/SpinalRiscv/Stage.scala b/src/main/scala/SpinalRiscv/Stage.scala index a0da232..8534892 100644 --- a/src/main/scala/SpinalRiscv/Stage.scala +++ b/src/main/scala/SpinalRiscv/Stage.scala @@ -44,7 +44,7 @@ class Stage() extends Area{ // def apply[T <: Data](key : Stageable[T]) : T = ??? - val arbitration = new Bundle{ + val arbitration = new Area{ val haltIt = False val removeIt = False val isValid = RegInit(False) diff --git a/src/main/scala/SpinalRiscv/TopLevel.scala b/src/main/scala/SpinalRiscv/TopLevel.scala index 2c5d6f6..2561689 100644 --- a/src/main/scala/SpinalRiscv/TopLevel.scala +++ b/src/main/scala/SpinalRiscv/TopLevel.scala @@ -322,7 +322,7 @@ class PcManagerSimplePlugin(resetVector : BigInt,fastFetchCmdPcCalculation : Boo } //FetchService hardware implementation - val jump = if(jumpInfos.length != 0) { + val jump = if(jumpInfos.length != 0) new Area { val sortedByStage = jumpInfos.sortWith((a, b) => pipeline.indexOf(a.stage) > pipeline.indexOf(b.stage)) val valids = sortedByStage.map(_.interface.valid) val pcs = sortedByStage.map(_.interface.payload) @@ -360,11 +360,11 @@ class IBusSimplePlugin extends Plugin[VexRiscv]{ import pipeline._ import pipeline.config._ - iCmd = master(Stream(IBusSimpleCmd())) + iCmd = master(Stream(IBusSimpleCmd())).setName("iCmd") iCmd.valid := prefetch.arbitration.isFiring iCmd.pc := prefetch.output(PC) - iRsp = in(IBusSimpleRsp()) + iRsp = in(IBusSimpleRsp()).setName("iRsp") fetch.insert(INSTRUCTION) := iRsp.inst } } @@ -431,7 +431,7 @@ class DBusSimplePlugin extends Plugin[VexRiscv]{ execute plug new Area{ import execute._ - dCmd = master Stream(DBusSimpleCmd()) + dCmd = master(Stream(DBusSimpleCmd())).setName("dCmd") dCmd.valid := input(MEMORY_ENABLE) && arbitration.isFiring dCmd.wr := input(INSTRUCTION)(5) dCmd.address := input(SRC_ADD_SUB).asUInt @@ -440,12 +440,14 @@ class DBusSimplePlugin extends Plugin[VexRiscv]{ when(input(MEMORY_ENABLE) && !dCmd.ready){ arbitration.haltIt := True } + + dCmd.elements } memory plug new Area { import memory._ - dRsp = in(DBusSimpleRsp()) + dRsp = in(DBusSimpleRsp()).setName("dRsp") insert(MEMORY_READ_DATA) := dRsp.data assert(!(input(MEMORY_ENABLE) && !input(INSTRUCTION)(5) && arbitration.isStuck),"DBusSimplePlugin doesn't allow memory stage stall when read happend") } @@ -453,7 +455,6 @@ class DBusSimplePlugin extends Plugin[VexRiscv]{ writeBack plug new Area { import memory._ - dRsp = in(DBusSimpleRsp()) val rspFormated = input(INSTRUCTION)(13 downto 12).mux( default -> input(MEMORY_READ_DATA), //W 1 -> B((31 downto 8) -> (input(MEMORY_READ_DATA)(7) && !input(INSTRUCTION)(14)),(7 downto 0) -> input(MEMORY_READ_DATA)(7 downto 0)), @@ -593,7 +594,7 @@ class RegFilePlugin(regFileReadyKind : RegFileReadKind) extends Plugin[VexRiscv] writeBack plug new Area { import writeBack._ - val regFileWrite = global.regFile.writePort + val regFileWrite = global.regFile.writePort.addAttribute("verilator public") regFileWrite.valid := input(REGFILE_WRITE_VALID) && arbitration.isFiring regFileWrite.address := input(INSTRUCTION)(rdRange).asUInt regFileWrite.data := input(REGFILE_WRITE_DATA) @@ -686,6 +687,7 @@ class IntAluPlugin extends Plugin[VexRiscv]{ val decoderService = pipeline.service(classOf[DecoderService]) + decoderService.addDefault(REGFILE_WRITE_VALID,False) decoderService.add(List( ADD -> (nonImmediateActions ++ List(ALU_CTRL -> AluCtrlEnum.ADD_SUB, SRC_USE_SUB_LESS -> False)), SUB -> (nonImmediateActions ++ List(ALU_CTRL -> AluCtrlEnum.ADD_SUB, SRC_USE_SUB_LESS -> True)), @@ -806,11 +808,11 @@ class FullBarrielShifterPlugin extends Plugin[VexRiscv]{ } } -class OutputAluResult extends Plugin[VexRiscv]{ - override def build(pipeline: VexRiscv): Unit = { - out(pipeline.writeBack.input(pipeline.config.REGFILE_WRITE_DATA)) - } -} +//class OutputAluResult extends Plugin[VexRiscv]{ +// override def build(pipeline: VexRiscv): Unit = { +// out(pipeline.writeBack.input(pipeline.config.REGFILE_WRITE_DATA)) +// } +//} object TopLevel { @@ -829,13 +831,19 @@ object TopLevel { new SrcPlugin, new FullBarrielShifterPlugin, new DBusSimplePlugin, - new HazardSimplePlugin(true,true,true,true), -// new HazardSimplePlugin(false,false,false,false), - new NoPredictionBranchPlugin, - new OutputAluResult +// new HazardSimplePlugin(true,true,true,true), + new HazardSimplePlugin(false,false,false,false), + new NoPredictionBranchPlugin +// new OutputAluResult ) - new VexRiscv(config) + val toplevel = new VexRiscv(config) + +// val iBus = toplevel.service(classOf[IBusSimplePlugin]) +// val dBus = toplevel.service(classOf[DBusSimplePlugin]) + + + toplevel } } } diff --git a/src/test/cpp/testA/main.cpp b/src/test/cpp/testA/main.cpp new file mode 100644 index 0000000..fba584e --- /dev/null +++ b/src/test/cpp/testA/main.cpp @@ -0,0 +1,163 @@ +#include "VVexRiscv.h" +#include "VVexRiscv_VexRiscv.h" +#include "verilated.h" +#include "verilated_vcd_c.h" +#include +#include +#include + +uint8_t memory[1024 * 1024]; + +uint32_t hti(char c) { + if (c >= 'A' && c <= 'F') + return c - 'A' + 10; + if (c >= 'a' && c <= 'f') + return c - 'a' + 10; + return c - '0'; +} + +uint32_t hToI(char *c, uint32_t size) { + uint32_t value = 0; + for (uint32_t i = 0; i < size; i++) { + value += hti(c[i]) << ((size - i - 1) * 4); + } + return value; +} + +void loadHex(const char* path) { + FILE *fp = fopen(path, "r"); + fseek(fp, 0, SEEK_END); + uint32_t size = ftell(fp); + fseek(fp, 0, SEEK_SET); + char* content = new char[size]; + fread(content, 1, size, fp); + + int offset = 0; + char* line = content; + while (1) { + if (line[0] == ':') { + uint32_t byteCount = hToI(line + 1, 2); + uint32_t nextAddr = hToI(line + 3, 4) + offset; + uint32_t key = hToI(line + 7, 2); + //printf("%d %d %d\n", byteCount, nextAddr,key); + switch (key) { + case 0: + for (uint32_t i = 0; i < byteCount; i++) { + memory[nextAddr + i] = hToI(line + 9 + i * 2, 2); + //printf("%x %x %c%c\n",nextAddr + i,hToI(line + 9 + i*2,2),line[9 + i * 2],line[9 + i * 2+1]); + } + break; + case 2: + offset = hToI(line + 9, 4) << 4; + break; + case 4: + offset = hToI(line + 9, 4) << 16; + break; + + } + } + + while (*line != '\n' && size != 0) { + line++; + size--; + } + if (size <= 1) + break; + line++; + size--; + } + + delete content; +} + + +#define testA1ReagFileWriteRef {1,10},{2,20},{3,40},{4,60} +#define testA2ReagFileWriteRef {5,1},{7,3} +uint32_t regFileWriteRefIndex = 0; +uint32_t regFileWriteRefArray[][2] = { + testA1ReagFileWriteRef, + testA1ReagFileWriteRef, + testA2ReagFileWriteRef, + testA2ReagFileWriteRef +}; + +#define TEXTIFY(A) #A + +#define assertEq(x,ref) if(x != ref) {\ + printf("\n*** %s is %d but should be %d ***\n\n",TEXTIFY(x),x,ref);\ + error = 1;\ +} + +int main(int argc, char **argv, char **env) { + int i; + int clk; + int error = 0; + printf("start\n"); + loadHex("testA.hex"); + Verilated::commandArgs(argc, argv); + // init top verilog instance + VVexRiscv* top = new VVexRiscv; + // init trace dump + Verilated::traceEverOn(true); + VerilatedVcdC* tfp = new VerilatedVcdC; + top->trace(tfp, 99); + tfp->open("sim.vcd"); + + // Reset + top->clk = 1; + top->reset = 1; + top->iCmd_ready = 1; + top->dCmd_ready = 1; + for (uint32_t i = 0; i < 16; i++) { + tfp->dump(i); + top->eval(); + } + top->reset = 0; + + // run simulation for 100 clock periods + for (i = 16; i < 600; i+=2) { + + uint32_t iRsp_inst_next = top->iRsp_inst; + if (top->iCmd_valid) { + assert((top->iCmd_payload_pc & 3) == 0); + uint8_t* ptr = memory + top->iCmd_payload_pc; + iRsp_inst_next = (ptr[0] << 0) | (ptr[1] << 8) | (ptr[2] << 16) | (ptr[3] << 24); + } + + if(top->VexRiscv->writeBack_RegFilePlugin_regFileWrite_valid == 1 && top->VexRiscv->writeBack_RegFilePlugin_regFileWrite_payload_address != 0){ + assertEq(top->VexRiscv->writeBack_RegFilePlugin_regFileWrite_payload_address, regFileWriteRefArray[regFileWriteRefIndex][0]); + assertEq(top->VexRiscv->writeBack_RegFilePlugin_regFileWrite_payload_data, regFileWriteRefArray[regFileWriteRefIndex][1]); + printf("%d\n",i); + + regFileWriteRefIndex++; + if(regFileWriteRefIndex == sizeof(regFileWriteRefArray)/sizeof(regFileWriteRefArray[0])){ + tfp->dump(i); + tfp->dump(i+1); + printf("SUCCESS\n"); + break; + } + } + + if(error) { + tfp->dump(i); + tfp->dump(i+1); + break; + } + // dump variables into VCD file and toggle clock + for (clk = 0; clk < 2; clk++) { + tfp->dump(i+ clk); + top->clk = !top->clk; + + top->eval(); + } + + top->iRsp_inst = iRsp_inst_next; + + if (Verilated::gotFinish()) + exit(0); + } + + tfp->close(); + printf("done\n"); + exit(0); +} diff --git a/src/test/cpp/testA/makefile b/src/test/cpp/testA/makefile new file mode 100644 index 0000000..f3e7d04 --- /dev/null +++ b/src/test/cpp/testA/makefile @@ -0,0 +1,12 @@ +run: compile + ./obj_dir/VVexRiscv + +verilate: + verilator -cc ../../../../VexRiscv.v --trace -Wno-WIDTH --exe main.cpp + +compile: verilate + make -j -C obj_dir/ -f VVexRiscv.mk VVexRiscv + +clean: + rm -rf obj_dir + diff --git a/src/test/cpp/testA/testA.hex b/src/test/cpp/testA/testA.hex new file mode 100644 index 0000000..8bb3b24 --- /dev/null +++ b/src/test/cpp/testA/testA.hex @@ -0,0 +1,29 @@ +:1000000013000000130000001300000013000000A4 +:100010001300000013000000130000009300A00074 +:100020001300000013000000130000001300000084 +:100030001300000013000000130000001301400132 +:100040001300000013000000130000001300000064 +:100050001300000013000000130000009381E00172 +:100060001300000013000000130000001300000044 +:100070001300000013000000130000003382210071 +:100080001300000013000000130000001300000024 +:100090001300000013000000130000009300A000F4 +:1000A000130140019381E00133822100130000001D +:1000B00013000000130000001300000013000000F4 +:1000C00013000000130000001300000013000000E4 +:1000D00013000000130000001300000013000000D4 +:1000E00013000000130000001300000013000000C4 +:1000F00013000000130000001300000013000000B4 +:1001000013000000130000001300000013000000A3 +:100110001300000013000000130000009302100001 +:100120001300000013000000130000001300000083 +:100130001300000013000000130000006F00000413 +:100140001300000013000000130000001300000063 +:100150001300000013000000130000001303200030 +:100160001300000013000000130000001300000043 +:100170001300000013000000130000009303300080 +:100180001300000013000000130000001300000023 +:100190001300000013000000130000009302100081 +:0C01A0006F008000130320009303300068 +:0400000540000000B7 +:00000001FF diff --git a/src/test/cpp/testA/yolo.gtkw b/src/test/cpp/testA/yolo.gtkw new file mode 100644 index 0000000..9c921cf --- /dev/null +++ b/src/test/cpp/testA/yolo.gtkw @@ -0,0 +1,57 @@ +[*] +[*] GTKWave Analyzer v3.3.58 (w)1999-2014 BSI +[*] Sun Mar 12 18:21:04 2017 +[*] +[dumpfile] "/home/spinalvm/Spinal/VexRiscv/src/test/cpp/testA/sim.vcd" +[dumpfile_mtime] "Sun Mar 12 18:18:56 2017" +[dumpfile_size] 105148 +[savefile] "/home/spinalvm/Spinal/VexRiscv/src/test/cpp/testA/yolo.gtkw" +[timestart] 156 +[size] 1776 953 +[pos] -1 -1 +*-4.022038 200 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 +[treeopen] TOP. +[sst_width] 487 +[signals_width] 559 +[sst_expanded] 1 +[sst_vpaned_height] 279 +@28 +TOP.VexRiscv.decode_BRANCH_CTRL[1:0] +TOP.VexRiscv.execute_BRANCH_SOLVED[1:0] +TOP.VexRiscv.execute_input_BRANCH_CTRL[1:0] +TOP.VexRiscv.execute_input_BRANCH_SOLVED[1:0] +TOP.VexRiscv.decode_arbitration_isValid +TOP.VexRiscv.decode_arbitration_isStuck +@22 +TOP.VexRiscv.decode_input_INSTRUCTION[31:0] +TOP.VexRiscv.decode_input_PC[31:0] +TOP.VexRiscv.iCmd_payload_pc[31:0] +@28 +TOP.VexRiscv.iCmd_ready +TOP.VexRiscv.iCmd_valid +@22 +TOP.VexRiscv.iRsp_inst[31:0] +TOP.VexRiscv.prefetch_PcManagerSimplePlugin_jump_pcLoad_payload[31:0] +@28 +TOP.VexRiscv.prefetch_PcManagerSimplePlugin_jump_pcLoad_valid +TOP.VexRiscv.prefetch_arbitration_isValid +TOP.VexRiscv.fetch_arbitration_isValid +TOP.VexRiscv.decode_arbitration_isValid +TOP.VexRiscv.execute_arbitration_isValid +TOP.VexRiscv.memory_arbitration_isValid +TOP.VexRiscv.writeBack_arbitration_isValid +TOP.VexRiscv.prefetch_arbitration_removeIt +TOP.VexRiscv.fetch_arbitration_removeIt +TOP.VexRiscv.decode_arbitration_removeIt +TOP.VexRiscv.execute_arbitration_removeIt +TOP.VexRiscv.memory_arbitration_removeIt +TOP.VexRiscv.writeBack_arbitration_removeIt +@29 +TOP.VexRiscv.writeBack_RegFilePlugin_regFileWrite_valid +@22 +TOP.VexRiscv.writeBack_RegFilePlugin_regFileWrite_payload_address[4:0] +TOP.VexRiscv.writeBack_RegFilePlugin_regFileWrite_payload_data[31:0] +@28 +TOP.VexRiscv.clk +[pattern_trace] 1 +[pattern_trace] 0