1
0

Merge branch 'master' into auto-plusargs

This commit is contained in:
Henry Cook 2018-02-06 18:38:44 -08:00 committed by GitHub
commit fe277cf6f0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
30 changed files with 236 additions and 166 deletions

View File

@ -14,7 +14,7 @@ $(generated_dir)/%.fir $(generated_dir)/%.d: $(FIRRTL_JAR) $(chisel_srcs) $(boot
%.v %.conf: %.fir $(FIRRTL_JAR)
mkdir -p $(dir $@)
$(FIRRTL) $(patsubst %,-i %,$(filter %.fir,$^)) -o $*.v -X verilog --infer-rw $(MODEL) --repl-seq-mem -c:$(MODEL):-o:$*.conf -faf $*.anno -ffaaf
$(FIRRTL) $(patsubst %,-i %,$(filter %.fir,$^)) -o $*.v -X verilog --infer-rw $(MODEL) --repl-seq-mem -c:$(MODEL):-o:$*.conf -faf $*.anno
$(generated_dir)/$(long_name).behav_srams.v : $(generated_dir)/$(long_name).conf $(VLSI_MEM_GEN)
cd $(generated_dir) && \

2
firrtl

@ -1 +1 @@
Subproject commit 19abcb04ad005a21319354550e87bfd428ec5597
Subproject commit 57025111d3bc872da726e31e3e9a1e4895593266

@ -1 +1 @@
Subproject commit 6909906e7e46e9abec601669a92a3af567531d5e
Subproject commit 45f5ae171a1950389f1b239b46a9e0d16ae0a6f4

Binary file not shown.

View File

@ -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)
}
}

View File

@ -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)
}
}

View File

@ -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)
}

View File

@ -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")
}
}

View File

@ -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)

View File

@ -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
}
}
}

View File

@ -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)

View File

@ -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)

View File

@ -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) = {

View File

@ -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 =>

View File

@ -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

View File

@ -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")

View File

@ -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

View File

@ -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,

View File

@ -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)
}

View File

@ -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)

View File

@ -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)) =>

View File

@ -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 {

View File

@ -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")

View File

@ -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))

View File

@ -14,7 +14,7 @@ $(generated_dir)/%.fir $(generated_dir)/%.d: $(FIRRTL_JAR) $(chisel_srcs) $(boot
$(generated_dir)/%.v $(generated_dir)/%.conf: $(generated_dir)/%.fir $(FIRRTL_JAR)
mkdir -p $(dir $@)
$(FIRRTL) -i $< -o $(generated_dir)/$*.v -X verilog --infer-rw $(MODEL) --repl-seq-mem -c:$(MODEL):-o:$(generated_dir)/$*.conf -faf $(generated_dir)/$*.anno -ffaaf
$(FIRRTL) -i $< -o $(generated_dir)/$*.v -X verilog --infer-rw $(MODEL) --repl-seq-mem -c:$(MODEL):-o:$(generated_dir)/$*.conf -faf $(generated_dir)/$*.anno
$(generated_dir)/$(long_name).behav_srams.v : $(generated_dir)/$(long_name).conf $(mem_gen)
cd $(generated_dir) && \

View File

@ -1,4 +1,5 @@
// See LICENSE.SiFive for license details.
//VCS coverage exclude_file
import "DPI-C" function int debug_tick
(

View File

@ -1,5 +1,5 @@
// See LICENSE.SiFive for license details.
//VCS coverage exclude_file
import "DPI-C" function int jtag_tick
(
output bit jtag_TCK,

View File

@ -1,5 +1,5 @@
// See LICENSE.SiFive for license details.
//VCS coverage exclude_file
`ifndef RESET_DELAY
`define RESET_DELAY 777.7
`endif

View File

@ -31,7 +31,7 @@
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
//VCS coverage exclude_file
`define CMD_RESET 0
`define CMD_TMS_SEQ 1
`define CMD_SCAN_CHAIN 2

View File

@ -1,5 +1,7 @@
// See LICENSE.SiFive for license details.
//VCS coverage exclude_file
// No default parameter values are intended, nor does IEEE 1800-2012 require them (clause A.2.4 param_assignment),
// but Incisive demands them. These default values should never be used.
module plusarg_reader #(parameter FORMAT="borked=%d", DEFAULT=0) (