package vexriscv import spinal.core._ import spinal.lib._ import scala.collection.mutable class Stageable[T <: Data](_dataType : => T) extends HardType[T](_dataType) with Nameable{ def dataType = apply() setWeakName(this.getClass.getSimpleName.replace("$","")) } class Stage() extends Area{ def outsideCondScope[T](that : => T) : T = { val body = Component.current.dslBody body.push() val swapContext = body.swap() val ret = that body.pop() swapContext.appendBack() ret } def input[T <: Data](key : Stageable[T]) : T = { inputs.getOrElseUpdate(key.asInstanceOf[Stageable[Data]],outsideCondScope{ val input,inputDefault = key() inputsDefault(key.asInstanceOf[Stageable[Data]]) = inputDefault input := inputDefault input.setPartialName(this, key.getName()) }).asInstanceOf[T] } def output[T <: Data](key : Stageable[T]) : T = { outputs.getOrElseUpdate(key.asInstanceOf[Stageable[Data]],outsideCondScope{ val output,outputDefault = key() outputsDefault(key.asInstanceOf[Stageable[Data]]) = outputDefault output := outputDefault output //.setPartialName(this,"output_" + key.getName()) }).asInstanceOf[T] } def insert[T <: Data](key : Stageable[T]) : T = inserts.getOrElseUpdate(key.asInstanceOf[Stageable[Data]],outsideCondScope(key())).asInstanceOf[T] //.setPartialName(this,key.getName()) // def apply[T <: Data](key : Stageable[T]) : T = ??? val arbitration = new Area{ val haltItself = False //user settable, stuck the instruction, should only be set by the instruction itself val haltByOther = False //When settable, stuck the instruction, should only be set by something else than the stucked instruction val removeIt = False //When settable, unschedule the instruction as if it was never executed (no side effect) val flushAll = False //When settable, unschedule instructions in the current stage and all prior ones val redoIt = False //Allow to notify that a given instruction in a pipeline is rescheduled val isValid = Bool //Inform if a instruction is in the current stage val isStuck = Bool //Inform if the instruction is stuck (haltItself || haltByOther) val isStuckByOthers = Bool //Inform if the instruction is stuck by sombody else def isRemoved = removeIt //Inform if the instruction is going to be unschedule the current cycle val isFlushed = Bool //Inform if the instruction is flushed (flushAll set in the current or subsequents stages) val isMoving = Bool //Inform if the instruction is going somewere else (next stage or unscheduled) val isFiring = Bool //Inform if the current instruction will go to the next stage the next cycle (isValid && !isStuck && !removeIt) } val inputs = mutable.HashMap[Stageable[Data],Data]() val outputs = mutable.HashMap[Stageable[Data],Data]() val signals = mutable.HashMap[Stageable[Data],Data]() val inserts = mutable.HashMap[Stageable[Data],Data]() val inputsDefault = mutable.HashMap[Stageable[Data],Data]() val outputsDefault = mutable.HashMap[Stageable[Data],Data]() def inputInit[T <: BaseType](stageable : Stageable[T],initValue : T) = Component.current.addPrePopTask(() => inputsDefault(stageable.asInstanceOf[Stageable[Data]]).asInstanceOf[T].getDrivingReg.init(initValue)) }