diff --git a/csrc/emulator.cc b/csrc/emulator.cc index cd2f6de6..2c8bea71 100644 --- a/csrc/emulator.cc +++ b/csrc/emulator.cc @@ -155,7 +155,7 @@ done_processing: srand48(random_seed); Verilated::randReset(2); - VTestHarness *tile = new VTestHarness; + TEST_HARNESS *tile = new TEST_HARNESS; #if VM_TRACE Verilated::traceEverOn(true); // Verilator must compute traced signals diff --git a/emulator/Makefrag-verilator b/emulator/Makefrag-verilator index 05ba9ed8..4e8ed1a6 100644 --- a/emulator/Makefrag-verilator +++ b/emulator/Makefrag-verilator @@ -1,5 +1,5 @@ #-------------------------------------------------------------------- -# Verilator Generation +# Verilator Generation #-------------------------------------------------------------------- firrtl = $(generated_dir)/$(long_name).fir firrtl_debug = $(generated_dir_debug)/$(long_name).fir @@ -57,7 +57,7 @@ VERILATOR_FLAGS := --top-module $(MODEL) \ --output-split 20000 \ -Wno-STMTDLY --x-assign unique \ -I$(base_dir)/vsrc \ - -O3 -CFLAGS "$(CXXFLAGS) -DVERILATOR -include $(base_dir)/csrc/verilator.h" + -O3 -CFLAGS "$(CXXFLAGS) -DVERILATOR -DTEST_HARNESS=V$(MODEL) -include $(base_dir)/csrc/verilator.h" cppfiles = $(addprefix $(base_dir)/csrc/, $(addsuffix .cc, $(CXXSRCS))) headers = $(wildcard $(base_dir)/csrc/*.h) diff --git a/firrtl b/firrtl index 2376ff98..bda2bd36 160000 --- a/firrtl +++ b/firrtl @@ -1 +1 @@ -Subproject commit 2376ff9849beafaf02b657b461c15a36d7b38fd4 +Subproject commit bda2bd363fbe66de9425bba12d96f5f9816a43ce diff --git a/riscv-tools b/riscv-tools index af8f5ee2..4dbb81b3 160000 --- a/riscv-tools +++ b/riscv-tools @@ -1 +1 @@ -Subproject commit af8f5ee2fc951a4a0b030e4a8d82fc4b1a1571e2 +Subproject commit 4dbb81b31698ebaa6a3d548ae628a3c716c5df72 diff --git a/src/main/scala/coreplex/CoreplexNetwork.scala b/src/main/scala/coreplex/CoreplexNetwork.scala index 3ee9a279..5368d2cf 100644 --- a/src/main/scala/coreplex/CoreplexNetwork.scala +++ b/src/main/scala/coreplex/CoreplexNetwork.scala @@ -66,7 +66,7 @@ trait CoreplexNetwork extends HasCoreplexParameters { Description("soc", Map( "#address-cells" -> width, "#size-cells" -> width, - "compatible" -> (p(DTSModel) +: p(DTSCompat)).map(s => ResourceString(s + "-soc")), + "compatible" -> ((p(DTSModel) +: p(DTSCompat)).map(s => ResourceString(s + "-soc")) :+ ResourceString("simple-bus")), "ranges" -> Nil)) } } diff --git a/src/main/scala/coreplex/RocketTiles.scala b/src/main/scala/coreplex/RocketTiles.scala index 4990c6d3..3622d3da 100644 --- a/src/main/scala/coreplex/RocketTiles.scala +++ b/src/main/scala/coreplex/RocketTiles.scala @@ -8,6 +8,7 @@ import diplomacy._ import rocket._ import tile._ import uncore.tilelink2._ +import util._ sealed trait ClockCrossing case object Synchronous extends ClockCrossing @@ -21,12 +22,17 @@ trait HasRocketTiles extends CoreplexRISCVPlatform { val module: HasRocketTilesModule private val crossing = p(RocketCrossing) - private val configs = p(RocketTilesKey) + val tileParams = p(RocketTilesKey) - // TODO: hack to fix deduplication; see PR https://github.com/ucb-bar/berkeley-hardfloat/pull/14 - hardfloat.consts + // Handle interrupts to be routed directly into each tile + val localIntNodes = tileParams map { t => + (t.core.nLocalInterrupts > 0).option(IntInputNode()) + } - val rocketWires: Seq[HasRocketTilesBundle => Unit] = configs.zipWithIndex.map { case (c, i) => + // Make a function for each tile that will wire it to coreplex devices and crossbars, + // according to the specified type of clock crossing. + val wiringTuple = localIntNodes.zip(tileParams).zipWithIndex + val rocketWires: Seq[HasRocketTilesBundle => Unit] = wiringTuple.map { case ((lip, c), i) => val pWithExtra = p.alterPartial { case TileKey => c case BuildRoCC => c.rocc @@ -34,10 +40,11 @@ trait HasRocketTiles extends CoreplexRISCVPlatform { } val intBar = LazyModule(new IntXbar) - intBar.intnode := debug.intnode // Debug Interrupt - intBar.intnode := clint.intnode // msip+mtip - intBar.intnode := plic.intnode // meip + intBar.intnode := debug.intnode // debug + intBar.intnode := clint.intnode // msip+mtip + intBar.intnode := plic.intnode // meip if (c.core.useVM) intBar.intnode := plic.intnode // seip + lip.foreach { intBar.intnode := _ } // lip crossing match { case Synchronous => { @@ -97,6 +104,7 @@ trait HasRocketTiles extends CoreplexRISCVPlatform { trait HasRocketTilesBundle extends CoreplexRISCVPlatformBundle { val outer: HasRocketTiles + val local_interrupts = HeterogeneousBag(outer.localIntNodes.flatten.map(_.bundleIn)) val tcrs = Vec(p(RocketTilesKey).size, new Bundle { val clock = Clock(INPUT) val reset = Bool(INPUT) diff --git a/src/main/scala/rocket/CSR.scala b/src/main/scala/rocket/CSR.scala index 28ac7831..ce7ac3a2 100644 --- a/src/main/scala/rocket/CSR.scala +++ b/src/main/scala/rocket/CSR.scala @@ -140,6 +140,8 @@ object CSR val firstHPM = 3 val nCtr = 32 val nHPM = nCtr - firstHPM + + val maxPMPs = 16 } class PerfCounterIO(implicit p: Parameters) extends CoreBundle @@ -418,10 +420,14 @@ class CSRFile(perfEventSets: EventSets = new EventSets(Seq()))(implicit p: Param val pmpCfgPerCSR = xLen / new PMPConfig().getWidth def pmpCfgIndex(i: Int) = (xLen / 32) * (i / pmpCfgPerCSR) - for (i <- 0 until reg_pmp.size by pmpCfgPerCSR) - read_mapping += (CSRs.pmpcfg0 + pmpCfgIndex(i)) -> reg_pmp.map(_.cfg).slice(i, i + pmpCfgPerCSR).asUInt - for ((pmp, i) <- reg_pmp zipWithIndex) - read_mapping += (CSRs.pmpaddr0 + i) -> pmp.addr + if (reg_pmp.nonEmpty) { + require(reg_pmp.size <= CSR.maxPMPs) + val read_pmp = reg_pmp.padTo(CSR.maxPMPs, 0.U.asTypeOf(new PMP)) + for (i <- 0 until read_pmp.size by pmpCfgPerCSR) + read_mapping += (CSRs.pmpcfg0 + pmpCfgIndex(i)) -> read_pmp.map(_.cfg).slice(i, i + pmpCfgPerCSR).asUInt + for ((pmp, i) <- read_pmp zipWithIndex) + read_mapping += (CSRs.pmpaddr0 + i) -> pmp.addr + } for (i <- 0 until nCustomMrwCsrs) { val addr = 0xff0 + i @@ -687,7 +693,7 @@ class CSRFile(perfEventSets: EventSets = new EventSets(Seq()))(implicit p: Param } if (reg_pmp.nonEmpty) for (((pmp, next), i) <- (reg_pmp zip (reg_pmp.tail :+ reg_pmp.last)) zipWithIndex) { require(xLen % pmp.cfg.getWidth == 0) - when (decoded_addr(CSRs.pmpcfg0 + pmpCfgIndex(i)) && !pmp.locked) { + when (decoded_addr(CSRs.pmpcfg0 + pmpCfgIndex(i)) && !pmp.cfgLocked) { pmp.cfg := new PMPConfig().fromBits(wdata >> ((i * pmp.cfg.getWidth) % xLen)) } when (decoded_addr(CSRs.pmpaddr0 + i) && !pmp.addrLocked(next)) { @@ -735,10 +741,11 @@ class CSRFile(perfEventSets: EventSets = new EventSets(Seq()))(implicit p: Param } for (bp <- reg_bp drop nBreakpoints) bp := new BP().fromBits(0) - if (reg_pmp.nonEmpty) { - for (pmp <- reg_pmp) { - if (!usingUser) pmp.cfg.m := true - when (reset) { pmp.cfg.p := 0 } + for (pmp <- reg_pmp) { + pmp.cfg.res := 0 + when (reset) { + pmp.cfg.a := 0 + pmp.cfg.l := 0 } } diff --git a/src/main/scala/rocket/DCache.scala b/src/main/scala/rocket/DCache.scala index a5f4516b..f476a486 100644 --- a/src/main/scala/rocket/DCache.scala +++ b/src/main/scala/rocket/DCache.scala @@ -180,6 +180,12 @@ class DCacheModule(outer: DCache) extends HellaCacheModule(outer) { io.cpu.s2_nack := s2_valid && !s2_valid_hit && !(s2_valid_uncached && tl_out.a.ready && !uncachedInFlight.asUInt.andR) when (io.cpu.s2_nack || (s2_valid_hit && s2_update_meta)) { s1_nack := true } + val s3_valid = Reg(next = s2_valid, init=Bool(false)) + val s3_uncached = Reg(next = s2_uncached, init=Bool(false)) + when (s2_valid_cached_miss) { + assert( !(s3_valid && s3_uncached) ) + } + // exceptions val s1_storegen = new StoreGen(s1_req.typ, s1_req.addr, UInt(0), wordBytes) val no_xcpt = Bool(usingDataScratchpad) && s1_req.phys /* slave port */ && s1_hit_state.isValid() diff --git a/src/main/scala/rocket/PMP.scala b/src/main/scala/rocket/PMP.scala index f8987849..fb19755f 100644 --- a/src/main/scala/rocket/PMP.scala +++ b/src/main/scala/rocket/PMP.scala @@ -9,9 +9,9 @@ import tile._ import util._ class PMPConfig extends Bundle { - val p = UInt(width = 2) + val l = Bool() + val res = UInt(width = 2) val a = UInt(width = 2) - val m = Bool() val x = Bool() val w = Bool() val r = Bool() @@ -32,8 +32,10 @@ class PMPReg(implicit p: Parameters) extends CoreBundle()(p) { val cfg = new PMPConfig val addr = UInt(width = paddrBits - PMP.lgAlign) - def locked = cfg.p(1) - def addrLocked(next: PMPReg) = locked || next.locked && next.cfg.a(1) + def napot = cfg.a(1) + def torNotNAPOT = cfg.a(0) + def cfgLocked = cfg.l + def addrLocked(next: PMPReg) = cfgLocked || next.cfgLocked && next.cfg.a(1) } class PMP(implicit p: Parameters) extends PMPReg { @@ -99,7 +101,7 @@ class PMP(implicit p: Parameters) extends PMPReg { // returns whether this PMP completely contains, or contains none of, a page def homogeneous(x: UInt, pgLevel: UInt, prev: PMP): Bool = - !cfg.p(0) || Mux(cfg.a(1), rangeHomogeneous(x, pgLevel, prev), pow2Homogeneous(x, pgLevel)) + Mux(napot, pow2Homogeneous(x, pgLevel), !torNotNAPOT || rangeHomogeneous(x, pgLevel, prev)) // returns whether this matching PMP fully contains the access def aligned(x: UInt, lgSize: UInt, lgMaxSize: Int, prev: PMP): Bool = if (lgMaxSize <= lgAlign) true.B else { @@ -108,12 +110,12 @@ class PMP(implicit p: Parameters) extends PMPReg { val straddlesUpperBound = ((x >> lgMaxSize) ^ (comparand >> lgMaxSize)) === 0 && (comparand(lgMaxSize-1, 0) & (x(lgMaxSize-1, 0) | lsbMask)) =/= 0 val rangeAligned = !(straddlesLowerBound || straddlesUpperBound) val pow2Aligned = (lsbMask & ~mask(lgMaxSize-1, 0)) === 0 - Mux(cfg.a(1), rangeAligned, pow2Aligned) + Mux(napot, pow2Aligned, rangeAligned) } // returns whether this PMP matches at least one byte of the access def hit(x: UInt, lgSize: UInt, lgMaxSize: Int, prev: PMP): Bool = - cfg.p(0) && Mux(cfg.a(1), rangeMatch(x, lgSize, lgMaxSize, prev), pow2Match(x, lgSize, lgMaxSize)) + Mux(napot, pow2Match(x, lgSize, lgMaxSize), torNotNAPOT && rangeMatch(x, lgSize, lgMaxSize, prev)) } class PMPHomogeneityChecker(pmps: Seq[PMP])(implicit p: Parameters) { @@ -144,7 +146,7 @@ class PMPChecker(lgMaxSize: Int)(implicit p: Parameters) extends CoreModule()(p) val res = (pmp0 /: (io.pmp zip (pmp0 +: io.pmp)).reverse) { case (prev, (pmp, prevPMP)) => val hit = pmp.hit(io.addr, io.size, lgMaxSize, prevPMP) - val ignore = default && !pmp.cfg.m + val ignore = default && !pmp.cfg.l val aligned = pmp.aligned(io.addr, io.size, lgMaxSize, prevPMP) val cur = Wire(init = pmp) cur.cfg.r := (aligned && pmp.cfg.r) || ignore diff --git a/src/main/scala/rocket/PTW.scala b/src/main/scala/rocket/PTW.scala index edeef24b..25b89c6d 100644 --- a/src/main/scala/rocket/PTW.scala +++ b/src/main/scala/rocket/PTW.scala @@ -79,6 +79,7 @@ class PTW(n: Int)(implicit edge: TLEdgeOut, p: Parameters) extends CoreModule()( val s1_kill = Reg(next = Bool(false)) val resp_valid = Reg(next = Vec.fill(io.requestor.size)(Bool(false))) val ae = Reg(next = io.mem.xcpt.ae.ld) + val resp_ae = Reg(Bool()) val r_req = Reg(new PTWReq) val r_req_dest = Reg(Bits()) @@ -99,7 +100,6 @@ class PTW(n: Int)(implicit edge: TLEdgeOut, p: Parameters) extends CoreModule()( } val traverse = pte.table() && !invalid_paddr && count < pgLevels-1 val pte_addr = Cat(r_pte.ppn, vpn_idx) << log2Ceil(xLen/8) - val resp_ae = Reg(next = ae || invalid_paddr) when (arb.io.out.fire()) { r_req := arb.io.out.bits diff --git a/src/main/scala/rocket/TLB.scala b/src/main/scala/rocket/TLB.scala index de3a90d1..1ad05b67 100644 --- a/src/main/scala/rocket/TLB.scala +++ b/src/main/scala/rocket/TLB.scala @@ -61,6 +61,7 @@ class TLB(lgMaxSize: Int, nEntries: Int)(implicit edge: TLEdgeOut, p: Parameters val level = UInt(width = log2Ceil(pgLevels)) val u = Bool() val g = Bool() + val ae = Bool() val sw = Bool() val sx = Bool() val sr = Bool() @@ -140,9 +141,13 @@ class TLB(lgMaxSize: Int, nEntries: Int)(implicit edge: TLEdgeOut, p: Parameters newEntry.c := cacheable newEntry.u := pte.u newEntry.g := pte.g - newEntry.sr := pte.sr() - newEntry.sw := pte.sw() - newEntry.sx := pte.sx() + // if an access exception occurs during PTW, pretend the page has full + // permissions so that a page fault will not occur, but clear the + // phyiscal memory permissions, so that an access exception will occur. + newEntry.ae := io.ptw.resp.bits.ae + newEntry.sr := pte.sr() || io.ptw.resp.bits.ae + newEntry.sw := pte.sw() || io.ptw.resp.bits.ae + newEntry.sx := pte.sx() || io.ptw.resp.bits.ae newEntry.pr := prot_r && !io.ptw.resp.bits.ae newEntry.pw := prot_w && !io.ptw.resp.bits.ae newEntry.px := prot_x && !io.ptw.resp.bits.ae @@ -154,7 +159,7 @@ class TLB(lgMaxSize: Int, nEntries: Int)(implicit edge: TLEdgeOut, p: Parameters val plru = new PseudoLRU(normalEntries) val repl_waddr = Mux(!valid(normalEntries-1, 0).andR, PriorityEncoder(~valid(normalEntries-1, 0)), plru.replace) - val priv_ok = Mux(priv_s, ~Mux(io.ptw.status.sum, UInt(0), entries.map(_.u).asUInt), entries.map(_.u).asUInt) + val priv_ok = entries.map(_.ae).asUInt | Mux(priv_s, ~Mux(io.ptw.status.sum, UInt(0), entries.map(_.u).asUInt), entries.map(_.u).asUInt) val r_array = Cat(true.B, priv_ok & (entries.map(_.sr).asUInt | Mux(io.ptw.status.mxr, entries.map(_.sx).asUInt, UInt(0)))) val w_array = Cat(true.B, priv_ok & entries.map(_.sw).asUInt) val x_array = Cat(true.B, priv_ok & entries.map(_.sx).asUInt) diff --git a/src/main/scala/rocket/Tile.scala b/src/main/scala/rocket/Tile.scala index 4f386d45..bec3190c 100644 --- a/src/main/scala/rocket/Tile.scala +++ b/src/main/scala/rocket/Tile.scala @@ -29,9 +29,10 @@ class RocketTile(val rocketParams: RocketTileParams, val hartid: Int)(implicit p nDCachePorts += 1 // core TODO dcachePorts += () => module.core.io.dmem ?? - val device = new Device { - def ofInt(x: Int) = Seq(ResourceInt(BigInt(x))) - def ofStr(x: String) = Seq(ResourceString(x)) + private def ofInt(x: Int) = Seq(ResourceInt(BigInt(x))) + private def ofStr(x: String) = Seq(ResourceString(x)) + + val cpuDevice = new Device { def describe(resources: ResourceBindings): Description = { val block = p(CacheBlockBytes) val m = if (rocketParams.core.mulDiv.nonEmpty) "m" else "" @@ -85,24 +86,28 @@ class RocketTile(val rocketParams: RocketTileParams, val hartid: Int)(implicit p "compatible" -> ofStr("riscv"), "status" -> ofStr("okay"), "clock-frequency" -> Seq(ResourceInt(rocketParams.core.bootFreqHz)), - "riscv,isa" -> ofStr(isa), - "interrupt-controller" -> Nil, - "#interrupt-cells" -> ofInt(1)) + "riscv,isa" -> ofStr(isa)) ++ dcache ++ icache ++ nextlevel ++ mmu ++ itlb ++ dtlb) } } + val intcDevice = new Device { + def describe(resources: ResourceBindings): Description = { + Description(s"cpus/cpu@${hartid}/interrupt-controller", Map( + "compatible" -> ofStr("riscv,cpu-intc"), + "interrupt-controller" -> Nil, + "#interrupt-cells" -> ofInt(1))) + } + } ResourceBinding { - Resource(device, "reg").bind(ResourceInt(BigInt(hartid))) - - // debug, msip, mtip, meip, seip offsets in CSRs - val intMap = Seq(65535, 3, 7, 11, 9) + Resource(cpuDevice, "reg").bind(ResourceInt(BigInt(hartid))) + Resource(intcDevice, "reg").bind(ResourceInt(BigInt(hartid))) intNode.edgesIn.flatMap(_.source.sources).map { case s => for (i <- s.range.start until s.range.end) { - intMap.lift(i).foreach { j => + csrIntMap.lift(i).foreach { j => s.resources.foreach { r => - r.bind(device, ResourceInt(j)) + r.bind(intcDevice, ResourceInt(j)) } } } @@ -122,7 +127,8 @@ class RocketTileModule(outer: RocketTile) extends BaseTileModule(outer, () => ne require(outer.p(PAddrBits) >= outer.masterNode.edgesIn(0).bundle.addressBits) val core = Module(p(BuildCore)(outer.p)) - core.io.hartid := io.hartid + decodeCoreInterrupts(core.io.interrupts) // Decode the interrupt vector + core.io.hartid := io.hartid // Pass through the hartid outer.frontend.module.io.cpu <> core.io.imem outer.frontend.module.io.resetVector := io.resetVector dcachePorts += core.io.dmem // TODO outer.dcachePorts += () => module.core.io.dmem ?? @@ -136,12 +142,6 @@ class RocketTileModule(outer: RocketTile) extends BaseTileModule(outer, () => ne core.io.rocc.interrupt := lr.module.io.core.interrupt } - // Decode the interrupt vector - core.io.interrupts.debug := io.interrupts(0)(0) - core.io.interrupts.msip := io.interrupts(0)(1) - core.io.interrupts.mtip := io.interrupts(0)(2) - core.io.interrupts.meip := io.interrupts(0)(3) - core.io.interrupts.seip.foreach { _ := io.interrupts(0)(4) } // TODO eliminate this redundancy val h = dcachePorts.size diff --git a/src/main/scala/rocketchip/BaseTop.scala b/src/main/scala/rocketchip/BaseTop.scala index d74c8499..ffb2b6f9 100644 --- a/src/main/scala/rocketchip/BaseTop.scala +++ b/src/main/scala/rocketchip/BaseTop.scala @@ -35,7 +35,7 @@ trait HasTopLevelNetworks extends HasPeripheryParameters { val socBus = LazyModule(new TLXbar) // Wide or unordered-access slave devices (TL-UH) val peripheryBus = LazyModule(new TLXbar) // Narrow and ordered-access slave devices (TL-UL) - val intBus = LazyModule(new IntXbar) // Interrupts + val intBus = LazyModule(new IntXbar) // Device and global external interrupts val fsb = LazyModule(new TLBuffer(BufferParams.none)) // Master devices talking to the frontside of the L2 val bsb = LazyModule(new TLBuffer(BufferParams.none)) // Slave devices talking to the backside of the L2 val mem = Seq.fill(nMemoryChannels) { LazyModule(new TLXbar) } // Ports out to DRAM diff --git a/src/main/scala/tile/BaseTile.scala b/src/main/scala/tile/BaseTile.scala index 3b72d40d..bebe2bfb 100644 --- a/src/main/scala/tile/BaseTile.scala +++ b/src/main/scala/tile/BaseTile.scala @@ -52,13 +52,11 @@ trait HasTileLinkMasterPort extends HasTileParameters { implicit val p: Parameters val module: HasTileLinkMasterPortModule val masterNode = TLOutputNode() - val intNode = IntSinkNode(IntSinkPortSimple()) } trait HasTileLinkMasterPortBundle { val outer: HasTileLinkMasterPort val master = outer.masterNode.bundleOut - val interrupts = outer.intNode.bundleIn } trait HasTileLinkMasterPortModule { @@ -67,15 +65,18 @@ trait HasTileLinkMasterPortModule { } abstract class BaseTile(tileParams: TileParams)(implicit p: Parameters) extends BareTile - with HasTileLinkMasterPort { + with HasTileLinkMasterPort + with HasExternalInterrupts { override lazy val module = new BaseTileModule(this, () => new BaseTileBundle(this)) } class BaseTileBundle[+L <: BaseTile](_outer: L) extends BareTileBundle(_outer) - with HasTileLinkMasterPortBundle { + with HasTileLinkMasterPortBundle + with HasExternalInterruptsBundle { val hartid = UInt(INPUT, p(XLen)) val resetVector = UInt(INPUT, p(XLen)) } class BaseTileModule[+L <: BaseTile, +B <: BaseTileBundle[L]](_outer: L, _io: () => B) extends BareTileModule(_outer, _io) with HasTileLinkMasterPortModule + with HasExternalInterruptsModule diff --git a/src/main/scala/tile/Interrupts.scala b/src/main/scala/tile/Interrupts.scala index 00a00663..6210e3eb 100644 --- a/src/main/scala/tile/Interrupts.scala +++ b/src/main/scala/tile/Interrupts.scala @@ -4,13 +4,53 @@ package tile import Chisel._ import config.Parameters +import uncore.tilelink2.{IntSinkNode, IntSinkPortSimple} import util._ class TileInterrupts(implicit p: Parameters) extends CoreBundle()(p) { - val lip = Vec(coreParams.nLocalInterrupts, Bool()) val debug = Bool() val mtip = Bool() val msip = Bool() val meip = Bool() val seip = usingVM.option(Bool()) + val lip = Vec(coreParams.nLocalInterrupts, Bool()) +} + +// Use diplomatic interrupts to external interrupts from the coreplex into the tile +trait HasExternalInterrupts extends HasTileParameters { + implicit val p: Parameters + val module: HasExternalInterruptsModule + + val intNode = IntSinkNode(IntSinkPortSimple()) + + // TODO: the order of the following two functions must match, and + // also match the order which things are connected to the + // per-tile crossbar in coreplex.HasRocketTiles + + // debug, msip, mtip, meip, seip, lip offsets in CSRs + def csrIntMap: List[Int] = { + val nlips = tileParams.core.nLocalInterrupts + List(65535, 3, 7, 11, 9) ++ List.tabulate(nlips)(_ + 16) + } +} + +trait HasExternalInterruptsBundle { + val outer: HasExternalInterrupts + val interrupts = outer.intNode.bundleIn +} + +trait HasExternalInterruptsModule { + val outer: HasExternalInterrupts + val io: HasExternalInterruptsBundle + + // go from flat diplomatic Interrupts to bundled TileInterrupts + def decodeCoreInterrupts(core: TileInterrupts) { + val core_ips = Seq( + core.debug, + core.msip, + core.mtip, + core.meip, + core.seip.getOrElse(Wire(Bool()))) ++ core.lip + core_ips.zip(io.interrupts(0)).foreach { case(c, i) => c := i } + } } diff --git a/vsim/Makefrag-verilog b/vsim/Makefrag-verilog index f3d64787..8ac71ce4 100644 --- a/vsim/Makefrag-verilog +++ b/vsim/Makefrag-verilog @@ -25,6 +25,7 @@ $(generated_dir)/$(long_name).behav_srams.v : $(generated_dir)/$(long_name).conf #-------------------------------------------------------------------- # Run #-------------------------------------------------------------------- +.PRECIOUS: $(output_dir)/%.vpd $(output_dir)/%.run: $(output_dir)/% $(simv) cd $(sim_dir) && $(exec_simv) +max-cycles=$(timeout_cycles) $< 2> /dev/null 2> $@ && [ $$PIPESTATUS -eq 0 ]