Merge branch 'master' into auto-plusargs
This commit is contained in:
		| @@ -23,18 +23,25 @@ abstract class View { | ||||
| } | ||||
|  | ||||
| abstract class Parameters extends View { | ||||
|   final def ++ (x: Parameters):                                       Parameters = new ChainParameters(this, x) | ||||
|   final def alter(f: (View, View, View) => PartialFunction[Any,Any]): Parameters = Parameters(f) ++ this | ||||
|   final def alterPartial(f: PartialFunction[Any,Any]):                Parameters = Parameters((_,_,_) => f) ++ this | ||||
|   final def ++ (x: Parameters): Parameters = | ||||
|     new ChainParameters(this, x) | ||||
|  | ||||
|   final def alter(f: (View, View, View) => PartialFunction[Any,Any]): Parameters = | ||||
|     Parameters(f) ++ this | ||||
|  | ||||
|   final def alterPartial(f: PartialFunction[Any,Any]): Parameters = | ||||
|     Parameters((_,_,_) => f) ++ this | ||||
|  | ||||
|   final def alterMap(m: Map[Any,Any]): Parameters = | ||||
|     new MapParameters(m) ++ this | ||||
|  | ||||
|   protected[config] def chain[T](site: View, tail: View, pname: Field[T]): Option[T] | ||||
|   protected[config] def find[T](pname: Field[T], site: View) = chain(site, new TerminalView, pname) | ||||
| } | ||||
|  | ||||
| object Parameters { | ||||
|   def empty:                                                    Parameters = new EmptyParameters | ||||
|   def empty: Parameters = new EmptyParameters | ||||
|   def apply(f: (View, View, View) => PartialFunction[Any,Any]): Parameters = new PartialParameters(f) | ||||
|   def root(p: Parameters) = p | ||||
| } | ||||
|  | ||||
| class Config(p: Parameters) extends Parameters { | ||||
| @@ -69,3 +76,10 @@ private class PartialParameters(f: (View, View, View) => PartialFunction[Any,Any | ||||
|     if (g.isDefinedAt(pname)) Some(g.apply(pname).asInstanceOf[T]) else tail.find(pname, site) | ||||
|   } | ||||
| } | ||||
|  | ||||
| private class MapParameters(map: Map[Any, Any]) extends Parameters { | ||||
|   protected[config] def chain[T](site: View, tail: View, pname: Field[T]) = { | ||||
|     val g = map.get(pname) | ||||
|     if (g.isDefined) Some(g.get.asInstanceOf[T]) else tail.find(pname, site) | ||||
|   } | ||||
| } | ||||
|   | ||||
| @@ -12,6 +12,8 @@ import freechips.rocketchip.tile.XLen | ||||
| import freechips.rocketchip.tilelink._ | ||||
| import freechips.rocketchip.interrupts._ | ||||
| import freechips.rocketchip.util._ | ||||
| import freechips.rocketchip.util.property._ | ||||
| import chisel3.internal.sourceinfo.SourceInfo | ||||
| import scala.math.min | ||||
|  | ||||
| class GatewayPLICIO extends Bundle { | ||||
| @@ -231,6 +233,25 @@ class TLPLIC(params: PLICParams)(implicit p: Parameters) extends LazyModule | ||||
|     pending(0) := false | ||||
|     for (e <- enables) | ||||
|       e(0) := false | ||||
|  | ||||
|     if (nDevices >= 2) { | ||||
|       val claimed = claimer(0) && maxDevs(0) > 0 | ||||
|       val completed = completer(0) | ||||
|       cover(claimed && RegEnable(claimed, false.B, claimed || completed), "TWO_CLAIMS", "two claims with no intervening complete") | ||||
|       cover(completed && RegEnable(completed, false.B, claimed || completed), "TWO_COMPLETES", "two completes with no intervening claim") | ||||
|  | ||||
|       val ep = enables(0).asUInt & pending.asUInt | ||||
|       val ep2 = RegNext(ep) | ||||
|       val diff = ep & ~ep2 | ||||
|       cover((diff & (diff - 1)) =/= 0, "TWO_INTS_PENDING", "two enabled interrupts became pending on same cycle") | ||||
|  | ||||
|       if (nPriorities > 0) | ||||
|         ccover(maxDevs(0) > (UInt(1) << priority(0).getWidth) && maxDevs(0) <= Cat(UInt(1), threshold(0)), | ||||
|                "THRESHOLD", "interrupt pending but less than threshold") | ||||
|     } | ||||
|  | ||||
|     def ccover(cond: Bool, label: String, desc: String)(implicit sourceInfo: SourceInfo) = | ||||
|       cover(cond, s"PLIC_$label", "Interrupts;;" + desc) | ||||
|   } | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -174,7 +174,6 @@ sealed trait LazyModuleImpLike extends BaseModule | ||||
|       mod.finishInstantiate() | ||||
|       mod.dangles | ||||
|     } | ||||
|     wrapper.instantiate() | ||||
|     val nodeDangles = wrapper.nodes.reverse.flatMap(_.instantiate()) | ||||
|     val allDangles = nodeDangles ++ childDangles | ||||
|     val pairing = SortedMap(allDangles.groupBy(_.source).toSeq:_*) | ||||
| @@ -189,6 +188,7 @@ sealed trait LazyModuleImpLike extends BaseModule | ||||
|       if (d.flipped) { d.data <> io } else { io <> d.data } | ||||
|       d.copy(data = io, name = wrapper.valName.getOrElse("anon") + "_" + d.name) | ||||
|     } | ||||
|     wrapper.instantiate() | ||||
|     (auto, dangles) | ||||
|   } | ||||
|  | ||||
|   | ||||
| @@ -4,6 +4,8 @@ package freechips.rocketchip.jtag | ||||
|  | ||||
| import Chisel._ | ||||
| import chisel3.{Input, Output} | ||||
| import chisel3.experimental.withReset | ||||
|  | ||||
| import freechips.rocketchip.config.{Parameters} | ||||
| import freechips.rocketchip.util.{AsyncResetRegVec} | ||||
| import freechips.rocketchip.util.property._ | ||||
| @@ -69,26 +71,18 @@ object JtagState { | ||||
|   * | ||||
|   * | ||||
|   */ | ||||
| class JtagStateMachine(implicit val p: Parameters) extends Module(override_reset=Some(false.B)) { | ||||
| class JtagStateMachine(implicit val p: Parameters) extends Module() { | ||||
|   class StateMachineIO extends Bundle { | ||||
|     val tms = Input(Bool()) | ||||
|     val currState = Output(JtagState.State.chiselType()) | ||||
|  | ||||
|     val jtag_reset = Input(Bool()) | ||||
|     val currState = Output(JtagState.State.chiselType) | ||||
|   } | ||||
|   val io = IO(new StateMachineIO) | ||||
|  | ||||
|   // val nextState = WireInit(JtagState.State.chiselType(), DontCare) | ||||
|   val nextState = Wire(JtagState.State.chiselType()) | ||||
|  | ||||
|   val currStateReg = Module (new AsyncResetRegVec(w = JtagState.State.width, | ||||
|     init = JtagState.State.toInt(JtagState.TestLogicReset))) | ||||
|  | ||||
|   currStateReg.clock := clock | ||||
|   currStateReg.reset := io.jtag_reset | ||||
|   currStateReg.io.en := true.B | ||||
|   currStateReg.io.d  := nextState | ||||
|  | ||||
|   val currState = currStateReg.io.q | ||||
|  | ||||
|   switch (currState) { | ||||
| @@ -148,7 +142,8 @@ class JtagStateMachine(implicit val p: Parameters) extends Module(override_reset | ||||
|   JtagState.State.all.foreach { s =>  | ||||
|     cover (currState === s.U && io.tms === true.B,  s"${s.toString}_tms_1", "JTAG; ${s.toString} with TMS = 1; State Transition from ${s.toString} with TMS = 1") | ||||
|     cover (currState === s.U && io.tms === false.B, s"${s.toString}_tms_0", "JTAG; ${s.toString} with TMS = 0; State Transition from ${s.toString} with TMS = 0") | ||||
|     cover (currState === s.U && io.jtag_reset === true.B, s"${s.toString}_reset", "JTAG; ${s.toString} with reset; JTAG Reset asserted during ${s.toString") | ||||
|    cover (currState === s.U && reset.toBool === true.B, s"${s.toString}_reset", "JTAG; ${s.toString} with reset; JTAG Reset asserted during ${s.toString") | ||||
|   | ||||
|   } | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -9,6 +9,8 @@ import scala.collection.SortedMap | ||||
| import Chisel._ | ||||
| import chisel3.core.{Input, Output} | ||||
| import chisel3.util._ | ||||
| import chisel3.experimental.withReset | ||||
|  | ||||
| import freechips.rocketchip.config.Parameters | ||||
|  | ||||
| /** JTAG signals, viewed from the master side | ||||
| @@ -71,22 +73,26 @@ class JtagTapController(irLength: Int, initialInstruction: BigInt)(implicit val | ||||
|  | ||||
|   val tdo = Wire(Bool())  // 4.4.1c TDI should appear here uninverted after shifting | ||||
|   val tdo_driven = Wire(Bool()) | ||||
|   io.jtag.TDO.data := NegativeEdgeLatch(clock, tdo, name = Some("tdoReg"))  // 4.5.1a TDO changes on falling edge of TCK, 6.1.2.1d driver active on first TCK falling edge in ShiftIR and ShiftDR states | ||||
|   io.jtag.TDO.driven := NegativeEdgeLatch(clock, tdo_driven, name = Some("tdoeReg")) | ||||
|   io.jtag.TDO.data := NegEdgeReg(clock, tdo, name = Some("tdoReg"))  // 4.5.1a TDO changes on falling edge of TCK, 6.1.2.1d driver active on first TCK falling edge in ShiftIR and ShiftDR states | ||||
|   io.jtag.TDO.driven := NegEdgeReg(clock, tdo_driven, name = Some("tdoeReg")) | ||||
|  | ||||
|   // | ||||
|   // JTAG state machine | ||||
|   // | ||||
|   val stateMachine = Module(new JtagStateMachine) | ||||
|   stateMachine.io.tms := io.jtag.TMS | ||||
|   val currState = stateMachine.io.currState | ||||
|   io.output.state := stateMachine.io.currState | ||||
|  | ||||
|   val currState = Wire(JtagState.State.chiselType) | ||||
|  | ||||
|   // At this point, the TRSTn should already have been | ||||
|   // combined with any POR, and it should also be | ||||
|   // synchronized to TCK. | ||||
|   require(!io.jtag.TRSTn.isDefined, "TRSTn should be absorbed into jtckPOReset outside of JtagTapController.") | ||||
|   stateMachine.io.jtag_reset := io.control.jtag_reset | ||||
|   withReset(io.control.jtag_reset) { | ||||
|     val stateMachine = Module(new JtagStateMachine) | ||||
|     stateMachine.suggestName("stateMachine") | ||||
|     stateMachine.io.tms := io.jtag.TMS | ||||
|     currState := stateMachine.io.currState | ||||
|     io.output.state := stateMachine.io.currState | ||||
|   } | ||||
|  | ||||
|   // | ||||
|   // Instruction Register | ||||
| @@ -105,7 +111,7 @@ class JtagTapController(irLength: Int, initialInstruction: BigInt)(implicit val | ||||
|   val updateInstruction = Wire(Bool()) | ||||
|  | ||||
|   val nextActiveInstruction = Wire(UInt(irLength.W)) | ||||
|   val activeInstruction = NegativeEdgeLatch(clock, nextActiveInstruction, updateInstruction, name = Some("irReg"))   // 7.2.1d active instruction output latches on TCK falling edge | ||||
|   val activeInstruction = NegEdgeReg(clock, nextActiveInstruction, updateInstruction, name = Some("irReg"))   // 7.2.1d active instruction output latches on TCK falling edge | ||||
|  | ||||
|   when (reset.toBool) { | ||||
|     nextActiveInstruction := initialInstruction.U(irLength.W) | ||||
|   | ||||
| @@ -2,9 +2,9 @@ | ||||
|  | ||||
| package freechips.rocketchip.jtag | ||||
|  | ||||
| //import chisel3._ | ||||
| import Chisel._ | ||||
| import chisel3.core.{Input, Output} | ||||
| import chisel3.experimental.withClock | ||||
|  | ||||
| /** Bundle representing a tristate pin. | ||||
|   */ | ||||
| @@ -13,40 +13,23 @@ class Tristate extends Bundle { | ||||
|   val driven = Bool()  // active high, pin is hi-Z when driven is low | ||||
| } | ||||
|  | ||||
| class NegativeEdgeLatch[T <: Data](clock: Clock, dataType: T) | ||||
|     extends Module(override_clock=Some(clock)) { | ||||
|   class IoClass extends Bundle { | ||||
|     val next = Input(dataType) | ||||
|     val enable = Input(Bool()) | ||||
|     val output = Output(dataType) | ||||
|   } | ||||
|   val io = IO(new IoClass) | ||||
|  | ||||
|   val reg = Reg(dataType) | ||||
|   when (io.enable) { | ||||
|     reg := io.next | ||||
|   } | ||||
|   io.output := reg | ||||
| } | ||||
|  | ||||
| /** Generates a register that updates on the falling edge of the input clock signal. | ||||
|   */ | ||||
| object NegativeEdgeLatch { | ||||
| object NegEdgeReg { | ||||
|   def apply[T <: Data](clock: Clock, next: T, enable: Bool=true.B, name: Option[String] = None): T = { | ||||
|     // TODO better init passing once in-module multiclock support improves | ||||
|     val latch_module = Module(new NegativeEdgeLatch((!clock.asUInt).asClock, next.cloneType)) | ||||
|     name.foreach(latch_module.suggestName(_)) | ||||
|     latch_module.io.next := next | ||||
|     latch_module.io.enable := enable | ||||
|     latch_module.io.output | ||||
|     // TODO pass in initial value as well | ||||
|     withClock((!clock.asUInt).asClock) { | ||||
|       val reg = RegEnable(next = next, enable = enable) | ||||
|       name.foreach{reg.suggestName(_)} | ||||
|       reg | ||||
|     } | ||||
|   } | ||||
| } | ||||
|  | ||||
| /** A module that counts transitions on the input clock line, used as a basic sanity check and | ||||
|   * debug indicator clock-crossing designs. | ||||
|   */ | ||||
| class ClockedCounter(modClock: Clock, counts: BigInt, init: Option[BigInt]) | ||||
|     extends Module(override_clock=Some(modClock)) { | ||||
| class ClockedCounter(counts: BigInt, init: Option[BigInt]) extends Module { | ||||
|   require(counts > 0, "really?") | ||||
|  | ||||
|   val width = log2Ceil(counts) | ||||
| @@ -65,19 +48,23 @@ class ClockedCounter(modClock: Clock, counts: BigInt, init: Option[BigInt]) | ||||
|   } .otherwise { | ||||
|     count := count + 1.U | ||||
|   } | ||||
|  | ||||
|   io.count := count | ||||
|  io.count := count | ||||
| } | ||||
|  | ||||
| /** Count transitions on the input bit by specifying it as a clock to a counter. | ||||
|   */ | ||||
| object ClockedCounter { | ||||
|   def apply (data: Bool, counts: BigInt, init: BigInt): UInt = { | ||||
|     val counter = Module(new ClockedCounter(data.asClock, counts, Some(init))) | ||||
|     counter.io.count | ||||
|     withClock(data.asClock) { | ||||
|       val counter = Module(new ClockedCounter(counts, Some(init))) | ||||
|       counter.io.count | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   def apply (data: Bool, counts: BigInt): UInt = { | ||||
|     val counter = Module(new ClockedCounter(data.asClock, counts, None)) | ||||
|     counter.io.count | ||||
|     withClock(data.asClock) { | ||||
|       val counter = Module(new ClockedCounter(counts, None)) | ||||
|       counter.io.count | ||||
|     } | ||||
|   } | ||||
| } | ||||
|   | ||||
| @@ -6,6 +6,8 @@ import Chisel._ | ||||
|  | ||||
| import freechips.rocketchip.diplomacy._ | ||||
| import freechips.rocketchip.util.{GenericParameterizedBundle, ReduceOthers} | ||||
| import freechips.rocketchip.util.property._ | ||||
| import chisel3.internal.sourceinfo.{SourceInfo, SourceLine} | ||||
|  | ||||
| // A bus agnostic register interface to a register-based device | ||||
|  | ||||
| @@ -30,7 +32,7 @@ class RegMapperOutput(params: RegMapperParams) extends GenericParameterizedBundl | ||||
| object RegMapper | ||||
| { | ||||
|   // Create a generic register-based device | ||||
|   def apply(bytes: Int, concurrency: Int, undefZero: Boolean, in: DecoupledIO[RegMapperInput], mapping: RegField.Map*) = { | ||||
|   def apply(bytes: Int, concurrency: Int, undefZero: Boolean, in: DecoupledIO[RegMapperInput], mapping: RegField.Map*)(implicit sourceInfo: SourceInfo) = { | ||||
|     val bytemap = mapping.toList | ||||
|     // Negative addresses are bad | ||||
|     bytemap.foreach { byte => require (byte._1 >= 0) } | ||||
| @@ -134,8 +136,19 @@ object RegMapper | ||||
|       val romask = backMask(high, low).orR() | ||||
|       val womask = backMask(high, low).andR() | ||||
|       val data = if (field.write.combinational) back.bits.data else front.bits.data | ||||
|       val (f_riready, f_rovalid, f_data) = field.read.fn(rivalid(i) && rimask, roready(i) && romask) | ||||
|       val (f_wiready, f_wovalid) = field.write.fn(wivalid(i) && wimask, woready(i) && womask, data(high, low)) | ||||
|       val f_rivalid = rivalid(i) && rimask | ||||
|       val f_roready = roready(i) && romask | ||||
|       val f_wivalid = wivalid(i) && wimask | ||||
|       val f_woready = woready(i) && womask | ||||
|       val (f_riready, f_rovalid, f_data) = field.read.fn(f_rivalid, f_roready) | ||||
|       val (f_wiready, f_wovalid) = field.write.fn(f_wivalid, f_woready, data(high, low)) | ||||
|  | ||||
|       // cover reads and writes to register | ||||
|       cover(f_rivalid && f_riready, field.name + "_Reg_read_start", field.description + " RegField Read Request Initiate") | ||||
|       cover(f_rovalid && f_roready, field.name + "_Reg_read_out", field.description + " RegField Read Request Complete") | ||||
|       cover(f_wivalid && f_wiready, field.name + "_Reg_write_start", field.description + " RegField Write Request Initiate") | ||||
|       cover(f_wovalid && f_woready, field.name + "_Reg_write_out", field.description + " RegField Write Request Complete") | ||||
|  | ||||
|       def litOR(x: Bool, y: Bool) = if (x.isLit && x.litValue == 1) Bool(true) else x || y | ||||
|       // Add this field to the ready-valid signals for the register | ||||
|       rifire(reg) = (rivalid(i), litOR(f_riready, !rimask)) +: rifire(reg) | ||||
|   | ||||
| @@ -33,8 +33,8 @@ object ALU | ||||
|  | ||||
|   def FN_MUL    = FN_ADD | ||||
|   def FN_MULH   = FN_SL | ||||
|   def FN_MULHSU = FN_SLT | ||||
|   def FN_MULHU  = FN_SLTU | ||||
|   def FN_MULHSU = FN_SEQ | ||||
|   def FN_MULHU  = FN_SNE | ||||
|  | ||||
|   def isMulFN(fn: UInt, cmp: UInt) = fn(1,0) === cmp(1,0) | ||||
|   def isSub(cmd: UInt) = cmd(3) | ||||
|   | ||||
| @@ -196,7 +196,7 @@ class CSRFileIO(implicit p: Parameters) extends CoreBundle | ||||
|   val retire = UInt(INPUT, log2Up(1+retireWidth)) | ||||
|   val cause = UInt(INPUT, xLen) | ||||
|   val pc = UInt(INPUT, vaddrBitsExtended) | ||||
|   val badaddr = UInt(INPUT, vaddrBitsExtended) | ||||
|   val tval = UInt(INPUT, vaddrBitsExtended) | ||||
|   val time = UInt(OUTPUT, xLen) | ||||
|   val fcsr_rm = Bits(OUTPUT, FPConstants.RM_SZ) | ||||
|   val fcsr_flags = Valid(Bits(width = FPConstants.FLAGS_SZ)).flip | ||||
| @@ -364,7 +364,7 @@ class CSRFile(perfEventSets: EventSets = new EventSets(Seq()))(implicit p: Param | ||||
|  | ||||
|   val debug_csrs = LinkedHashMap[Int,Bits]( | ||||
|     CSRs.dcsr -> reg_dcsr.asUInt, | ||||
|     CSRs.dpc -> reg_dpc.asUInt, | ||||
|     CSRs.dpc -> reg_dpc.sextTo(xLen), | ||||
|     CSRs.dscratch -> reg_dscratch.asUInt) | ||||
|  | ||||
|   val fp_csrs = LinkedHashMap[Int,Bits]( | ||||
| @@ -526,13 +526,7 @@ class CSRFile(perfEventSets: EventSets = new EventSets(Seq()))(implicit p: Param | ||||
|   assert(!io.singleStep || io.retire <= UInt(1)) | ||||
|   assert(!reg_singleStepped || io.retire === UInt(0)) | ||||
|  | ||||
|   val epc = ~(~io.pc | (coreInstBytes-1)) | ||||
|   val write_badaddr = exception && cause.isOneOf(Causes.illegal_instruction, Causes.breakpoint, | ||||
|     Causes.misaligned_load, Causes.misaligned_store, | ||||
|     Causes.load_access, Causes.store_access, Causes.fetch_access, | ||||
|     Causes.load_page_fault, Causes.store_page_fault, Causes.fetch_page_fault) | ||||
|   val badaddr_value = Mux(write_badaddr, io.badaddr, 0.U) | ||||
|  | ||||
|   val epc = formEPC(io.pc) | ||||
|   val noCause :: mCause :: hCause :: sCause :: uCause :: Nil = Enum(5) | ||||
|   val xcause_dest = Wire(init = noCause) | ||||
|  | ||||
| @@ -546,19 +540,19 @@ class CSRFile(perfEventSets: EventSets = new EventSets(Seq()))(implicit p: Param | ||||
|         new_prv := PRV.M | ||||
|       } | ||||
|     }.elsewhen (delegate) { | ||||
|       reg_sepc := formEPC(epc) | ||||
|       reg_sepc := epc | ||||
|       reg_scause := cause | ||||
|       xcause_dest := sCause | ||||
|       reg_sbadaddr := badaddr_value | ||||
|       reg_sbadaddr := io.tval | ||||
|       reg_mstatus.spie := reg_mstatus.sie | ||||
|       reg_mstatus.spp := reg_mstatus.prv | ||||
|       reg_mstatus.sie := false | ||||
|       new_prv := PRV.S | ||||
|     }.otherwise { | ||||
|       reg_mepc := formEPC(epc) | ||||
|       reg_mepc := epc | ||||
|       reg_mcause := cause | ||||
|       xcause_dest := mCause | ||||
|       reg_mbadaddr := badaddr_value | ||||
|       reg_mbadaddr := io.tval | ||||
|       reg_mstatus.mpie := reg_mstatus.mie | ||||
|       reg_mstatus.mpp := trimPrivilege(reg_mstatus.prv) | ||||
|       reg_mstatus.mie := false | ||||
| @@ -566,20 +560,22 @@ class CSRFile(perfEventSets: EventSets = new EventSets(Seq()))(implicit p: Param | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   for ( | ||||
|     (cover_reg, cover_reg_label) <- List( | ||||
|       (mCause, "MCAUSE"), | ||||
|       (sCause, "SCAUSE") | ||||
|     ); | ||||
|     (cover_cause_code, cover_cause_label) <- List( | ||||
|       (Causes.user_ecall, "ECALL_USER"), | ||||
|       (Causes.supervisor_ecall, "ECALL_SUPERVISOR"), | ||||
|       (Causes.hypervisor_ecall, "ECALL_HYPERVISOR"), | ||||
|       (Causes.machine_ecall, "ECALL_MACHINE") | ||||
|     ) | ||||
|   ) { | ||||
|     cover((xcause_dest === cover_reg) && (cause === UInt(cover_cause_code)), | ||||
|           s"${cover_reg_label}_${cover_cause_label}") | ||||
|   for (i <- 0 until supported_interrupts.getWidth) { | ||||
|     val en = exception && (supported_interrupts & (BigInt(1) << i).U) =/= 0 && cause === (BigInt(1) << (xLen - 1)).U + i | ||||
|     val delegable = (delegable_interrupts & (BigInt(1) << i).U) =/= 0 | ||||
|     cover(en, s"INTERRUPT_M_$i") | ||||
|     cover(en && delegable && delegate, s"INTERRUPT_S_$i") | ||||
|   } | ||||
|   for (i <- 0 until xLen) { | ||||
|     val supported_exceptions = 0x87e | | ||||
|       (if (usingCompressed && !coreParams.misaWritable) 0 else 1) | | ||||
|       (if (usingUser) 0x100 else 0) | | ||||
|       (if (usingVM) 0xb200 else 0) | ||||
|     if (((supported_exceptions >> i) & 1) != 0) { | ||||
|       val en = exception && cause === i | ||||
|       cover(en, s"EXCEPTION_M_$i") | ||||
|       cover(en && delegate, s"EXCEPTION_S_$i") | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   when (insn_ret) { | ||||
| @@ -607,6 +603,11 @@ class CSRFile(perfEventSets: EventSets = new EventSets(Seq()))(implicit p: Param | ||||
|  | ||||
|   io.rw.rdata := Mux1H(for ((k, v) <- read_mapping) yield decoded_addr(k) -> v) | ||||
|  | ||||
|   // cover access to register | ||||
|   read_mapping.foreach( {case (k, v) => { | ||||
|     cover(io.rw.cmd.isOneOf(CSR.W, CSR.S, CSR.C, CSR.R) && io.rw.addr===k, "CSR_access_"+k.toString, "Cover Accessing Core CSR field") | ||||
|   }}) | ||||
|  | ||||
|   io.fcsr_rm := reg_frm | ||||
|   when (io.fcsr_flags.valid) { | ||||
|     reg_fflags := reg_fflags | io.fcsr_flags.bits | ||||
| @@ -685,7 +686,7 @@ class CSRFile(perfEventSets: EventSets = new EventSets(Seq()))(implicit p: Param | ||||
|         if (usingUser) reg_dcsr.ebreaku := new_dcsr.ebreaku | ||||
|         if (usingUser) reg_dcsr.prv := trimPrivilege(new_dcsr.prv) | ||||
|       } | ||||
|       when (decoded_addr(CSRs.dpc))      { reg_dpc := ~(~wdata | (coreInstBytes-1)) } | ||||
|       when (decoded_addr(CSRs.dpc))      { reg_dpc := formEPC(wdata) } | ||||
|       when (decoded_addr(CSRs.dscratch)) { reg_dscratch := wdata } | ||||
|     } | ||||
|     if (usingVM) { | ||||
| @@ -801,7 +802,7 @@ class CSRFile(perfEventSets: EventSets = new EventSets(Seq()))(implicit p: Param | ||||
|     t.priv := Cat(reg_debug, reg_mstatus.prv) | ||||
|     t.cause := cause | ||||
|     t.interrupt := cause(xLen-1) | ||||
|     t.tval := badaddr_value | ||||
|     t.tval := io.tval | ||||
|   } | ||||
|  | ||||
|   def chooseInterrupt(masksIn: Seq[UInt]): (Bool, UInt) = { | ||||
|   | ||||
| @@ -186,6 +186,7 @@ class HellaCacheModule(outer: HellaCache) extends LazyModuleImp(outer) | ||||
|   val (tl_out, _) = outer.node.out(0) | ||||
|   val io = IO(new HellaCacheBundle(outer)) | ||||
|   dontTouch(io.cpu.resp) // Users like to monitor these fields even if the core ignores some signals | ||||
|   dontTouch(io.cpu.s1_data) | ||||
|  | ||||
|   private val fifoManagers = edge.manager.managers.filter(TLFIFOFixer.allUncacheable) | ||||
|   fifoManagers.foreach { m => | ||||
|   | ||||
| @@ -39,30 +39,35 @@ case class MulDivParams( | ||||
| class MulDiv(cfg: MulDivParams, width: Int, nXpr: Int = 32) extends Module { | ||||
|   val io = new MultiplierIO(width, log2Up(nXpr)) | ||||
|   val w = io.req.bits.in1.getWidth | ||||
|   val mulw = (w + cfg.mulUnroll - 1) / cfg.mulUnroll * cfg.mulUnroll | ||||
|   val fastMulW = w/2 > cfg.mulUnroll && w % (2*cfg.mulUnroll) == 0 | ||||
|   val mulw = if (cfg.mulUnroll == 0) w else (w + cfg.mulUnroll - 1) / cfg.mulUnroll * cfg.mulUnroll | ||||
|   val fastMulW = if (cfg.mulUnroll == 0) false else w/2 > cfg.mulUnroll && w % (2*cfg.mulUnroll) == 0 | ||||
|   | ||||
|   val s_ready :: s_neg_inputs :: s_mul :: s_div :: s_dummy :: s_neg_output :: s_done_mul :: s_done_div :: Nil = Enum(UInt(), 8) | ||||
|   val state = Reg(init=s_ready) | ||||
|   | ||||
|   val req = Reg(io.req.bits) | ||||
|   val count = Reg(UInt(width = log2Ceil((w/cfg.divUnroll + 1) max (w/cfg.mulUnroll)))) | ||||
|   val count = Reg(UInt(width = log2Ceil( | ||||
|     ((cfg.divUnroll != 0).option(w/cfg.divUnroll + 1).toSeq ++ | ||||
|      (cfg.mulUnroll != 0).option(mulw/cfg.mulUnroll)).reduce(_ max _)))) | ||||
|   val neg_out = Reg(Bool()) | ||||
|   val isHi = Reg(Bool()) | ||||
|   val resHi = Reg(Bool()) | ||||
|   val divisor = Reg(Bits(width = w+1)) // div only needs w bits | ||||
|   val remainder = Reg(Bits(width = 2*mulw+2)) // div only needs 2*w+1 bits | ||||
|  | ||||
|   val mulDecode = List( | ||||
|     FN_MUL    -> List(Y, N, X, X), | ||||
|     FN_MULH   -> List(Y, Y, Y, Y), | ||||
|     FN_MULHU  -> List(Y, Y, N, N), | ||||
|     FN_MULHSU -> List(Y, Y, Y, N)) | ||||
|   val divDecode = List( | ||||
|     FN_DIV    -> List(N, N, Y, Y), | ||||
|     FN_REM    -> List(N, Y, Y, Y), | ||||
|     FN_DIVU   -> List(N, N, N, N), | ||||
|     FN_REMU   -> List(N, Y, N, N)) | ||||
|   val cmdMul :: cmdHi :: lhsSigned :: rhsSigned :: Nil = | ||||
|     DecodeLogic(io.req.bits.fn, List(X, X, X, X), List( | ||||
|                    FN_DIV    -> List(N, N, Y, Y), | ||||
|                    FN_REM    -> List(N, Y, Y, Y), | ||||
|                    FN_DIVU   -> List(N, N, N, N), | ||||
|                    FN_REMU   -> List(N, Y, N, N), | ||||
|                    FN_MUL    -> List(Y, N, X, X), | ||||
|                    FN_MULH   -> List(Y, Y, Y, Y), | ||||
|                    FN_MULHU  -> List(Y, Y, N, N), | ||||
|                    FN_MULHSU -> List(Y, Y, Y, N))).map(_ toBool) | ||||
|     DecodeLogic(io.req.bits.fn, List(X, X, X, X), | ||||
|       (if (cfg.divUnroll != 0) divDecode else Nil) ++ (if (cfg.mulUnroll != 0) mulDecode else Nil)).map(_.toBool) | ||||
|  | ||||
|   require(w == 32 || w == 64) | ||||
|   def halfWidth(req: MultiplierReq) = Bool(w > 32) && req.dw === DW_32 | ||||
| @@ -79,7 +84,7 @@ class MulDiv(cfg: MulDivParams, width: Int, nXpr: Int = 32) extends Module { | ||||
|   val result = Mux(resHi, remainder(2*w, w+1), remainder(w-1, 0)) | ||||
|   val negated_remainder = -result | ||||
|  | ||||
|   when (state === s_neg_inputs) { | ||||
|   if (cfg.divUnroll != 0) when (state === s_neg_inputs) { | ||||
|     when (remainder(w-1)) { | ||||
|       remainder := negated_remainder | ||||
|     } | ||||
| @@ -88,12 +93,12 @@ class MulDiv(cfg: MulDivParams, width: Int, nXpr: Int = 32) extends Module { | ||||
|     } | ||||
|     state := s_div | ||||
|   } | ||||
|   when (state === s_neg_output) { | ||||
|   if (cfg.divUnroll != 0) when (state === s_neg_output) { | ||||
|     remainder := negated_remainder | ||||
|     state := s_done_div | ||||
|     resHi := false | ||||
|   } | ||||
|   when (state === s_mul) { | ||||
|   if (cfg.mulUnroll != 0) when (state === s_mul) { | ||||
|     val mulReg = Cat(remainder(2*mulw+1,w+1),remainder(w-1,0)) | ||||
|     val mplierSign = remainder(w) | ||||
|     val mplier = mulReg(mulw-1,0) | ||||
| @@ -116,7 +121,7 @@ class MulDiv(cfg: MulDivParams, width: Int, nXpr: Int = 32) extends Module { | ||||
|       resHi := isHi | ||||
|     } | ||||
|   } | ||||
|   when (state === s_div) { | ||||
|   if (cfg.divUnroll != 0) when (state === s_div) { | ||||
|     val unrolls = ((0 until cfg.divUnroll) scanLeft remainder) { case (rem, i) => | ||||
|       // the special case for iteration 0 is to save HW, not for correctness | ||||
|       val difference = if (i == 0) subtractor else rem(2*w,w) - divisor(w-1,0) | ||||
| @@ -156,7 +161,7 @@ class MulDiv(cfg: MulDivParams, width: Int, nXpr: Int = 32) extends Module { | ||||
|     state := Mux(cmdMul, s_mul, Mux(lhs_sign || rhs_sign, s_neg_inputs, s_div)) | ||||
|     isHi := cmdHi | ||||
|     resHi := false | ||||
|     count := Mux[UInt](Bool(fastMulW) && cmdMul && halfWidth(io.req.bits), w/cfg.mulUnroll/2, 0) | ||||
|     count := (if (fastMulW) Mux[UInt](cmdMul && halfWidth(io.req.bits), w/cfg.mulUnroll/2, 0) else 0) | ||||
|     neg_out := Mux(cmdHi, lhs_sign, lhs_sign =/= rhs_sign) | ||||
|     divisor := Cat(rhs_sign, rhs_in) | ||||
|     remainder := lhs_in | ||||
|   | ||||
| @@ -279,6 +279,15 @@ class PTW(n: Int)(implicit edge: TLEdgeOut, p: Parameters) extends CoreModule()( | ||||
|     count := pgLevels-1 | ||||
|   } | ||||
|  | ||||
|   for (i <- 0 until pgLevels) { | ||||
|     val leaf = io.mem.resp.valid && !traverse && count === i | ||||
|     ccover(leaf && pte.v && !invalid_paddr, s"L$i", s"successful page-table access, level $i") | ||||
|     ccover(leaf && pte.v && invalid_paddr, s"L${i}_BAD_PPN_MSB", s"PPN too large, level $i") | ||||
|     ccover(leaf && !io.mem.resp.bits.data(0), s"L${i}_INVALID_PTE", s"page not present, level $i") | ||||
|     if (i != pgLevels-1) | ||||
|       ccover(leaf && !pte.v && io.mem.resp.bits.data(0), s"L${i}_BAD_PPN_LSB", s"PPN LSBs not zero, level $i") | ||||
|   } | ||||
|   ccover(io.mem.resp.valid && count === pgLevels-1 && pte.table(), s"TOO_DEEP", s"page table too deep") | ||||
|   ccover(io.mem.s2_nack, "NACK", "D$ nacked page-table access") | ||||
|   ccover(state === s_wait2 && io.mem.s2_xcpt.ae.ld, "AE", "access exception while walking page table") | ||||
|  | ||||
|   | ||||
| @@ -545,7 +545,11 @@ class Rocket(implicit p: Parameters) extends CoreModule()(p) | ||||
|   csr.io.fcsr_flags := io.fpu.fcsr_flags | ||||
|   csr.io.rocc_interrupt := io.rocc.interrupt | ||||
|   csr.io.pc := wb_reg_pc | ||||
|   csr.io.badaddr := encodeVirtualAddress(wb_reg_wdata, wb_reg_wdata) | ||||
|   val tval_valid = wb_xcpt && wb_cause.isOneOf(Causes.illegal_instruction, Causes.breakpoint, | ||||
|     Causes.misaligned_load, Causes.misaligned_store, | ||||
|     Causes.load_access, Causes.store_access, Causes.fetch_access, | ||||
|     Causes.load_page_fault, Causes.store_page_fault, Causes.fetch_page_fault) | ||||
|   csr.io.tval := Mux(tval_valid, encodeVirtualAddress(wb_reg_wdata, wb_reg_wdata), 0.U) | ||||
|   io.ptw.ptbr := csr.io.ptbr | ||||
|   io.ptw.status := csr.io.status | ||||
|   io.ptw.pmp := csr.io.pmp | ||||
|   | ||||
| @@ -40,12 +40,12 @@ object TLBPageLookup | ||||
|     val amoSizes = TransferSizes(4, xLen/8) | ||||
|  | ||||
|     val permissions = managers.map { m => | ||||
|       require (!m.supportsGet        || m.supportsGet       .contains(allSizes),  s"MemoryMap region ${m.name} only supports ${m.supportsGet} Get, but must support ${allSizes}") | ||||
|       require (!m.supportsPutFull    || m.supportsPutFull   .contains(allSizes),  s"MemoryMap region ${m.name} only supports ${m.supportsPutFull} PutFull, but must support ${allSizes}") | ||||
|       require (!m.supportsAcquireB   || m.supportsAcquireB  .contains(xferSizes), s"MemoryMap region ${m.name} only supports ${m.supportsAcquireB} AcquireB, but must support ${xferSizes}") | ||||
|       require (!m.supportsAcquireT   || m.supportsAcquireT  .contains(xferSizes), s"MemoryMap region ${m.name} only supports ${m.supportsAcquireT} AcquireT, but must support ${xferSizes}") | ||||
|       require (!m.supportsLogical    || m.supportsLogical   .contains(amoSizes),  s"MemoryMap region ${m.name} only supports ${m.supportsLogical} Logical, but must support ${amoSizes}") | ||||
|       require (!m.supportsArithmetic || m.supportsArithmetic.contains(amoSizes),  s"MemoryMap region ${m.name} only supports ${m.supportsArithmetic} Arithmetic, but must support ${amoSizes}") | ||||
|       require (!m.supportsGet        || m.supportsGet       .contains(allSizes),  s"Memory region '${m.name}' at ${m.address} only supports ${m.supportsGet} Get, but must support ${allSizes}") | ||||
|       require (!m.supportsPutFull    || m.supportsPutFull   .contains(allSizes),  s"Memory region '${m.name}' at ${m.address} only supports ${m.supportsPutFull} PutFull, but must support ${allSizes}") | ||||
|       require (!m.supportsAcquireB   || m.supportsAcquireB  .contains(xferSizes), s"Memory region '${m.name}' at ${m.address} only supports ${m.supportsAcquireB} AcquireB, but must support ${xferSizes}") | ||||
|       require (!m.supportsAcquireT   || m.supportsAcquireT  .contains(xferSizes), s"Memory region '${m.name}' at ${m.address} only supports ${m.supportsAcquireT} AcquireT, but must support ${xferSizes}") | ||||
|       require (!m.supportsLogical    || m.supportsLogical   .contains(amoSizes),  s"Memory region '${m.name}' at ${m.address} only supports ${m.supportsLogical} Logical, but must support ${amoSizes}") | ||||
|       require (!m.supportsArithmetic || m.supportsArithmetic.contains(amoSizes),  s"Memory region '${m.name}' at ${m.address} only supports ${m.supportsArithmetic} Arithmetic, but must support ${amoSizes}") | ||||
|  | ||||
|       (m.address, TLBFixedPermissions( | ||||
|         e = Seq(RegionType.PUT_EFFECTS, RegionType.GET_EFFECTS) contains m.regionType, | ||||
|   | ||||
| @@ -10,6 +10,8 @@ import freechips.rocketchip.config.Parameters | ||||
| import freechips.rocketchip.rocket._ | ||||
| import freechips.rocketchip.rocket.Instructions._ | ||||
| import freechips.rocketchip.util._ | ||||
| import freechips.rocketchip.util.property._ | ||||
| import chisel3.internal.sourceinfo.SourceInfo | ||||
|  | ||||
| case class FPUParams( | ||||
|   divSqrt: Boolean = true, | ||||
| @@ -768,6 +770,7 @@ class FPU(cfg: FPUParams)(implicit p: Parameters) extends FPUModule()(p) { | ||||
|   val wbInfo = Reg(Vec(maxLatency-1, new WBInfo)) | ||||
|   val mem_wen = mem_reg_valid && (mem_ctrl.fma || mem_ctrl.fastpipe || mem_ctrl.fromint) | ||||
|   val write_port_busy = RegEnable(mem_wen && (memLatencyMask & latencyMask(ex_ctrl, 1)).orR || (wen & latencyMask(ex_ctrl, 0)).orR, req_valid) | ||||
|   ccover(mem_reg_valid && write_port_busy, "WB_STRUCTURAL", "structural hazard on writeback") | ||||
|  | ||||
|   for (i <- 0 until maxLatency-2) { | ||||
|     when (wen(i+1)) { wbInfo(i) := wbInfo(i+1) } | ||||
| @@ -820,11 +823,15 @@ class FPU(cfg: FPUParams)(implicit p: Parameters) extends FPUModule()(p) { | ||||
|   io.sboard_set := wb_reg_valid && !wb_cp_valid && Reg(next=useScoreboard(_._1.cond(mem_ctrl)) || mem_ctrl.div || mem_ctrl.sqrt) | ||||
|   io.sboard_clr := !wb_cp_valid && (divSqrt_wen || (wen(0) && useScoreboard(x => wbInfo(0).pipeid === UInt(x._2)))) | ||||
|   io.sboard_clra := waddr | ||||
|   ccover(io.sboard_clr && load_wb, "DUAL_WRITEBACK", "load and FMA writeback on same cycle") | ||||
|   // we don't currently support round-max-magnitude (rm=4) | ||||
|   io.illegal_rm := io.inst(14,12).isOneOf(5, 6) || io.inst(14,12) === 7 && io.fcsr_rm >= 5 | ||||
|  | ||||
|   if (cfg.divSqrt) { | ||||
|     val divSqrt_killed = Reg(Bool()) | ||||
|     ccover(divSqrt_inFlight && divSqrt_killed, "DIV_KILLED", "divide killed after issued to divider") | ||||
|     ccover(divSqrt_inFlight && mem_reg_valid && (mem_ctrl.div || mem_ctrl.sqrt), "DIV_BUSY", "divider structural hazard") | ||||
|     ccover(mem_reg_valid && divSqrt_write_port_busy, "DIV_WB_STRUCTURAL", "structural hazard on division writeback") | ||||
|  | ||||
|     for (t <- floatTypes) { | ||||
|       val tag = !mem_ctrl.singleOut // TODO typeTag | ||||
| @@ -873,4 +880,7 @@ class FPU(cfg: FPUParams)(implicit p: Parameters) extends FPUModule()(p) { | ||||
|     } | ||||
|     req | ||||
|   } | ||||
|  | ||||
|   def ccover(cond: Bool, label: String, desc: String)(implicit sourceInfo: SourceInfo) = | ||||
|     cover(cond, s"FPU_$label", "Core;;" + desc) | ||||
| } | ||||
|   | ||||
| @@ -76,7 +76,7 @@ object TLPermissions | ||||
|   def BtoN = UInt(2, cWidth) | ||||
|   def isShrink(x: UInt) = x <= BtoN | ||||
|  | ||||
|   // Report types (ProbeAck) | ||||
|   // Report types (ProbeAck, Release) | ||||
|   def TtoT = UInt(3, cWidth) | ||||
|   def BtoB = UInt(4, cWidth) | ||||
|   def NtoN = UInt(5, cWidth) | ||||
|   | ||||
| @@ -18,8 +18,8 @@ class TLSourceShrinker(maxInFlight: Int)(implicit p: Parameters) extends LazyMod | ||||
|     sourceId = IdRange(0, maxInFlight)) | ||||
|   val node = TLAdapterNode( | ||||
|     // We erase all client information since we crush the source Ids | ||||
|     clientFn  = { _ => TLClientPortParameters(clients = Seq(client)) }, | ||||
|     managerFn = { mp => mp.copy(managers = mp.managers.map(_.copy(fifoId = None)))  }) | ||||
|     clientFn  = { cp => TLClientPortParameters(clients = Seq(client.copy(requestFifo = cp.clients.exists(_.requestFifo)))) }, | ||||
|     managerFn = { mp => mp.copy(managers = mp.managers.map(m => m.copy(fifoId = if (maxInFlight==1) Some(0) else m.fifoId)))  }) | ||||
|  | ||||
|   lazy val module = new LazyModuleImp(this) { | ||||
|     (node.in zip node.out) foreach { case ((in, edgeIn), (out, edgeOut)) => | ||||
|   | ||||
| @@ -29,25 +29,25 @@ case class ParsedInputNames( | ||||
|   * canonical ways of building various JVM elaboration-time structures. | ||||
|   */ | ||||
| trait HasGeneratorUtilities { | ||||
|   def getConfig(names: ParsedInputNames): Config = { | ||||
|     new Config(names.fullConfigClasses.foldRight(Parameters.empty) { case (currentName, config) => | ||||
|   def getConfig(fullConfigClassNames: Seq[String]): Config = { | ||||
|     new Config(fullConfigClassNames.foldRight(Parameters.empty) { case (currentName, config) => | ||||
|       val currentConfig = try { | ||||
|         Class.forName(currentName).newInstance.asInstanceOf[Config] | ||||
|       } catch { | ||||
|         case e: java.lang.ClassNotFoundException => | ||||
|           throwException(s"""Unable to find part "$currentName" from "${names.configs}", did you misspell it?""", e) | ||||
|           throwException(s"""Unable to find part "$currentName" from "$fullConfigClassNames", did you misspell it?""", e) | ||||
|       } | ||||
|       currentConfig ++ config | ||||
|     }) | ||||
|   } | ||||
|  | ||||
|   def getParameters(names: ParsedInputNames): Parameters = getParameters(getConfig(names)) | ||||
|   def getParameters(names: Seq[String]): Parameters = getParameters(getConfig(names)) | ||||
|  | ||||
|   def getParameters(config: Config): Parameters = Parameters.root(config.toInstance) | ||||
|   def getParameters(config: Config): Parameters = config.toInstance | ||||
|  | ||||
|   def elaborate(names: ParsedInputNames, params: Parameters): Circuit = { | ||||
|   def elaborate(fullTopModuleClassName: String, params: Parameters): Circuit = { | ||||
|     val gen = () => | ||||
|       Class.forName(names.fullTopModuleClass) | ||||
|       Class.forName(fullTopModuleClassName) | ||||
|         .getConstructor(classOf[Parameters]) | ||||
|         .newInstance(params) | ||||
|         .asInstanceOf[RawModule] | ||||
| @@ -69,17 +69,8 @@ trait HasGeneratorUtilities { | ||||
|     } | ||||
|     res.toString | ||||
|   } | ||||
|  | ||||
|   def writeOutputFile(targetDir: String, fname: String, contents: String): File = { | ||||
|     val f = new File(targetDir, fname) | ||||
|     val fw = new FileWriter(f) | ||||
|     fw.write(contents) | ||||
|     fw.close | ||||
|     f | ||||
|   } | ||||
| } | ||||
|  | ||||
|  | ||||
| /** Standardized command line interface for Scala entry point */ | ||||
| trait GeneratorApp extends App with HasGeneratorUtilities { | ||||
|   lazy val names: ParsedInputNames = { | ||||
| @@ -95,11 +86,10 @@ trait GeneratorApp extends App with HasGeneratorUtilities { | ||||
|   } | ||||
|  | ||||
|   // Canonical ways of building various JVM elaboration-time structures | ||||
|   lazy val td = names.targetDir | ||||
|   lazy val config = getConfig(names) | ||||
|   lazy val world = config.toInstance | ||||
|   lazy val params = Parameters.root(world) | ||||
|   lazy val circuit = elaborate(names, params) | ||||
|   lazy val td: String = names.targetDir | ||||
|   lazy val config: Config = getConfig(names.fullConfigClasses) | ||||
|   lazy val params: Parameters = config.toInstance | ||||
|   lazy val circuit: Circuit = elaborate(names.fullTopModuleClass, params) | ||||
|  | ||||
|   val longName: String // Exhaustive name used to interface with external build tool targets | ||||
|  | ||||
| @@ -137,6 +127,14 @@ trait GeneratorApp extends App with HasGeneratorUtilities { | ||||
|       writeOutputFile(td, s"$longName.$extension", contents ()) | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   def writeOutputFile(targetDir: String, fname: String, contents: String): File = { | ||||
|     val f = new File(targetDir, fname) | ||||
|     val fw = new FileWriter(f) | ||||
|     fw.write(contents) | ||||
|     fw.close | ||||
|     f | ||||
|   } | ||||
| } | ||||
|  | ||||
| object ElaborationArtefacts { | ||||
|   | ||||
| @@ -5,10 +5,6 @@ package freechips.rocketchip.util.property | ||||
| import Chisel._ | ||||
| import chisel3.internal.sourceinfo.{SourceInfo, SourceLine} | ||||
| import chisel3.util.{ReadyValidIO} | ||||
| import freechips.rocketchip.config.{Field, Parameters} | ||||
|  | ||||
| case object PropertyLibrary extends Field[BasePropertyLibrary](new DefaultPropertyLibrary) | ||||
|  | ||||
|  | ||||
| sealed abstract class PropertyType(name: String) { | ||||
|   override def toString: String = name | ||||
| @@ -20,7 +16,7 @@ object PropertyType { | ||||
|   object Cover extends PropertyType("Cover") | ||||
| } | ||||
|  | ||||
| trait BasePropertyParameters {  | ||||
| trait BasePropertyParameters { | ||||
|   val pType: PropertyType | ||||
|   val cond: Bool | ||||
|   val label: String | ||||
| @@ -133,24 +129,30 @@ class CrossProperty(cond: Seq[Seq[CoverBoolean]], exclude: Seq[Seq[String]], mes | ||||
|  | ||||
| } | ||||
|  | ||||
| // The implementation using a setable global is bad, but removes dependence on Parameters | ||||
| // This change was made in anticipation of a proper cover library | ||||
| object cover { | ||||
|   def apply(cond: Bool)(implicit sourceInfo: SourceInfo, p: Parameters): Unit = { | ||||
|     p(PropertyLibrary).generateProperty(CoverPropertyParameters(cond)) | ||||
|   private var propLib: BasePropertyLibrary = new DefaultPropertyLibrary | ||||
|   def setPropLib(lib: BasePropertyLibrary): Unit = this.synchronized { | ||||
|     propLib = lib | ||||
|   } | ||||
|   def apply(cond: Bool, label: String)(implicit sourceInfo: SourceInfo, p: Parameters): Unit = { | ||||
|     p(PropertyLibrary).generateProperty(CoverPropertyParameters(cond, label)) | ||||
|   def apply(cond: Bool)(implicit sourceInfo: SourceInfo): Unit = { | ||||
|     propLib.generateProperty(CoverPropertyParameters(cond)) | ||||
|   } | ||||
|   def apply(cond: Bool, label: String, message: String)(implicit sourceInfo: SourceInfo, p: Parameters): Unit = { | ||||
|     p(PropertyLibrary).generateProperty(CoverPropertyParameters(cond, label, message)) | ||||
|   def apply(cond: Bool, label: String)(implicit sourceInfo: SourceInfo): Unit = { | ||||
|     propLib.generateProperty(CoverPropertyParameters(cond, label)) | ||||
|   } | ||||
|   def apply(prop: BaseProperty)(implicit sourceInfo: SourceInfo, p: Parameters): Unit = { | ||||
|   def apply(cond: Bool, label: String, message: String)(implicit sourceInfo: SourceInfo): Unit = { | ||||
|     propLib.generateProperty(CoverPropertyParameters(cond, label, message)) | ||||
|   } | ||||
|   def apply(prop: BaseProperty)(implicit sourceInfo: SourceInfo): Unit = { | ||||
|     prop.generateProperties().foreach( (pp: BasePropertyParameters) => { | ||||
|       if (pp.pType == PropertyType.Cover) { | ||||
|         p(PropertyLibrary).generateProperty(CoverPropertyParameters(pp.cond, pp.label, pp.message)) | ||||
|         propLib.generateProperty(CoverPropertyParameters(pp.cond, pp.label, pp.message)) | ||||
|       } | ||||
|     }) | ||||
|   } | ||||
|   def apply[T <: Data](rv: ReadyValidIO[T], label: String, message: String)(implicit sourceInfo: SourceInfo, p: Parameters): Unit = { | ||||
|   def apply[T <: Data](rv: ReadyValidIO[T], label: String, message: String)(implicit sourceInfo: SourceInfo): Unit = { | ||||
|     apply( rv.valid &&  rv.ready, label + "_FIRE",  message + ": valid and ready") | ||||
|     apply( rv.valid && !rv.ready, label + "_STALL", message + ": valid and not ready") | ||||
|     apply(!rv.valid &&  rv.ready, label + "_IDLE",  message + ": not valid and ready") | ||||
|   | ||||
| @@ -3,6 +3,7 @@ | ||||
| package freechips.rocketchip.util | ||||
|  | ||||
| import Chisel._ | ||||
| import chisel3.experimental.{withClockAndReset} | ||||
|  | ||||
| /** Reset: asynchronous assert, | ||||
|   *  synchronous de-assert | ||||
| @@ -28,12 +29,12 @@ object ResetCatchAndSync { | ||||
|   def apply(clk: Clock, rst: Bool, sync: Int = 3, name: Option[String] = None, | ||||
|     psd: Option[PSDTestMode] = None): Bool = { | ||||
|  | ||||
|     val catcher = Module (new ResetCatchAndSync(sync)) | ||||
|     if (name.isDefined) {catcher.suggestName(name.get)} | ||||
|     catcher.clock := clk | ||||
|     catcher.reset := rst | ||||
|     catcher.io.psd <> psd.getOrElse(Wire(new PSDTestMode()).fromBits(UInt(0))) | ||||
|     catcher.io.sync_reset | ||||
|     withClockAndReset(clk, rst) { | ||||
|       val catcher = Module (new ResetCatchAndSync(sync)) | ||||
|       if (name.isDefined) {catcher.suggestName(name.get)} | ||||
|       catcher.io.psd <> psd.getOrElse(Wire(new PSDTestMode()).fromBits(UInt(0))) | ||||
|       catcher.io.sync_reset | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   def apply(clk: Clock, rst: Bool, sync: Int, name: String): Bool = apply(clk, rst, sync, Some(name)) | ||||
|   | ||||
		Reference in New Issue
	
	Block a user