diff --git a/Makefrag b/Makefrag index a8335606..e05f6d69 100644 --- a/Makefrag +++ b/Makefrag @@ -49,12 +49,13 @@ bootrom_img = $(base_dir)/bootrom/bootrom.img # Constants Header Files #--------------------------------------------------------------------- +# sed uses -E (instead of -r) for BSD support params_file = $(generated_dir)/$(MODEL).$(CONFIG).prm consts_header = $(generated_dir)/consts.$(CONFIG).h $(consts_header): $(params_file) echo "#ifndef __CONST_H__" > $@ echo "#define __CONST_H__" >> $@ - sed -r 's/\(([A-Za-z0-9_]+),([A-Za-z0-9_]+)\)/#define \1 \2/' $< >> $@ + sed -E 's/\(([A-Za-z0-9_]+),([A-Za-z0-9_]+)\)/#define \1 \2/' $< >> $@ echo "#endif // __CONST_H__" >> $@ params_file_debug = $(generated_dir_debug)/$(MODEL).$(CONFIG).prm @@ -62,7 +63,7 @@ consts_header_debug = $(generated_dir_debug)/consts.$(CONFIG).h $(consts_header_debug): $(params_file_debug) echo "#ifndef __CONST_H__" > $@ echo "#define __CONST_H__" >> $@ - sed -r 's/\(([A-Za-z0-9_]+),([A-Za-z0-9_]+)\)/#define \1 \2/' $< >> $@ + sed -E 's/\(([A-Za-z0-9_]+),([A-Za-z0-9_]+)\)/#define \1 \2/' $< >> $@ echo "#endif // __CONST_H__" >> $@ clean-run-output: diff --git a/csrc/emulator.cc b/csrc/emulator.cc index a6b04de1..db914704 100644 --- a/csrc/emulator.cc +++ b/csrc/emulator.cc @@ -98,14 +98,14 @@ int main(int argc, char** argv) #if VM_TRACE bool dump = tfp && trace_count >= start; if (dump) - tfp->dump(trace_count * 2); + tfp->dump(static_cast(trace_count * 2)); #endif tile->clk = 1; tile->eval(); #if VM_TRACE if (dump) - tfp->dump(trace_count * 2 + 1); + tfp->dump(static_cast(trace_count * 2 + 1)); #endif trace_count++; } diff --git a/firrtl b/firrtl index 6a05468e..7c38199c 160000 --- a/firrtl +++ b/firrtl @@ -1 +1 @@ -Subproject commit 6a05468ed0ece1ace3019666b16f2ae83ef76ef9 +Subproject commit 7c38199ce7a5d9dd7e27ffbb9b2b2770b972ed94 diff --git a/src/main/scala/coreplex/Coreplex.scala b/src/main/scala/coreplex/Coreplex.scala index 70d1343b..2ccad311 100644 --- a/src/main/scala/coreplex/Coreplex.scala +++ b/src/main/scala/coreplex/Coreplex.scala @@ -59,7 +59,7 @@ abstract class Coreplex(implicit val p: Parameters, implicit val c: CoreplexConf val slave = Vec(c.nSlaves, new ClientUncachedTileLinkIO()(innerParams)).flip val interrupts = Vec(c.nExtInterrupts, Bool()).asInput val debug = new DebugBusIO()(p).flip - val rtcTick = Bool(INPUT) + val prci = Vec(c.nTiles, new PRCITileIO).flip val success: Option[Bool] = hasSuccessFlag.option(Bool(OUTPUT)) } @@ -170,21 +170,14 @@ class DefaultCoreplex(tp: Parameters, tc: CoreplexConfig) extends Coreplex()(tp, debugModule.io.tl <> mmioNetwork.port("int:debug") debugModule.io.db <> io.debug - val prci = Module(new PRCI) - prci.io.tl <> mmioNetwork.port("int:prci") - prci.io.rtcTick := io.rtcTick - - (prci.io.tiles, tileResets, tileList).zipped.foreach { - case (prci, rst, tile) => - rst := reset - tile.io.prci <> prci - } - - for (i <- 0 until tc.nTiles) { - prci.io.interrupts(i).meip := plic.io.harts(plic.cfg.context(i, 'M')) - if (p(UseVM)) - prci.io.interrupts(i).seip := plic.io.harts(plic.cfg.context(i, 'S')) - prci.io.interrupts(i).debug := debugModule.io.debugInterrupts(i) + // connect coreplex-internal interrupts to tiles + for (((tile, tileReset), i) <- (tileList zip tileResets) zipWithIndex) { + tileReset := io.prci(i).reset + tile.io.interrupts := io.prci(i).interrupts + tile.io.interrupts.meip := plic.io.harts(plic.cfg.context(i, 'M')) + tile.io.interrupts.seip.foreach(_ := plic.io.harts(plic.cfg.context(i, 'S'))) + tile.io.interrupts.debug := debugModule.io.debugInterrupts(i) + tile.io.hartid := i } val tileSlavePorts = (0 until tc.nTiles) map (i => s"int:dmem$i") filter (ioAddrMap contains _) diff --git a/src/main/scala/coreplex/UnitTest.scala b/src/main/scala/coreplex/UnitTest.scala index b308b2e1..ca8e66da 100644 --- a/src/main/scala/coreplex/UnitTest.scala +++ b/src/main/scala/coreplex/UnitTest.scala @@ -7,10 +7,14 @@ import uncore.tilelink.TLId import cde.Parameters class UnitTestCoreplex(tp: Parameters, tc: CoreplexConfig) extends Coreplex()(tp, tc) { - require(!tc.hasExtMMIOPort) require(tc.nSlaves == 0) require(tc.nMemChannels == 0) + io.master.mmio.foreach { port => + port.acquire.valid := Bool(false) + port.grant.ready := Bool(false) + } + io.debug.req.ready := Bool(false) io.debug.resp.valid := Bool(false) diff --git a/src/main/scala/junctions/crossing.scala b/src/main/scala/junctions/crossing.scala index 4a17fde7..4e8e4227 100644 --- a/src/main/scala/junctions/crossing.scala +++ b/src/main/scala/junctions/crossing.scala @@ -83,5 +83,44 @@ object AsyncIrrevocableFrom // takes from_source from the 'from' clock domain and puts it into your clock domain def apply[T <: Data](from_clock: Clock, from_reset: Bool, from_source: ReadyValidIO[T], depth: Int = 8, sync: Int = 3): IrrevocableIO[T] = { PostQueueIrrevocablize(AsyncDecoupledFrom(from_clock, from_reset, from_source, depth, sync)) +} + +/** Because Chisel/FIRRTL does not allow us + * to directly assign clocks from Signals, + * we need this black box module. + * This may even be useful because some back-end + * flows like to have this sort of transition + * flagged with a special cell or module anyway. + */ + +class SignalToClock extends BlackBox { + val io = new Bundle { + val signal_in = Bool(INPUT) + val clock_out = Clock(OUTPUT) + } + + // io.clock_out := io.signal_in +} + +object SignalToClock { + def apply(signal: Bool): Clock = { + val s2c = Module(new SignalToClock) + s2c.io.signal_in := signal + s2c.io.clock_out + } +} + +class ClockToSignal extends BlackBox { + val io = new Bundle { + val clock_in = Clock(INPUT) + val signal_out = Bool(OUTPUT) + } +} + +object ClockToSignal { + def apply(clk: Clock): Bool = { + val c2s = Module(new ClockToSignal) + c2s.io.clock_in := clk + c2s.io.signal_out } } diff --git a/src/main/scala/junctions/hasti.scala b/src/main/scala/junctions/hasti.scala index 6063729e..9a36048f 100644 --- a/src/main/scala/junctions/hasti.scala +++ b/src/main/scala/junctions/hasti.scala @@ -521,10 +521,8 @@ class HastiTestSRAM(depth: Int)(implicit p: Parameters) extends HastiModule()(p) // In case we are stalled, we need to hold the read data val d_rdata = holdUnless(mem.read(a_address, read), RegNext(read)) // Whenever the port is not needed for reading, execute pending writes - when (!read) { - when (p_valid) { mem.write(p_address, p_wdata, p_mask.toBools) } - p_valid := Bool(false) - } + when (!read && p_valid) { mem.write(p_address, p_wdata, p_mask.toBools) } + when (!read) { p_valid := Bool(false) } // Record the request for later? when (ready && a_request && a_write) { diff --git a/src/main/scala/rocket/csr.scala b/src/main/scala/rocket/csr.scala index e75edb47..8b3ecff0 100644 --- a/src/main/scala/rocket/csr.scala +++ b/src/main/scala/rocket/csr.scala @@ -61,6 +61,14 @@ class DCSR extends Bundle { val prv = UInt(width = PRV.SZ) } +class TileInterrupts(implicit p: Parameters) extends CoreBundle()(p) { + val debug = Bool() + val mtip = Bool() + val msip = Bool() + val meip = Bool() + val seip = usingVM.option(Bool()) +} + class MIP extends Bundle { val rocc = Bool() val meip = Bool() @@ -121,7 +129,8 @@ object CSR } class CSRFileIO(implicit p: Parameters) extends CoreBundle { - val prci = new PRCITileIO().flip + val interrupts = new TileInterrupts().asInput + val hartid = UInt(INPUT, xLen) val rw = new Bundle { val addr = UInt(INPUT, CSR.ADDRSZ) val cmd = Bits(INPUT, CSR.SZ) @@ -297,7 +306,7 @@ class CSRFile(implicit p: Parameters) extends CoreModule()(p) CSRs.mepc -> reg_mepc.sextTo(xLen), CSRs.mbadaddr -> reg_mbadaddr.sextTo(xLen), CSRs.mcause -> reg_mcause, - CSRs.mhartid -> io.prci.id) + CSRs.mhartid -> io.hartid) val debug_csrs = collection.immutable.ListMap( CSRs.dcsr -> reg_dcsr.asUInt, @@ -611,8 +620,8 @@ class CSRFile(implicit p: Parameters) extends CoreModule()(p) } } - reg_mip := io.prci.interrupts - reg_dcsr.debugint := io.prci.interrupts.debug + reg_mip := io.interrupts + reg_dcsr.debugint := io.interrupts.debug reg_sptbr.asid := 0 if (nBreakpoints <= 1) reg_tselect := 0 diff --git a/src/main/scala/rocket/rocket.scala b/src/main/scala/rocket/rocket.scala index 6fa6893a..61b013b2 100644 --- a/src/main/scala/rocket/rocket.scala +++ b/src/main/scala/rocket/rocket.scala @@ -143,7 +143,8 @@ object ImmGen { class Rocket(implicit p: Parameters) extends CoreModule()(p) { val io = new Bundle { - val prci = new PRCITileIO().flip + val interrupts = new TileInterrupts().asInput + val hartid = UInt(INPUT, xLen) val imem = new FrontendIO()(p.alterPartial({case CacheName => "L1I" })) val dmem = new HellaCacheIO()(p.alterPartial({ case CacheName => "L1D" })) val ptw = new DatapathPTWIO().flip @@ -514,7 +515,8 @@ class Rocket(implicit p: Parameters) extends CoreModule()(p) { csr.io.exception := wb_reg_xcpt csr.io.cause := wb_reg_cause csr.io.retire := wb_valid - csr.io.prci <> io.prci + csr.io.interrupts := io.interrupts + csr.io.hartid := io.hartid io.fpu.fcsr_rm := csr.io.fcsr_rm csr.io.fcsr_flags := io.fpu.fcsr_flags csr.io.rocc.interrupt <> io.rocc.interrupt @@ -681,7 +683,7 @@ class Rocket(implicit p: Parameters) extends CoreModule()(p) { } else { printf("C%d: %d [%d] pc=[%x] W[r%d=%x][%d] R[r%d=%x] R[r%d=%x] inst=[%x] DASM(%x)\n", - io.prci.id, csr.io.time(31,0), wb_valid, wb_reg_pc, + io.hartid, csr.io.time(31,0), wb_valid, wb_reg_pc, Mux(rf_wen, rf_waddr, UInt(0)), rf_wdata, rf_wen, wb_reg_inst(19,15), Reg(next=Reg(next=ex_rs(0))), wb_reg_inst(24,20), Reg(next=Reg(next=ex_rs(1))), diff --git a/src/main/scala/rocket/tile.scala b/src/main/scala/rocket/tile.scala index df055f90..1a868fa8 100644 --- a/src/main/scala/rocket/tile.scala +++ b/src/main/scala/rocket/tile.scala @@ -31,7 +31,8 @@ abstract class Tile(clockSignal: Clock = null, resetSignal: Bool = null) class TileIO extends Bundle { val cached = Vec(nCachedTileLinkPorts, new ClientTileLinkIO) val uncached = Vec(nUncachedTileLinkPorts, new ClientUncachedTileLinkIO) - val prci = new PRCITileIO().flip + val hartid = UInt(INPUT, p(XLen)) + val interrupts = new TileInterrupts().asInput val slave = (p(DataScratchpadSize) > 0).option(new ClientUncachedTileLinkIO().flip) } @@ -54,7 +55,8 @@ class RocketTile(clockSignal: Clock = null, resetSignal: Bool = null) val uncachedArbPorts = collection.mutable.ArrayBuffer(icache.io.mem) val uncachedPorts = collection.mutable.ArrayBuffer[ClientUncachedTileLinkIO]() val cachedPorts = collection.mutable.ArrayBuffer(dcache.mem) - core.io.prci <> io.prci + core.io.interrupts := io.interrupts + core.io.hartid := io.hartid icache.io.cpu <> core.io.imem val fpuOpt = p(FPUKey).map(cfg => Module(new FPU(cfg))) diff --git a/src/main/scala/rocketchip/Periphery.scala b/src/main/scala/rocketchip/Periphery.scala index 50fa150f..cdf6e5fd 100644 --- a/src/main/scala/rocketchip/Periphery.scala +++ b/src/main/scala/rocketchip/Periphery.scala @@ -276,6 +276,33 @@ trait PeripherySlaveModule extends HasPeripheryParameters { ///// +/** Always-ON block */ +trait PeripheryAON extends LazyModule { + implicit val p: Parameters + val pDevices: ResourceManager[AddrMapEntry] + + pDevices.add(AddrMapEntry("prci", MemSize(0x4000000, MemAttr(AddrMapProt.RW)))) +} + +trait PeripheryAONBundle { + implicit val p: Parameters +} + +trait PeripheryAONModule extends HasPeripheryParameters { + implicit val p: Parameters + val outer: PeripheryAON + val io: PeripheryAONBundle + val mmioNetwork: Option[TileLinkRecursiveInterconnect] + val coreplex: Coreplex + + val prci = Module(new PRCI()(innerMMIOParams)) + prci.io.rtcTick := Counter(p(RTCPeriod)).inc() + prci.io.tl <> mmioNetwork.get.port("prci") + coreplex.io.prci <> prci.io.tiles +} + +///// + trait PeripheryTestRAM extends LazyModule { implicit val p: Parameters val pDevices: ResourceManager[AddrMapEntry] diff --git a/src/main/scala/rocketchip/Top.scala b/src/main/scala/rocketchip/Top.scala index 7dfdb0bc..ca239673 100644 --- a/src/main/scala/rocketchip/Top.scala +++ b/src/main/scala/rocketchip/Top.scala @@ -66,7 +66,6 @@ class BaseTopModule[+L <: BaseTop, +B <: BaseTopBundle](val p: Parameters, l: L, val io: B = b(coreplex) io.success zip coreplex.io.success map { case (x, y) => x := y } - coreplex.io.rtcTick := Counter(p(RTCPeriod)).inc() val mmioNetwork = c.hasExtMMIOPort.option( Module(new TileLinkRecursiveInterconnect(1, p(GlobalAddrMap).get.subMap("io:ext"))( @@ -76,17 +75,17 @@ class BaseTopModule[+L <: BaseTop, +B <: BaseTopBundle](val p: Parameters, l: L, /** Example Top with Periphery */ class ExampleTop(p: Parameters) extends BaseTop(p) - with PeripheryDebug with PeripheryExtInterrupts + with PeripheryDebug with PeripheryExtInterrupts with PeripheryAON with PeripheryMasterMem with PeripheryMasterMMIO with PeripherySlave { override lazy val module = Module(new ExampleTopModule(p, this, new ExampleTopBundle(p, _))) } class ExampleTopBundle(p: Parameters, c: Coreplex) extends BaseTopBundle(p, c) - with PeripheryDebugBundle with PeripheryExtInterruptsBundle + with PeripheryDebugBundle with PeripheryExtInterruptsBundle with PeripheryAONBundle with PeripheryMasterMemBundle with PeripheryMasterMMIOBundle with PeripherySlaveBundle class ExampleTopModule[+L <: ExampleTop, +B <: ExampleTopBundle](p: Parameters, l: L, b: Coreplex => B) extends BaseTopModule(p, l, b) - with PeripheryDebugModule with PeripheryExtInterruptsModule + with PeripheryDebugModule with PeripheryExtInterruptsModule with PeripheryAONModule with PeripheryMasterMemModule with PeripheryMasterMMIOModule with PeripherySlaveModule /** Example Top with TestRAM */ diff --git a/src/main/scala/rocketchip/Utils.scala b/src/main/scala/rocketchip/Utils.scala index 1f4765a2..b07a91b2 100644 --- a/src/main/scala/rocketchip/Utils.scala +++ b/src/main/scala/rocketchip/Utils.scala @@ -54,7 +54,6 @@ object GenerateGlobalAddrMap { entries += AddrMapEntry("debug", MemSize(4096, MemAttr(AddrMapProt.RWX))) entries += AddrMapEntry("bootrom", MemSize(4096, MemAttr(AddrMapProt.RX))) entries += AddrMapEntry("plic", MemRange(0x40000000, 0x4000000, MemAttr(AddrMapProt.RW))) - entries += AddrMapEntry("prci", MemSize(0x4000000, MemAttr(AddrMapProt.RW))) if (p(DataScratchpadSize) > 0) { // TODO heterogeneous tiles require(p(NTiles) == 1) // TODO relax this require(p(NMemoryChannels) == 0) // TODO allow both scratchpad & DRAM @@ -84,7 +83,7 @@ object GenerateConfigString { def apply(p: Parameters, c: CoreplexConfig, pDevicesEntries: Seq[AddrMapEntry]) = { val addrMap = p(GlobalAddrMap).get val plicAddr = addrMap("io:int:plic").start - val prciAddr = addrMap("io:int:prci").start + val prciAddr = addrMap("io:ext:prci").start val xLen = p(XLen) val res = new StringBuilder res append "plic {\n" diff --git a/src/main/scala/uncore/devices/Prci.scala b/src/main/scala/uncore/devices/Prci.scala index 24232fd8..d607be91 100644 --- a/src/main/scala/uncore/devices/Prci.scala +++ b/src/main/scala/uncore/devices/Prci.scala @@ -13,21 +13,11 @@ import cde.{Parameters, Field} /** Number of tiles */ case object NTiles extends Field[Int] -class PRCIInterrupts extends Bundle { - val meip = Bool() - val seip = Bool() - val debug = Bool() -} - class PRCITileIO(implicit p: Parameters) extends Bundle { val reset = Bool(OUTPUT) - val id = UInt(OUTPUT, log2Up(p(NTiles))) - val interrupts = { - val result = new PRCIInterrupts { - val mtip = Bool() - val msip = Bool() - } - result.asOutput + val interrupts = new Bundle { + val mtip = Bool() + val msip = Bool() } override def cloneType: this.type = new PRCITileIO().asInstanceOf[this.type] @@ -47,7 +37,6 @@ class PRCI(implicit val p: Parameters) extends Module with HasTileLinkParameters with HasAddrMapParameters { val io = new Bundle { - val interrupts = Vec(p(NTiles), new PRCIInterrupts).asInput val tl = new ClientUncachedTileLinkIO().flip val tiles = Vec(p(NTiles), new PRCITileIO) val rtcTick = Bool(INPUT) @@ -84,10 +73,9 @@ class PRCI(implicit val p: Parameters) extends Module } for ((tile, i) <- io.tiles zipWithIndex) { - tile.interrupts := io.interrupts(i) tile.interrupts.msip := ipi(i)(0) tile.interrupts.mtip := time >= timecmp(i) - tile.id := UInt(i) + tile.reset := reset } // TODO generalize these to help other TL slaves diff --git a/src/main/scala/uncore/tilelink2/RegisterCrossing.scala b/src/main/scala/uncore/tilelink2/RegisterCrossing.scala index 843c559e..3c11bbca 100644 --- a/src/main/scala/uncore/tilelink2/RegisterCrossing.scala +++ b/src/main/scala/uncore/tilelink2/RegisterCrossing.scala @@ -5,6 +5,7 @@ package uncore.tilelink2 import Chisel._ import chisel3.util.{Irrevocable, IrrevocableIO} import junctions._ +import uncore.util.{AsyncResetRegVec} // A very simple flow control state machine, run in the specified clock domain class BusyRegisterCrossing(clock: Clock, reset: Bool) @@ -131,3 +132,56 @@ class RegisterReadCrossing[T <: Data](gen: T, sync: Int = 3) extends Module { crossing.io.deq.ready := io.master_port.request.valid && !reg.io.busy crossing.io.enq.valid := Bool(true) } + +/** Wrapper to create an + * asynchronously reset + * slave register which + * can be both read + * and written using + * crossing FIFOs. + */ + +object AsyncRWSlaveRegField { + + def apply(slave_clock: Clock, + slave_reset: Bool, + width: Int, + init: Int, + master_allow: Bool = Bool(true), + slave_allow: Bool = Bool(true) + ): (UInt, RegField) = { + + val async_slave_reg = Module(new AsyncResetRegVec(width, init)) + async_slave_reg.reset := slave_reset + async_slave_reg.clock := slave_clock + + val wr_crossing = Module (new RegisterWriteCrossing(UInt(width = width))) + + val scope = Module (new AsyncScope()) + + wr_crossing.io.master_clock := scope.clock + wr_crossing.io.master_reset := scope.reset + wr_crossing.io.master_allow := master_allow + wr_crossing.io.slave_clock := slave_clock + wr_crossing.io.slave_reset := slave_reset + wr_crossing.io.slave_allow := slave_allow + + async_slave_reg.io.en := wr_crossing.io.slave_valid + async_slave_reg.io.d := wr_crossing.io.slave_register + + val rd_crossing = Module (new RegisterReadCrossing(UInt(width = width ))) + + rd_crossing.io.master_clock := scope.clock + rd_crossing.io.master_reset := scope.reset + rd_crossing.io.master_allow := master_allow + rd_crossing.io.slave_clock := slave_clock + rd_crossing.io.slave_reset := slave_reset + rd_crossing.io.slave_allow := slave_allow + + rd_crossing.io.slave_register := async_slave_reg.io.q + + (async_slave_reg.io.q, RegField(width, rd_crossing.io.master_port, wr_crossing.io.master_port)) + + } + +} diff --git a/vsim/Makefrag b/vsim/Makefrag index 3abb2b4e..31ee449b 100644 --- a/vsim/Makefrag +++ b/vsim/Makefrag @@ -7,7 +7,11 @@ bb_vsrcs = $(base_dir)/vsrc/DebugTransportModuleJtag.v \ $(base_dir)/vsrc/jtag_vpi.v \ $(base_dir)/vsrc/AsyncMailbox.v \ - $(base_dir)/vsrc/AsyncResetReg.v + $(base_dir)/vsrc/AsyncResetReg.v \ + $(base_dir)/vsrc/ClockDivider.v \ + $(base_dir)/vsrc/ClockToSignal.v \ + $(base_dir)/vsrc/SignalToClock.v \ + sim_vsrcs = \ $(generated_dir)/$(MODEL).$(CONFIG).v \ diff --git a/vsrc/ClockToSignal.v b/vsrc/ClockToSignal.v new file mode 100644 index 00000000..db8b8b37 --- /dev/null +++ b/vsrc/ClockToSignal.v @@ -0,0 +1,19 @@ + +/* This blackbox is needed by + * Chisel in order to do type conversion. + * It may be useful for some synthesis flows + * as well which require special + * flagging on conversion from data to clock. + */ + + +module ClockToSignal( + output signal_out, + input clock_in + ); + + + assign signal_out = clock_in; + +endmodule // ClockToSignal + diff --git a/vsrc/SignalToClock.v b/vsrc/SignalToClock.v new file mode 100644 index 00000000..553bc580 --- /dev/null +++ b/vsrc/SignalToClock.v @@ -0,0 +1,18 @@ + +/* This blackbox is needed by + * Chisel in order to do type conversion. + * It may be useful for some synthesis flows + * as well which require special + * flagging on conversion from data to clock. + */ + + +module SignalToClock ( + output clock_out, + input signal_in + ); + + + assign clock_out = signal_in; + +endmodule // SignalToClock