Better decoding

This commit is contained in:
Charles Papon 2017-03-13 18:30:37 +01:00
parent e36c90af03
commit df99a0d963
4 changed files with 128 additions and 77 deletions

View File

@ -6,7 +6,7 @@ import spinal.lib._
import scala.collection.mutable import scala.collection.mutable
class Stageable[T <: Data](dataType : T) extends HardType[T](dataType) with Nameable{ class Stageable[T <: Data](val dataType : T) extends HardType[T](dataType) with Nameable{
setWeakName(this.getClass.getSimpleName.replace("$","")) setWeakName(this.getClass.getSimpleName.replace("$",""))
} }

View File

@ -146,61 +146,103 @@ class VexRiscv(val config : VexRiscvConfig) extends Component with Pipeline{
trait DecoderService{ trait DecoderService{
def add(key : MaskedLiteral,values : Seq[(Stageable[_ <: Data],Any)]) def add(key : MaskedLiteral,values : Seq[(Stageable[_ <: BaseType],Any)])
def add(encoding :Seq[(MaskedLiteral,Seq[(Stageable[_ <: Data],Any)])]) def add(encoding :Seq[(MaskedLiteral,Seq[(Stageable[_ <: BaseType],Any)])])
def addDefault(key : Stageable[_ <: Data], value : Any) def addDefault(key : Stageable[_ <: BaseType], value : Any)
} }
case class Node(val value : BigInt,val careAbout : BigInt){ case class Masked(value : BigInt,care : BigInt){
} }
class DecoderSimplePlugin extends Plugin[VexRiscv] with DecoderService { class DecoderSimplePlugin extends Plugin[VexRiscv] with DecoderService {
override def add(encoding: Seq[(MaskedLiteral, Seq[(Stageable[_ <: Data], Any)])]): Unit = encoding.foreach(e => this.add(e._1,e._2)) override def add(encoding: Seq[(MaskedLiteral, Seq[(Stageable[_ <: BaseType], Any)])]): Unit = encoding.foreach(e => this.add(e._1,e._2))
override def add(key: MaskedLiteral, values: Seq[(Stageable[_ <: Data], Any)]): Unit = { override def add(key: MaskedLiteral, values: Seq[(Stageable[_ <: BaseType], Any)]): Unit = {
require(!encodings.contains(key)) require(!encodings.contains(key))
encodings(key) = values.map{case (a,b) => (a,b match{ encodings(key) = values.map{case (a,b) => (a,b match{
case e : SpinalEnumElement[_] => e() case e : SpinalEnumElement[_] => e()
case e => e case e : BaseType => e
})} })}
} }
override def addDefault(key: Stageable[_ <: Data], value: Any): Unit = { override def addDefault(key: Stageable[_ <: BaseType], value: Any): Unit = {
require(!defaults.contains(key)) require(!defaults.contains(key))
defaults(key) = value match{ defaults(key) = value match{
case e : SpinalEnumElement[_] => e() case e : SpinalEnumElement[_] => e()
case e : Data => e case e : BaseType => e
} }
} }
val defaults = mutable.HashMap[Stageable[_ <: Data], Data]() val defaults = mutable.HashMap[Stageable[_ <: BaseType], BaseType]()
val encodings = mutable.HashMap[MaskedLiteral,Seq[(Stageable[_ <: Data], Any)]]() val encodings = mutable.HashMap[MaskedLiteral,Seq[(Stageable[_ <: BaseType], BaseType)]]()
override def build(pipeline: VexRiscv): Unit = { override def build(pipeline: VexRiscv): Unit = {
import pipeline.decode._ import pipeline.decode._
import pipeline.config._ import pipeline.config._
val stageables = encodings.flatMap(_._2.map(_._1)).toSet val stageables = (encodings.flatMap(_._2.map(_._1)) ++ defaults.map(_._1)).toSet.toList
var offset = 0
var defaultValue, defaultCare = BigInt(0)
val offsetOf = mutable.HashMap[Stageable[_ <: BaseType],Int]()
//Build defaults value and field offset map
stageables.foreach(e => {
defaults.get(e) match {
case Some(value) => {
value.input match {
case literal: EnumLiteral[_] => literal.fixEncoding(e.dataType.asInstanceOf[SpinalEnumCraft[_]].getEncoding)
case _ =>
}
defaultValue += value.input.asInstanceOf[Literal].getValue << offset
defaultCare += ((BigInt(1) << e.dataType.getBitsWidth) - 1) << offset
stageables.foreach(e => if(defaults.contains(e.asInstanceOf[Stageable[Data]]))
insert(e.asInstanceOf[Stageable[Data]]) := defaults(e.asInstanceOf[Stageable[Data]])
else
insert(e).assignDontCare())
stageables.foreach(insert(_) match{
case e : Bits => println(e.getWidth)
case _ =>
})
for((key,values) <- encodings){
when(input(INSTRUCTION) === key){
for((stageable,value) <- values){
insert(stageable).assignFrom(value.asInstanceOf[AnyRef],false)
} }
case _ =>
} }
offsetOf(e) = offset
offset += e.dataType.getBitsWidth
})
//Build spec
val spec = encodings.map { case (key, values) =>
var decodedValue, decodedCare = BigInt(0)
for((e, literal) <- values){
literal.input match{
case literal : EnumLiteral[_] => literal.fixEncoding(e.dataType.asInstanceOf[SpinalEnumCraft[_]].getEncoding)
case _ =>
}
val offset = offsetOf(e)
decodedValue += literal.input.asInstanceOf[Literal].getValue << offset
decodedCare += ((BigInt(1) << e.dataType.getBitsWidth)-1) << offset
}
(Masked(key.value,key.careAbout),Masked(decodedValue,decodedCare))
} }
// logic implementation
val decodedBits = Bits(stageables.foldLeft(0)(_ + _.dataType.getBitsWidth) bits)
val defaultBits = cloneOf(decodedBits)
// require(defaultValue == 0)
for(i <- decodedBits.range)
// if(defaultCare.testBit(i))
defaultBits(i) := Bool(defaultValue.testBit(i))
// else
// defaultBits(i).assignDontCare()
val localAnds = for((key, mapping) <- spec) yield Mux[Bits](((input(INSTRUCTION) & key.care) === (key.value & key.care)), B(mapping.value & mapping.care, decodedBits.getWidth bits) , B(0, decodedBits.getWidth bits))
decodedBits := localAnds.foldLeft(defaultBits)(_ | _)
//Unpack decodedBits and insert fields in the pipeline
offset = 0
stageables.foreach(e => {
insert(e).assignFromBits(decodedBits(offset, e.dataType.getBitsWidth bits))
offset += e.dataType.getBitsWidth
})
} }
def bench(toplevel : VexRiscv): Unit ={ def bench(toplevel : VexRiscv): Unit ={
@ -231,7 +273,7 @@ class NoPredictionBranchPlugin extends Plugin[VexRiscv]{
val decoderService = pipeline.service(classOf[DecoderService]) val decoderService = pipeline.service(classOf[DecoderService])
val bActions = List[(Stageable[_ <: Data],Any)]( val bActions = List[(Stageable[_ <: BaseType],Any)](
LEGAL_INSTRUCTION -> True, LEGAL_INSTRUCTION -> True,
SRC1_CTRL -> Src1CtrlEnum.RS, SRC1_CTRL -> Src1CtrlEnum.RS,
SRC2_CTRL -> Src2CtrlEnum.RS, SRC2_CTRL -> Src2CtrlEnum.RS,
@ -240,7 +282,7 @@ class NoPredictionBranchPlugin extends Plugin[VexRiscv]{
SRC2_USE -> True SRC2_USE -> True
) )
val jActions = List[(Stageable[_ <: Data],Any)]( val jActions = List[(Stageable[_ <: BaseType],Any)](
LEGAL_INSTRUCTION -> True, LEGAL_INSTRUCTION -> True,
SRC1_CTRL -> Src1CtrlEnum.FOUR, SRC1_CTRL -> Src1CtrlEnum.FOUR,
SRC2_CTRL -> Src2CtrlEnum.PC, SRC2_CTRL -> Src2CtrlEnum.PC,
@ -418,7 +460,7 @@ class DBusSimplePlugin extends Plugin[VexRiscv]{
val decoderService = pipeline.service(classOf[DecoderService]) val decoderService = pipeline.service(classOf[DecoderService])
val stdActions = List[(Stageable[_ <: Data],Any)]( val stdActions = List[(Stageable[_ <: BaseType],Any)](
LEGAL_INSTRUCTION -> True, LEGAL_INSTRUCTION -> True,
SRC1_CTRL -> Src1CtrlEnum.RS, SRC1_CTRL -> Src1CtrlEnum.RS,
SRC_USE_SUB_LESS -> False, SRC_USE_SUB_LESS -> False,
@ -675,7 +717,7 @@ class IntAluPlugin extends Plugin[VexRiscv]{
import pipeline.config._ import pipeline.config._
import Riscv._ import Riscv._
val immediateActions = List[(Stageable[_ <: Data],Any)]( val immediateActions = List[(Stageable[_ <: BaseType],Any)](
LEGAL_INSTRUCTION -> True, LEGAL_INSTRUCTION -> True,
SRC1_CTRL -> Src1CtrlEnum.RS, SRC1_CTRL -> Src1CtrlEnum.RS,
SRC2_CTRL -> Src2CtrlEnum.IMI, SRC2_CTRL -> Src2CtrlEnum.IMI,
@ -685,7 +727,7 @@ class IntAluPlugin extends Plugin[VexRiscv]{
SRC1_USE -> True SRC1_USE -> True
) )
val nonImmediateActions = List[(Stageable[_ <: Data],Any)]( val nonImmediateActions = List[(Stageable[_ <: BaseType],Any)](
LEGAL_INSTRUCTION -> True, LEGAL_INSTRUCTION -> True,
SRC1_CTRL -> Src1CtrlEnum.RS, SRC1_CTRL -> Src1CtrlEnum.RS,
SRC2_CTRL -> Src2CtrlEnum.RS, SRC2_CTRL -> Src2CtrlEnum.RS,
@ -768,7 +810,7 @@ class FullBarrielShifterPlugin extends Plugin[VexRiscv]{
val immediateActions = List[(Stageable[_ <: Data],Any)]( val immediateActions = List[(Stageable[_ <: BaseType],Any)](
LEGAL_INSTRUCTION -> True, LEGAL_INSTRUCTION -> True,
SRC1_CTRL -> Src1CtrlEnum.RS, SRC1_CTRL -> Src1CtrlEnum.RS,
SRC2_CTRL -> Src2CtrlEnum.IMI, SRC2_CTRL -> Src2CtrlEnum.IMI,
@ -777,7 +819,7 @@ class FullBarrielShifterPlugin extends Plugin[VexRiscv]{
BYPASSABLE_MEMORY_STAGE -> True BYPASSABLE_MEMORY_STAGE -> True
) )
val nonImmediateActions = List[(Stageable[_ <: Data],Any)]( val nonImmediateActions = List[(Stageable[_ <: BaseType],Any)](
LEGAL_INSTRUCTION -> True, LEGAL_INSTRUCTION -> True,
SRC1_CTRL -> Src1CtrlEnum.RS, SRC1_CTRL -> Src1CtrlEnum.RS,
SRC2_CTRL -> Src2CtrlEnum.RS, SRC2_CTRL -> Src2CtrlEnum.RS,

View File

@ -3,6 +3,7 @@
#include "verilated.h" #include "verilated.h"
#include "verilated_vcd_c.h" #include "verilated_vcd_c.h"
#include <stdio.h> #include <stdio.h>
#include <iostream>
#include <stdlib.h> #include <stdlib.h>
#include <stdint.h> #include <stdint.h>
@ -85,10 +86,12 @@ uint32_t regFileWriteRefArray[][2] = {
#define assertEq(x,ref) if(x != ref) {\ #define assertEq(x,ref) if(x != ref) {\
printf("\n*** %s is %d but should be %d ***\n\n",TEXTIFY(x),x,ref);\ printf("\n*** %s is %d but should be %d ***\n\n",TEXTIFY(x),x,ref);\
error = 1;\ error = 1; \
throw std::exception();\
} }
int main(int argc, char **argv, char **env) { int main(int argc, char **argv, char **env) {
Verilated::randReset(2);
int i; int i;
int clk; int clk;
int error = 0; int error = 0;
@ -105,58 +108,64 @@ int main(int argc, char **argv, char **env) {
// Reset // Reset
top->clk = 1; top->clk = 1;
top->reset = 1; top->reset = 0;
top->iCmd_ready = 1; top->iCmd_ready = 1;
top->dCmd_ready = 1; top->dCmd_ready = 1;
for (uint32_t i = 0; i < 16; i++) { top->eval();
tfp->dump(i); top->reset = 1;
top->eval(); top->eval();
} tfp->dump(0);
top->reset = 0; top->reset = 0;
top->eval();
// run simulation for 100 clock periods
for (i = 16; i < 600; i+=2) {
uint32_t iRsp_inst_next = top->iRsp_inst; try {
if (top->iCmd_valid) { // run simulation for 100 clock periods
assert((top->iCmd_payload_pc & 3) == 0); for (i = 16; i < 600; i+=2) {
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){ uint32_t iRsp_inst_next = top->iRsp_inst;
assertEq(top->VexRiscv->writeBack_RegFilePlugin_regFileWrite_payload_address, regFileWriteRefArray[regFileWriteRefIndex][0]); if (top->iCmd_valid) {
assertEq(top->VexRiscv->writeBack_RegFilePlugin_regFileWrite_payload_data, regFileWriteRefArray[regFileWriteRefIndex][1]); assertEq(top->iCmd_payload_pc & 3,0);
printf("%d\n",i); //printf("%d\n",top->iCmd_payload_pc);
uint8_t* ptr = memory + top->iCmd_payload_pc;
regFileWriteRefIndex++; iRsp_inst_next = (ptr[0] << 0) | (ptr[1] << 8) | (ptr[2] << 16) | (ptr[3] << 24);
if(regFileWriteRefIndex == sizeof(regFileWriteRefArray)/sizeof(regFileWriteRefArray[0])){
tfp->dump(i);
tfp->dump(i+1);
printf("SUCCESS\n");
break;
} }
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;
}
}
// 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);
} }
} catch (const std::exception& e) {
if(error) { std::cout << e.what();
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);
} }
if(error)
tfp->dump(i);
tfp->dump(i+1);
tfp->close(); tfp->close();
printf("done\n"); printf("done\n");
exit(0); exit(0);

View File

@ -2,7 +2,7 @@ run: compile
./obj_dir/VVexRiscv ./obj_dir/VVexRiscv
verilate: verilate:
verilator -cc ../../../../VexRiscv.v --trace -Wno-WIDTH --exe main.cpp verilator -cc ../../../../VexRiscv.v --gdbbt --trace -Wno-WIDTH --x-assign unique --exe main.cpp
compile: verilate compile: verilate
make -j -C obj_dir/ -f VVexRiscv.mk VVexRiscv make -j -C obj_dir/ -f VVexRiscv.mk VVexRiscv