【问题标题】:How is this syntax explained in chisel?这个语法在凿子中是如何解释的?
【发布时间】:2019-12-17 13:26:35
【问题描述】:

我正在学习凿子和火箭芯片。我最近在 Rocket/RocketCore.scala 文件中发现了一个不可读的语法。

val perfEvents = new EventSets(Seq(
new EventSet((mask, hits) => Mux(mask(0), wb_xcpt, wb_valid && pipelineIDToWB((mask & hits).orR)), Seq(
  ("exception", () => false.B),
  ("load", () => id_ctrl.mem && id_ctrl.mem_cmd === M_XRD && !id_ctrl.fp),
  ("store", () => id_ctrl.mem && id_ctrl.mem_cmd === M_XWR && !id_ctrl.fp),
  ("amo", () => Bool(usingAtomics) && id_ctrl.mem && (isAMO(id_ctrl.mem_cmd) || id_ctrl.mem_cmd.isOneOf(M_XLR, M_XSC))),
  ("system", () => id_ctrl.csr =/= CSR.N),
  ("arith", () => id_ctrl.wxd && !(id_ctrl.jal || id_ctrl.jalr || id_ctrl.mem || id_ctrl.fp || id_ctrl.mul || id_ctrl.div || id_ctrl.csr =/= CSR.N)),
  ("branch", () => id_ctrl.branch),
  ("jal", () => id_ctrl.jal),
  ("jalr", () => id_ctrl.jalr))
  ++ (if (!usingMulDiv) Seq() else Seq(
    ("mul", () => if (pipelinedMul) id_ctrl.mul else id_ctrl.div && (id_ctrl.alu_fn & ALU.FN_DIV) =/= ALU.FN_DIV),
    ("div", () => if (pipelinedMul) id_ctrl.div else id_ctrl.div && (id_ctrl.alu_fn & ALU.FN_DIV) === ALU.FN_DIV)))
  ++ (if (!usingFPU) Seq() else Seq(
    ("fp load", () => id_ctrl.fp && io.fpu.dec.ldst && io.fpu.dec.wen),
    ("fp store", () => id_ctrl.fp && io.fpu.dec.ldst && !io.fpu.dec.wen),
    ("fp add", () => id_ctrl.fp && io.fpu.dec.fma && io.fpu.dec.swap23),
    ("fp mul", () => id_ctrl.fp && io.fpu.dec.fma && !io.fpu.dec.swap23 && !io.fpu.dec.ren3),
    ("fp mul-add", () => id_ctrl.fp && io.fpu.dec.fma && io.fpu.dec.ren3),
    ("fp div/sqrt", () => id_ctrl.fp && (io.fpu.dec.div || io.fpu.dec.sqrt)),
    ("fp other", () => id_ctrl.fp && !(io.fpu.dec.ldst || io.fpu.dec.fma || io.fpu.dec.div || io.fpu.dec.sqrt))))),
new EventSet((mask, hits) => (mask & hits).orR, Seq(
  ("load-use interlock", () => id_ex_hazard && ex_ctrl.mem || id_mem_hazard && mem_ctrl.mem || id_wb_hazard && wb_ctrl.mem),
  ("long-latency interlock", () => id_sboard_hazard),
  ("csr interlock", () => id_ex_hazard && ex_ctrl.csr =/= CSR.N || id_mem_hazard && mem_ctrl.csr =/= CSR.N || id_wb_hazard && wb_ctrl.csr =/= CSR.N),
  ("I$ blocked", () => icache_blocked),
  ("D$ blocked", () => id_ctrl.mem && dcache_blocked),
  ("branch misprediction", () => take_pc_mem && mem_direction_misprediction),
  ("control-flow target misprediction", () => take_pc_mem && mem_misprediction && mem_cfi && !mem_direction_misprediction && !icache_blocked),
  ("flush", () => wb_reg_flush_pipe),
  ("replay", () => replay_wb))
  ++ (if (!usingMulDiv) Seq() else Seq(
    ("mul/div interlock", () => id_ex_hazard && (ex_ctrl.mul || ex_ctrl.div) || id_mem_hazard && (mem_ctrl.mul || mem_ctrl.div) || id_wb_hazard && wb_ctrl.div)))
  ++ (if (!usingFPU) Seq() else Seq(
    ("fp interlock", () => id_ex_hazard && ex_ctrl.fp || id_mem_hazard && mem_ctrl.fp || id_wb_hazard && wb_ctrl.fp || id_ctrl.fp && id_stall_fpu)))),
new EventSet((mask, hits) => (mask & hits).orR, Seq(
  ("I$ miss", () => io.imem.perf.acquire),
  ("D$ miss", () => io.dmem.perf.acquire),
  ("D$ release", () => io.dmem.perf.release),
  ("ITLB miss", () => io.imem.perf.tlbMiss),
  ("DTLB miss", () => io.dmem.perf.tlbMiss),
  ("L2 TLB miss", () => io.ptw.perf.l2miss)))))

