Remove legacy HTIF things
The SCR file is gone, too, because it is tightly coupled. The general concept could be revived as a module that somehow connects to (or is contained by) the debug module.
This commit is contained in:
parent
f57524e0c1
commit
354b81c8fe
@ -83,8 +83,7 @@ class DmaTrackerIO(implicit p: Parameters) extends DmaBundle()(p) {
|
||||
class DmaManager(outstandingCSR: Int)(implicit p: Parameters)
|
||||
extends DmaModule()(p)
|
||||
with HasNastiParameters
|
||||
with HasAddrMapParameters
|
||||
with HasHtifParameters {
|
||||
with HasAddrMapParameters {
|
||||
|
||||
val io = new Bundle {
|
||||
val ctrl = (new NastiIO).flip
|
||||
@ -168,7 +167,9 @@ class DmaManager(outstandingCSR: Int)(implicit p: Parameters)
|
||||
}
|
||||
|
||||
val addrTable = Vec.tabulate(nDmaClients) { i =>
|
||||
UInt(addrMap(s"conf:csr$i").start + outstandingCSR * csrDataBytes)
|
||||
//UInt(addrMap(s"conf:csr$i").start + outstandingCSR * csrDataBytes)
|
||||
require(false, "CSR MMIO ports no longer exist")
|
||||
UInt(0)
|
||||
}
|
||||
|
||||
io.mmio.ar.valid := Bool(false)
|
||||
@ -176,7 +177,7 @@ class DmaManager(outstandingCSR: Int)(implicit p: Parameters)
|
||||
io.mmio.aw.bits := NastiWriteAddressChannel(
|
||||
id = UInt(0),
|
||||
addr = addrTable(resp_client_id),
|
||||
size = UInt(log2Up(csrDataBytes)))
|
||||
size = { require(false, "CSR MMIO ports no longer exist"); UInt(0) })
|
||||
io.mmio.w.valid := resp_wdata_pending
|
||||
io.mmio.w.bits := NastiWriteDataChannel(data = resp_status)
|
||||
io.mmio.b.ready := resp_wresp_pending
|
||||
|
@ -1,326 +0,0 @@
|
||||
// See LICENSE for license details.
|
||||
|
||||
package uncore
|
||||
|
||||
import Chisel._
|
||||
import Chisel.ImplicitConversions._
|
||||
import junctions._
|
||||
import junctions.NastiConstants._
|
||||
import cde.{Parameters, Field}
|
||||
|
||||
case object HtifKey extends Field[HtifParameters]
|
||||
|
||||
case class HtifParameters(width: Int, nCores: Int, offsetBits: Int, csrDataBits: Int, nSCR: Int = 64)
|
||||
|
||||
trait HasHtifParameters {
|
||||
implicit val p: Parameters
|
||||
val htifExternal = p(HtifKey)
|
||||
val dataBits = p(TLKey(p(TLId))).dataBitsPerBeat
|
||||
val dataBeats = p(TLKey(p(TLId))).dataBeats
|
||||
val w = htifExternal.width
|
||||
val nSCR = htifExternal.nSCR
|
||||
val scrAddrBits = log2Up(nSCR)
|
||||
val scrDataBits = 64
|
||||
val scrDataBytes = scrDataBits / 8
|
||||
val csrDataBits = htifExternal.csrDataBits
|
||||
val csrDataBytes = csrDataBits / 8
|
||||
val offsetBits = htifExternal.offsetBits
|
||||
val nCores = htifExternal.nCores
|
||||
}
|
||||
|
||||
abstract class HtifModule(implicit val p: Parameters) extends Module with HasHtifParameters
|
||||
abstract class HtifBundle(implicit val p: Parameters) extends ParameterizedBundle()(p)
|
||||
with HasHtifParameters
|
||||
|
||||
class HostIO(w: Int) extends Bundle {
|
||||
val clk = Bool(OUTPUT)
|
||||
val clk_edge = Bool(OUTPUT)
|
||||
val in = Decoupled(Bits(width = w)).flip
|
||||
val out = Decoupled(Bits(width = w))
|
||||
|
||||
override def cloneType = new HostIO(w).asInstanceOf[this.type]
|
||||
}
|
||||
|
||||
class HtifIO(implicit p: Parameters) extends HtifBundle()(p) {
|
||||
val reset = Bool(INPUT)
|
||||
val id = UInt(INPUT, log2Up(nCores))
|
||||
val csr = new SmiIO(csrDataBits, 12).flip
|
||||
}
|
||||
|
||||
class Htif(csr_RESET: Int)(implicit val p: Parameters) extends Module with HasHtifParameters {
|
||||
val io = new Bundle {
|
||||
val host = new HostIO(w)
|
||||
val cpu = Vec(nCores, new HtifIO).flip
|
||||
val mem = new ClientUncachedTileLinkIO
|
||||
val scr = new SmiIO(scrDataBits, scrAddrBits)
|
||||
}
|
||||
|
||||
val short_request_bits = 64
|
||||
val long_request_bits = short_request_bits + dataBits*dataBeats
|
||||
require(short_request_bits % w == 0)
|
||||
|
||||
val rx_count_w = 13 + log2Up(64) - log2Up(w) // data size field is 12 bits
|
||||
val rx_count = Reg(init=UInt(0,rx_count_w))
|
||||
val rx_shifter = Reg(Bits(width = short_request_bits))
|
||||
val rx_shifter_in = Cat(io.host.in.bits, rx_shifter(short_request_bits-1,w))
|
||||
val next_cmd = rx_shifter_in(3,0)
|
||||
val cmd = Reg(Bits())
|
||||
val size = Reg(Bits())
|
||||
val pos = Reg(Bits())
|
||||
val seqno = Reg(Bits())
|
||||
val addr = Reg(Bits())
|
||||
when (io.host.in.valid && io.host.in.ready) {
|
||||
rx_shifter := rx_shifter_in
|
||||
rx_count := rx_count + UInt(1)
|
||||
when (rx_count === UInt(short_request_bits/w-1)) {
|
||||
cmd := next_cmd
|
||||
size := rx_shifter_in(15,4)
|
||||
pos := rx_shifter_in(15,4+offsetBits-3)
|
||||
seqno := rx_shifter_in(23,16)
|
||||
addr := rx_shifter_in(63,24)
|
||||
}
|
||||
}
|
||||
|
||||
val rx_word_count = (rx_count >> log2Up(short_request_bits/w))
|
||||
val rx_word_done = io.host.in.valid && rx_count(log2Up(short_request_bits/w)-1,0).andR
|
||||
val packet_ram_depth = long_request_bits/short_request_bits-1
|
||||
val packet_ram = Mem(packet_ram_depth, Bits(width = short_request_bits))
|
||||
when (rx_word_done && io.host.in.ready) {
|
||||
packet_ram(rx_word_count(log2Up(packet_ram_depth)-1,0) - UInt(1)) := rx_shifter_in
|
||||
}
|
||||
|
||||
val cmd_readmem :: cmd_writemem :: cmd_readcr :: cmd_writecr :: cmd_ack :: cmd_nack :: Nil = Enum(UInt(), 6)
|
||||
|
||||
val csr_addr = addr(io.cpu(0).csr.req.bits.addr.getWidth-1, 0)
|
||||
val csr_coreid = addr(log2Up(nCores)-1+20+1,20)
|
||||
val csr_wdata = packet_ram(0)
|
||||
|
||||
val bad_mem_packet = size(offsetBits-1-3,0).orR || addr(offsetBits-1-3,0).orR
|
||||
val nack = Mux(cmd === cmd_readmem || cmd === cmd_writemem, bad_mem_packet,
|
||||
Mux(cmd === cmd_readcr || cmd === cmd_writecr, size =/= UInt(1),
|
||||
Bool(true)))
|
||||
|
||||
val tx_count = Reg(init=UInt(0, rx_count_w))
|
||||
val tx_subword_count = tx_count(log2Up(short_request_bits/w)-1,0)
|
||||
val tx_word_count = tx_count(rx_count_w-1, log2Up(short_request_bits/w))
|
||||
val packet_ram_raddr = tx_word_count(log2Up(packet_ram_depth)-1,0) - UInt(1)
|
||||
when (io.host.out.valid && io.host.out.ready) {
|
||||
tx_count := tx_count + UInt(1)
|
||||
}
|
||||
|
||||
val rx_done = rx_word_done && Mux(rx_word_count === UInt(0), next_cmd =/= cmd_writemem && next_cmd =/= cmd_writecr, rx_word_count === size || rx_word_count(log2Up(packet_ram_depth)-1,0) === UInt(0))
|
||||
val tx_size = Mux(!nack && (cmd === cmd_readmem || cmd === cmd_readcr || cmd === cmd_writecr), size, UInt(0))
|
||||
val tx_done = io.host.out.ready && tx_subword_count.andR && (tx_word_count === tx_size || tx_word_count > UInt(0) && packet_ram_raddr.andR)
|
||||
|
||||
val state_rx :: state_csr_req :: state_csr_resp :: state_mem_rreq :: state_mem_wreq :: state_mem_rresp :: state_mem_wresp :: state_tx :: Nil = Enum(UInt(), 8)
|
||||
val state = Reg(init=state_rx)
|
||||
|
||||
val (cnt, cnt_done) = Counter((state === state_mem_wreq && io.mem.acquire.ready) ||
|
||||
(state === state_mem_rresp && io.mem.grant.valid), dataBeats)
|
||||
val rx_cmd = Mux(rx_word_count === UInt(0), next_cmd, cmd)
|
||||
when (state === state_rx && rx_done) {
|
||||
state := Mux(rx_cmd === cmd_readmem, state_mem_rreq,
|
||||
Mux(rx_cmd === cmd_writemem, state_mem_wreq,
|
||||
Mux(rx_cmd === cmd_readcr || rx_cmd === cmd_writecr, state_csr_req,
|
||||
state_tx)))
|
||||
}
|
||||
when (state === state_mem_wreq) {
|
||||
when (cnt_done) { state := state_mem_wresp }
|
||||
}
|
||||
when (state === state_mem_rreq) {
|
||||
when(io.mem.acquire.ready) { state := state_mem_rresp }
|
||||
}
|
||||
when (state === state_mem_wresp && io.mem.grant.valid) {
|
||||
state := Mux(cmd === cmd_readmem || pos === UInt(1), state_tx, state_rx)
|
||||
pos := pos - UInt(1)
|
||||
addr := addr + UInt(1 << offsetBits-3)
|
||||
}
|
||||
when (state === state_mem_rresp && cnt_done) {
|
||||
state := Mux(cmd === cmd_readmem || pos === UInt(1), state_tx, state_rx)
|
||||
pos := pos - UInt(1)
|
||||
addr := addr + UInt(1 << offsetBits-3)
|
||||
}
|
||||
when (state === state_tx && tx_done) {
|
||||
when (tx_word_count === tx_size) {
|
||||
rx_count := UInt(0)
|
||||
tx_count := UInt(0)
|
||||
}
|
||||
state := Mux(cmd === cmd_readmem && pos =/= UInt(0), state_mem_rreq, state_rx)
|
||||
}
|
||||
|
||||
val n = dataBits/short_request_bits
|
||||
val mem_req_data = (0 until n).map { i =>
|
||||
def addr(offset: UInt) =
|
||||
if (dataBits == short_request_bits) offset
|
||||
else Cat(offset, UInt(i, log2Up(n)))
|
||||
when (state === state_mem_rresp && io.mem.grant.valid) {
|
||||
packet_ram(addr(io.mem.grant.bits.addr_beat)) :=
|
||||
io.mem.grant.bits.data((i+1)*short_request_bits-1, i*short_request_bits)
|
||||
}
|
||||
packet_ram(addr(cnt))
|
||||
}.reverse.reduce(_##_)
|
||||
|
||||
val init_addr = addr.toUInt >> (offsetBits-3)
|
||||
io.mem.acquire.valid := state === state_mem_rreq || state === state_mem_wreq
|
||||
io.mem.acquire.bits := Mux(cmd === cmd_writemem,
|
||||
PutBlock(
|
||||
addr_block = init_addr,
|
||||
addr_beat = cnt,
|
||||
client_xact_id = UInt(0),
|
||||
data = mem_req_data),
|
||||
GetBlock(addr_block = init_addr))
|
||||
io.mem.grant.ready := Bool(true)
|
||||
|
||||
val csrReadData = Reg(Bits(width = io.cpu(0).csr.resp.bits.getWidth))
|
||||
for (i <- 0 until nCores) {
|
||||
val my_reset = Reg(init=Bool(true))
|
||||
|
||||
val cpu = io.cpu(i)
|
||||
val me = csr_coreid === UInt(i)
|
||||
cpu.csr.req.valid := state === state_csr_req && me && csr_addr =/= UInt(csr_RESET)
|
||||
cpu.csr.req.bits.rw := cmd === cmd_writecr
|
||||
cpu.csr.req.bits.addr := csr_addr
|
||||
cpu.csr.req.bits.data := csr_wdata
|
||||
cpu.reset := my_reset
|
||||
|
||||
when (cpu.csr.req.fire()) { state := state_csr_resp }
|
||||
|
||||
when (state === state_csr_req && me && csr_addr === UInt(csr_RESET)) {
|
||||
when (cmd === cmd_writecr) {
|
||||
my_reset := csr_wdata(0)
|
||||
}
|
||||
csrReadData := my_reset.toBits
|
||||
state := state_tx
|
||||
}
|
||||
|
||||
cpu.csr.resp.ready := Bool(true)
|
||||
when (state === state_csr_resp && cpu.csr.resp.valid) {
|
||||
csrReadData := cpu.csr.resp.bits
|
||||
state := state_tx
|
||||
}
|
||||
}
|
||||
|
||||
io.scr.req.valid := (state === state_csr_req && csr_coreid.andR)
|
||||
io.scr.req.bits.addr := addr(scrAddrBits - 1, 0).toUInt
|
||||
io.scr.req.bits.data := csr_wdata
|
||||
io.scr.req.bits.rw := (cmd === cmd_writecr)
|
||||
io.scr.resp.ready := Bool(true)
|
||||
|
||||
when (io.scr.req.fire()) { state := state_csr_resp }
|
||||
when (state === state_csr_resp && io.scr.resp.valid) {
|
||||
csrReadData := io.scr.resp.bits
|
||||
state := state_tx
|
||||
}
|
||||
|
||||
val tx_cmd = Mux(nack, cmd_nack, cmd_ack)
|
||||
val tx_cmd_ext = Cat(Bits(0, 4-tx_cmd.getWidth), tx_cmd)
|
||||
val tx_header = Cat(addr, seqno, tx_size, tx_cmd_ext)
|
||||
val tx_data = Mux(tx_word_count === UInt(0), tx_header,
|
||||
Mux(cmd === cmd_readcr || cmd === cmd_writecr, csrReadData,
|
||||
packet_ram(packet_ram_raddr)))
|
||||
|
||||
io.host.in.ready := state === state_rx
|
||||
io.host.out.valid := state === state_tx
|
||||
io.host.out.bits := tx_data >> Cat(tx_count(log2Up(short_request_bits/w)-1,0), Bits(0, log2Up(w)))
|
||||
}
|
||||
|
||||
class NastiIOHostIOConverter(htifW: Int)(implicit val p: Parameters)
|
||||
extends Module with HasNastiParameters {
|
||||
val io = new Bundle {
|
||||
val nasti = (new NastiIO).flip
|
||||
val host = new HostIO(htifW).flip
|
||||
val reset = Bool(OUTPUT)
|
||||
}
|
||||
|
||||
def cloneType = new NastiIOHostIOConverter(htifW).asInstanceOf[this.type]
|
||||
|
||||
val raddr = io.nasti.ar.bits.addr(6, 2)
|
||||
val waddr = io.nasti.aw.bits.addr(6, 2)
|
||||
|
||||
|
||||
val DCOUNT_ADDR = 0x00
|
||||
val RFIFO_ADDR = 0x01
|
||||
|
||||
val WFIFO_ADDR = 0x00
|
||||
val RESET_ADDR = 0x1f
|
||||
|
||||
val FIFO_DEPTH = 32
|
||||
|
||||
val fifo_ren = Reg(init = Bool(false))
|
||||
val fifo_wen = Reg(init = Bool(false))
|
||||
|
||||
val fifo_rd_len = Reg(UInt(width = nastiXLenBits))
|
||||
val fifo_rd_id = Reg(UInt(width = nastiXIdBits))
|
||||
val fifo_wr_id = Reg(UInt(width = nastiXIdBits))
|
||||
val fifo_wr_ack = Reg(init = Bool(false))
|
||||
|
||||
val rd_count = Reg(init = Bool(false))
|
||||
val wr_reset = Reg(init = Bool(false))
|
||||
|
||||
when (io.nasti.ar.fire()) {
|
||||
fifo_rd_len := io.nasti.ar.bits.len
|
||||
fifo_rd_id := io.nasti.ar.bits.id
|
||||
when (raddr === UInt(RFIFO_ADDR)) {
|
||||
fifo_ren := Bool(true)
|
||||
} .elsewhen (raddr === UInt(DCOUNT_ADDR)) {
|
||||
rd_count := Bool(true)
|
||||
}
|
||||
}
|
||||
|
||||
when (io.nasti.r.fire()) {
|
||||
when (io.nasti.r.bits.last) {
|
||||
fifo_ren := Bool(false)
|
||||
rd_count := Bool(false)
|
||||
} .otherwise { fifo_rd_len := fifo_rd_len - UInt(1) }
|
||||
}
|
||||
|
||||
when (io.nasti.aw.fire()) {
|
||||
fifo_wr_id := io.nasti.aw.bits.id
|
||||
when (waddr === UInt(WFIFO_ADDR)) {
|
||||
fifo_wen := Bool(true)
|
||||
} .elsewhen (waddr === UInt(RESET_ADDR)) {
|
||||
wr_reset := Bool(true)
|
||||
}
|
||||
}
|
||||
|
||||
when (io.nasti.w.fire() && io.nasti.w.bits.last) {
|
||||
fifo_wen := Bool(false)
|
||||
wr_reset := Bool(false)
|
||||
fifo_wr_ack := Bool(true)
|
||||
}
|
||||
|
||||
when (io.nasti.b.fire()) { fifo_wr_ack := Bool(false) }
|
||||
|
||||
io.nasti.ar.ready := !fifo_ren
|
||||
io.nasti.aw.ready := !fifo_wen && !fifo_wr_ack
|
||||
io.nasti.b.valid := fifo_wr_ack
|
||||
io.nasti.b.bits := NastiWriteResponseChannel(id = fifo_wr_id)
|
||||
|
||||
io.reset := io.nasti.w.valid && wr_reset
|
||||
|
||||
val hn_fifo = Module(new MultiWidthFifo(htifW, nastiXDataBits, FIFO_DEPTH))
|
||||
hn_fifo.io.in <> io.host.out
|
||||
hn_fifo.io.out.ready := fifo_ren && io.nasti.r.ready
|
||||
io.nasti.r.valid := (fifo_ren && hn_fifo.io.out.valid) || rd_count
|
||||
io.nasti.r.bits := NastiReadDataChannel(
|
||||
id = fifo_rd_id,
|
||||
data = Mux(fifo_ren, hn_fifo.io.out.bits, hn_fifo.io.count),
|
||||
last = (fifo_rd_len === UInt(0)))
|
||||
|
||||
val nh_fifo = Module(new MultiWidthFifo(nastiXDataBits, htifW, FIFO_DEPTH))
|
||||
io.host.in <> nh_fifo.io.out
|
||||
nh_fifo.io.in.valid := fifo_wen && io.nasti.w.valid
|
||||
nh_fifo.io.in.bits := io.nasti.w.bits.data
|
||||
io.nasti.w.ready := (fifo_wen && nh_fifo.io.in.ready) || wr_reset
|
||||
|
||||
assert(!io.nasti.w.valid || io.nasti.w.bits.strb.andR,
|
||||
"Nasti to HostIO converter cannot take partial writes")
|
||||
assert(!io.nasti.ar.valid ||
|
||||
io.nasti.ar.bits.len === UInt(0) ||
|
||||
io.nasti.ar.bits.burst === BURST_FIXED,
|
||||
"Nasti to HostIO converter can only take fixed bursts")
|
||||
assert(!io.nasti.aw.valid ||
|
||||
io.nasti.aw.bits.len === UInt(0) ||
|
||||
io.nasti.aw.bits.burst === BURST_FIXED,
|
||||
"Nasti to HostIO converter can only take fixed bursts")
|
||||
}
|
@ -1,102 +0,0 @@
|
||||
package uncore
|
||||
|
||||
import Chisel._
|
||||
import junctions.SmiIO
|
||||
import cde.Parameters
|
||||
import scala.collection.mutable.HashMap
|
||||
import scala.collection.mutable.ArrayBuffer
|
||||
|
||||
/** Stores a map between SCR file names and address in the SCR file, which can
|
||||
* later be dumped to a header file for the test bench. */
|
||||
class SCRFileMap(prefix: String, maxAddress: Int, baseAddress: BigInt) {
|
||||
private val addr2name = HashMap.empty[Int, String]
|
||||
private val name2addr = HashMap.empty[String, Int]
|
||||
|
||||
def allocate(address: Int, name: String): Int = {
|
||||
Predef.assert(!addr2name.contains(address), "address already allocated")
|
||||
Predef.assert(!name2addr.contains(name), "name already allocated")
|
||||
Predef.assert(address < maxAddress, "address too large")
|
||||
addr2name += (address -> name)
|
||||
name2addr += (name -> address)
|
||||
println(prefix + ": %x -> ".format(baseAddress + address) + name)
|
||||
address
|
||||
}
|
||||
|
||||
def allocate(name: String): Int = {
|
||||
val addr = (0 until maxAddress).filter{ addr => !addr2name.contains(addr) }(0)
|
||||
allocate(addr, name)
|
||||
}
|
||||
|
||||
def as_c_header(): String = {
|
||||
addr2name.map{ case(address, name) =>
|
||||
List(
|
||||
"#define " + prefix + "__" + name + "__PADDR 0x%x".format(baseAddress + address),
|
||||
"#define " + prefix + "__" + name + "__OFFSET 0x%x".format(address)
|
||||
)
|
||||
}.flatten.mkString("\n") + "\n"
|
||||
}
|
||||
}
|
||||
|
||||
class SCRIO(map: SCRFileMap)(implicit p: Parameters) extends HtifBundle()(p) {
|
||||
val rdata = Vec(nSCR, Bits(INPUT, scrDataBits))
|
||||
val wen = Bool(OUTPUT)
|
||||
val waddr = UInt(OUTPUT, log2Up(nSCR))
|
||||
val wdata = Bits(OUTPUT, scrDataBits)
|
||||
|
||||
def attach(regs: Seq[Data], name_base: String): Seq[Data] = {
|
||||
regs.zipWithIndex.map{ case(reg, i) => attach(reg, name_base + "__" + i) }
|
||||
}
|
||||
|
||||
def attach(reg: Data, name: String): Data = {
|
||||
val addr = map.allocate(name)
|
||||
when (wen && (waddr === UInt(addr))) {
|
||||
reg := wdata
|
||||
}
|
||||
rdata(addr) := reg
|
||||
reg
|
||||
}
|
||||
|
||||
def allocate(address: Int, name: String): Unit = {
|
||||
map.allocate(address, name)
|
||||
}
|
||||
}
|
||||
|
||||
class SCRFile(prefix: String, baseAddress: BigInt)(implicit p: Parameters) extends HtifModule()(p) {
|
||||
val map = new SCRFileMap(prefix, 64, baseAddress)
|
||||
AllSCRFiles += map
|
||||
|
||||
val io = new Bundle {
|
||||
val smi = new SmiIO(scrDataBits, scrAddrBits).flip
|
||||
val scr = new SCRIO(map)
|
||||
}
|
||||
|
||||
val scr_rdata = Wire(Vec(io.scr.rdata.size, Bits(width=scrDataBits)))
|
||||
for (i <- 0 until scr_rdata.size)
|
||||
scr_rdata(i) := io.scr.rdata(i)
|
||||
|
||||
val read_addr = Reg(init = UInt(0, scrAddrBits))
|
||||
val resp_valid = Reg(init = Bool(false))
|
||||
|
||||
io.smi.req.ready := !resp_valid
|
||||
io.smi.resp.valid := resp_valid
|
||||
io.smi.resp.bits := scr_rdata(read_addr)
|
||||
|
||||
io.scr.wen := io.smi.req.fire() && io.smi.req.bits.rw
|
||||
io.scr.wdata := io.smi.req.bits.data
|
||||
io.scr.waddr := io.smi.req.bits.addr
|
||||
|
||||
when (io.smi.req.fire()) {
|
||||
read_addr := io.smi.req.bits.addr
|
||||
resp_valid := Bool(true)
|
||||
}
|
||||
when (io.smi.resp.fire()) { resp_valid := Bool(false) }
|
||||
}
|
||||
|
||||
/** Every elaborated SCR file ends up in this global arry so it can be printed
|
||||
* out later. */
|
||||
object AllSCRFiles {
|
||||
private var maps = ArrayBuffer.empty[SCRFileMap]
|
||||
|
||||
def +=(map: SCRFileMap): Unit = { maps += map }
|
||||
def foreach( f: (SCRFileMap => Unit) ): Unit = { maps.foreach{ m => f(m) } }
|
||||
}
|
Loading…
Reference in New Issue
Block a user