Better decoding
This commit is contained in:
parent
e36c90af03
commit
df99a0d963
|
@ -6,7 +6,7 @@ import spinal.lib._
|
|||
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("$",""))
|
||||
}
|
||||
|
||||
|
|
|
@ -146,61 +146,103 @@ class VexRiscv(val config : VexRiscvConfig) extends Component with Pipeline{
|
|||
|
||||
|
||||
trait DecoderService{
|
||||
def add(key : MaskedLiteral,values : Seq[(Stageable[_ <: Data],Any)])
|
||||
def add(encoding :Seq[(MaskedLiteral,Seq[(Stageable[_ <: Data],Any)])])
|
||||
def addDefault(key : Stageable[_ <: Data], value : Any)
|
||||
def add(key : MaskedLiteral,values : Seq[(Stageable[_ <: BaseType],Any)])
|
||||
def add(encoding :Seq[(MaskedLiteral,Seq[(Stageable[_ <: BaseType],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 {
|
||||
override def add(encoding: Seq[(MaskedLiteral, Seq[(Stageable[_ <: Data], 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(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[_ <: BaseType], Any)]): Unit = {
|
||||
require(!encodings.contains(key))
|
||||
encodings(key) = values.map{case (a,b) => (a,b match{
|
||||
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))
|
||||
defaults(key) = value match{
|
||||
case e : SpinalEnumElement[_] => e()
|
||||
case e : Data => e
|
||||
case e : BaseType => e
|
||||
}
|
||||
}
|
||||
|
||||
val defaults = mutable.HashMap[Stageable[_ <: Data], Data]()
|
||||
val encodings = mutable.HashMap[MaskedLiteral,Seq[(Stageable[_ <: Data], Any)]]()
|
||||
val defaults = mutable.HashMap[Stageable[_ <: BaseType], BaseType]()
|
||||
val encodings = mutable.HashMap[MaskedLiteral,Seq[(Stageable[_ <: BaseType], BaseType)]]()
|
||||
|
||||
override def build(pipeline: VexRiscv): Unit = {
|
||||
import pipeline.decode._
|
||||
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]()
|
||||
|
||||
stageables.foreach(e => if(defaults.contains(e.asInstanceOf[Stageable[Data]]))
|
||||
insert(e.asInstanceOf[Stageable[Data]]) := defaults(e.asInstanceOf[Stageable[Data]])
|
||||
else
|
||||
insert(e).assignDontCare())
|
||||
//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(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 ={
|
||||
|
@ -231,7 +273,7 @@ class NoPredictionBranchPlugin extends Plugin[VexRiscv]{
|
|||
|
||||
val decoderService = pipeline.service(classOf[DecoderService])
|
||||
|
||||
val bActions = List[(Stageable[_ <: Data],Any)](
|
||||
val bActions = List[(Stageable[_ <: BaseType],Any)](
|
||||
LEGAL_INSTRUCTION -> True,
|
||||
SRC1_CTRL -> Src1CtrlEnum.RS,
|
||||
SRC2_CTRL -> Src2CtrlEnum.RS,
|
||||
|
@ -240,7 +282,7 @@ class NoPredictionBranchPlugin extends Plugin[VexRiscv]{
|
|||
SRC2_USE -> True
|
||||
)
|
||||
|
||||
val jActions = List[(Stageable[_ <: Data],Any)](
|
||||
val jActions = List[(Stageable[_ <: BaseType],Any)](
|
||||
LEGAL_INSTRUCTION -> True,
|
||||
SRC1_CTRL -> Src1CtrlEnum.FOUR,
|
||||
SRC2_CTRL -> Src2CtrlEnum.PC,
|
||||
|
@ -418,7 +460,7 @@ class DBusSimplePlugin extends Plugin[VexRiscv]{
|
|||
|
||||
val decoderService = pipeline.service(classOf[DecoderService])
|
||||
|
||||
val stdActions = List[(Stageable[_ <: Data],Any)](
|
||||
val stdActions = List[(Stageable[_ <: BaseType],Any)](
|
||||
LEGAL_INSTRUCTION -> True,
|
||||
SRC1_CTRL -> Src1CtrlEnum.RS,
|
||||
SRC_USE_SUB_LESS -> False,
|
||||
|
@ -675,7 +717,7 @@ class IntAluPlugin extends Plugin[VexRiscv]{
|
|||
import pipeline.config._
|
||||
import Riscv._
|
||||
|
||||
val immediateActions = List[(Stageable[_ <: Data],Any)](
|
||||
val immediateActions = List[(Stageable[_ <: BaseType],Any)](
|
||||
LEGAL_INSTRUCTION -> True,
|
||||
SRC1_CTRL -> Src1CtrlEnum.RS,
|
||||
SRC2_CTRL -> Src2CtrlEnum.IMI,
|
||||
|
@ -685,7 +727,7 @@ class IntAluPlugin extends Plugin[VexRiscv]{
|
|||
SRC1_USE -> True
|
||||
)
|
||||
|
||||
val nonImmediateActions = List[(Stageable[_ <: Data],Any)](
|
||||
val nonImmediateActions = List[(Stageable[_ <: BaseType],Any)](
|
||||
LEGAL_INSTRUCTION -> True,
|
||||
SRC1_CTRL -> Src1CtrlEnum.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,
|
||||
SRC1_CTRL -> Src1CtrlEnum.RS,
|
||||
SRC2_CTRL -> Src2CtrlEnum.IMI,
|
||||
|
@ -777,7 +819,7 @@ class FullBarrielShifterPlugin extends Plugin[VexRiscv]{
|
|||
BYPASSABLE_MEMORY_STAGE -> True
|
||||
)
|
||||
|
||||
val nonImmediateActions = List[(Stageable[_ <: Data],Any)](
|
||||
val nonImmediateActions = List[(Stageable[_ <: BaseType],Any)](
|
||||
LEGAL_INSTRUCTION -> True,
|
||||
SRC1_CTRL -> Src1CtrlEnum.RS,
|
||||
SRC2_CTRL -> Src2CtrlEnum.RS,
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
#include "verilated.h"
|
||||
#include "verilated_vcd_c.h"
|
||||
#include <stdio.h>
|
||||
#include <iostream>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
|
||||
|
@ -85,10 +86,12 @@ uint32_t regFileWriteRefArray[][2] = {
|
|||
|
||||
#define assertEq(x,ref) if(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) {
|
||||
Verilated::randReset(2);
|
||||
int i;
|
||||
int clk;
|
||||
int error = 0;
|
||||
|
@ -105,58 +108,64 @@ int main(int argc, char **argv, char **env) {
|
|||
|
||||
// Reset
|
||||
top->clk = 1;
|
||||
top->reset = 1;
|
||||
top->reset = 0;
|
||||
top->iCmd_ready = 1;
|
||||
top->dCmd_ready = 1;
|
||||
for (uint32_t i = 0; i < 16; i++) {
|
||||
tfp->dump(i);
|
||||
top->eval();
|
||||
}
|
||||
top->eval();
|
||||
top->reset = 1;
|
||||
top->eval();
|
||||
tfp->dump(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;
|
||||
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);
|
||||
}
|
||||
try {
|
||||
// run simulation for 100 clock periods
|
||||
for (i = 16; i < 600; i+=2) {
|
||||
|
||||
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;
|
||||
uint32_t iRsp_inst_next = top->iRsp_inst;
|
||||
if (top->iCmd_valid) {
|
||||
assertEq(top->iCmd_payload_pc & 3,0);
|
||||
//printf("%d\n",top->iCmd_payload_pc);
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 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);
|
||||
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) {
|
||||
std::cout << e.what();
|
||||
}
|
||||
|
||||
if(error)
|
||||
tfp->dump(i);
|
||||
tfp->dump(i+1);
|
||||
tfp->close();
|
||||
printf("done\n");
|
||||
exit(0);
|
||||
|
|
|
@ -2,7 +2,7 @@ run: compile
|
|||
./obj_dir/VVexRiscv
|
||||
|
||||
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
|
||||
make -j -C obj_dir/ -f VVexRiscv.mk VVexRiscv
|
||||
|
|
Loading…
Reference in New Issue