在使用EventSet类时,没有找到mask和hits的定义。

【问题讨论】:

    标签: scala chisel rocket-chip


    【解决方案1】:

    这是一段相当吓人的代码。打破它

    • perfEvents 被分配为 EventSets 的一个实例
    • EventSets 需要单个参数
      • class EventSets(val eventSets: Seq[EventSet])
      • 所以您会看到 SeqEventSet 开始创建。
    • EventSet 需要两个参数
      • class EventSet(gate: (UInt, UInt) => Bool, events: Seq[(String, () => Bool)])
      • 首先:两个UInts 的函数返回一个Bool
      • 第二个:Seq 的 2 个 String 元组和一个返回 Bool 的无参数函数
      • 因此您会看到正在定义的这些元组的长序列。
      • 注意:(String, () => Bool()) 的顺序需要根据usingMulDiv 等配置参数而有所不同
        • 因此,您会多次看到构造 ++ (if (..
        • 这使用if 有条件地将元组的不同子序列添加到它正在构造的EventSet 参数。

    我希望这会有所帮助。这是一大堆东西,可能会变得丑陋而简短,或者更清晰,而且非常冗长。通过格式化程序运行它可能会有所帮助。这里有一点。

    val perfEvents = new EventSets(
      Seq(
        new EventSet(
          (mask, hits) => Mux(wb_xcpt, mask(0), wb_valid && pipelineIDToWB((mask & hits).orR)),
          Seq(
            ("exception", () => false.B),
            ("load", () => id_ctrl.mem && id_ctrl.mem_cmd === M_XRD && !id_ctrl.fp),
            ("store", () => id_ctrl.mem && id_ctrl.mem_cmd === M_XWR && !id_ctrl.fp),
            ("amo",
             () =>
               Bool(usingAtomics) && id_ctrl.mem && (isAMO(id_ctrl.mem_cmd) || id_ctrl.mem_cmd.isOneOf(M_XLR, M_XSC))),
            ("system", () => id_ctrl.csr =/= CSR.N),
            ("arith",
             () =>
               id_ctrl.wxd && !(id_ctrl.jal || id_ctrl.jalr || id_ctrl.mem || id_ctrl.fp || id_ctrl.mul || id_ctrl.div || id_ctrl.csr =/= CSR.N)),
            ("branch", () => id_ctrl.branch),
            ("jal", () => id_ctrl.jal),
            ("jalr", () => id_ctrl.jalr)
          )
            ++ (if (!usingMulDiv) Seq()
                else
                  Seq(
    

    【讨论】:

    • 非常感谢您的解释
    • @wubingrui 考虑接受一个答案,以便其他人知道该问题已得到解答,或者如果您认为该问题尚未得到解答,请解释原因。
    【解决方案2】:

    maskhits 只是传递给EventSet 构造函数的lambda 的参数,(mask, hits) => ... 部分它们的定义(或声明,如果您愿意)。如果您查看EventSet source,您会看到 lambda 被称为gate,并且仅在此方法中使用:

    def check(mask: UInt) = gate(mask, hits)
    

    所以mask 将是checkhits 的参数来自

    def hits = events.map(_._2()).asUInt
    

    在这种情况下,对于第一个 EventSet,您会得到类似

    Seq(
      false.B,
      id_ctrl.mem && id_ctrl.mem_cmd === M_XRD && !id_ctrl.fp,
      ...
    ).asUInt
    

    【讨论】:

    • 非常感谢您的解释
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-09-01
    • 2017-03-12
    • 2013-03-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多