Commit 17e1a3a7 authored by Jens Korinth's avatar Jens Korinth
Browse files

Fix bug concerning empty slots

* empty slots did not exist at all, resulting in reads/writes causing
  bus errors, crash
* new Slot type Empty represents an empty slot
* slots in status configuration are filled with empty slots to fix the
  problem
* should not increase the size significantly; all empty slots are
  represented by the same ConstantRegister
parent e209f949
......@@ -14,17 +14,28 @@ object Builder {
implicit val axi: Axi4Lite.Configuration = Axi4Lite.Configuration(dataWidth = Axi4Lite.Width32,
addrWidth = AddrWidth(12))
private final val emptySlot = new ConstantRegister(Some("Empty Slot"), value = BigInt(0))
private def makeRegister(s: Slot): Seq[(Long, ControlRegister)] = s match {
case k: Slot.Kernel => Seq(
256L + s.slot * 16L -> new ConstantRegister(Some("Slot ${s.slot} Kernel ID"), value = BigInt(k.kernel)),
260L + s.slot * 16L -> new ConstantRegister(Some("Slot ${s.slot} Local Mem"), value = BigInt(0))
256L + s.slot * 16L -> new ConstantRegister(Some(s"Slot ${s.slot} Kernel ID"), value = BigInt(k.kernel)),
260L + s.slot * 16L -> new ConstantRegister(Some(s"Slot ${s.slot} Local Mem"), value = BigInt(0))
)
case m: Slot.Memory => Seq(
256L + s.slot * 16L -> new ConstantRegister(Some("Slot ${s.slot} Kernel ID"), value = BigInt(0)),
260L + s.slot * 16L -> new ConstantRegister(Some("Slot ${s.slot} Local Mem"), value = BigInt(m.size))
256L + s.slot * 16L -> new ConstantRegister(Some(s"Slot ${s.slot} Kernel ID"), value = BigInt(0)),
260L + s.slot * 16L -> new ConstantRegister(Some(s"Slot ${s.slot} Local Mem"), value = BigInt(m.size))
)
case k: Slot.Empty => Seq(
256L + s.slot * 16L -> emptySlot,
260L + s.slot * 16L -> emptySlot
)
}
private def fillEmptySlots(ss: Seq[Slot]): Seq[Slot] = {
val slotIds: Set[Int] = (ss map (_.slot: Int)).toSet
ss ++ (for (x <- 0 until NUM_SLOTS if !(slotIds.contains(x))) yield Slot.Empty(x))
}
def makeConfiguration(status: Status): RegisterFile.Configuration = RegisterFile.Configuration(
regs = (Seq[(Long, ControlRegister)](
0x00L -> new ConstantRegister(Some("Magic ID"), value = BigInt("E5AE1337", 16)),
......@@ -36,45 +47,49 @@ object Builder {
0x1CL -> new ConstantRegister(Some("Host Clock (Hz)"), value = BigInt(status.clocks.host.frequency.toLong)),
0x20L -> new ConstantRegister(Some("Design Clock (Hz)"), value = BigInt(status.clocks.design.frequency.toLong)),
0x24L -> new ConstantRegister(Some("Memory Clock (Hz)"), value = BigInt(status.clocks.memory.frequency.toLong))
) ++ ((status.config map (makeRegister _) fold Seq()) (_ ++ _))).toMap
) ++ ((fillEmptySlots(status.config) map (makeRegister _) fold Seq()) (_ ++ _))).toMap
)
private def makeBuilder(status: Status): chisel.packaging.ModuleBuilder = new chisel.packaging.ModuleBuilder {
private def makeBuilder(base: Path, status: Status): chisel.packaging.ModuleBuilder = new chisel.packaging.ModuleBuilder {
val configuration = makeConfiguration(status)
val modules: Seq[ModuleDef] = Seq(
ModuleDef(
None,
() => new RegisterFile(configuration),
CoreDefinition(
Some(configuration),
() => new RegisterFile(configuration) { override def desiredName = "tapasco_status" },
CoreDefinition.withActions(
name = "tapasco_status",
vendor = "esa.cs.tu-darmstadt.de",
library = "tapasco",
version = "1.2",
root = makePath(status).toString,
interfaces = Seq(Interface(name = "saxi", kind = "axi4slave"))
root = makePath(base, status).toString,
interfaces = Seq(Interface(name = "s_axi", kind = "axi4slave")),
postBuildActions = Seq(_ match {
case Some(cfg: RegisterFile.Configuration) => cfg.dumpAddressMap(makePath(base, status).toString)
case _ => ()
})
)
)
)
}
private def makePath(status: Status): Path =
Paths.get(".").toAbsolutePath.resolve("ip").resolve("%08x".format(status.hashCode)).normalize
private def makePath(base: Path, status: Status): Path = base.resolve("%08x".format(status.hashCode))
def main(args: Array[String]) {
require (args.length == 1, "expected exactly one argument: the name of the json configuration file")
require (args.length == 2, "expected exactly two arguments: the base path for IP cores and the name of the json configuration file")
try {
val json = Json.parse(Source.fromFile(args(0)).getLines mkString " ")
val base = Paths.get(args(0)).toAbsolutePath.normalize
val json = Json.parse(Source.fromFile(args(1)).getLines mkString " ")
val status: Status = Json.fromJson[Status](json).get
val hash = "%08x".format(status.hashCode)
val path = makePath(status)
val path = makePath(base, status)
println("Read configuration:")
println(Json.prettyPrint(json))
println("Status:")
println(status)
if (makePath(status).toFile.exists) {
if (path.toFile.exists) {
println(s"IP for configuration 0x$hash already exists, no need to build")
} else {
makeBuilder(status).main(Array("tapasco_status"))
makeBuilder(base, status).main(Array(base.toString, "tapasco_status"))
}
println(s"Finished, IP Core is located in $path")
} catch {
......
......@@ -60,13 +60,26 @@ package object json {
) (Memory.apply _)
/** Slot.Memory @} */
/** @{ Slot.Empty */
implicit val emptyWrites: Writes[Empty] = (
(JsPath \ "Type").write[String] ~
(JsPath \ "SlotId").write[SlotId]
) (e => ("Empty", e.slot))
val emptyReads: Reads[Slot] = (
(JsPath \ "Type").read[String] (verifying[String](_.toLowerCase equals "empty")) ~>
(JsPath \ "SlotId").read[SlotId]
) .fmap(Empty.apply _)
/** Slot.Empty @} */
/** @{ Slot */
implicit val slotReads: Reads[Slot] = kernelReads | memoryReads
implicit val slotReads: Reads[Slot] = kernelReads | memoryReads | emptyReads
implicit object SlotWrites extends Writes[Slot] {
def writes(c: Slot): JsValue = c match {
case k: Kernel => kernelWrites.writes(k)
case m: Memory => memoryWrites.writes(m)
case e: Empty => emptyWrites.writes(e)
}
}
/** Slot @} */
......
......@@ -54,12 +54,11 @@ package object tapasco_status {
}
}
sealed trait Slot {
def slot: SlotId
}
sealed trait Slot { def slot: SlotId }
object Slot {
final case class Kernel(slot: SlotId, kernel: KernelId) extends Slot
final case class Memory(slot: SlotId, size: Size) extends Slot
final case class Empty (slot: SlotId) extends Slot
}
final case class Status(config: Seq[Slot],
......
......@@ -50,8 +50,13 @@ package object generators {
k <- genSize
} yield Slot.Memory(slotId getOrElse s, k)
implicit def genEmpty(slotId: Option[SlotId] = None): Gen[Slot.Empty] = for {
s <- genSlotId
} yield Slot.Empty(slotId getOrElse s)
implicit def genSlot(slotId: Option[SlotId] = None): Gen[Slot] = Gen.oneOf(genKernel(slotId),
genMemory(slotId))
genMemory(slotId),
genEmpty(slotId))
val genInterruptControllers: Gen[Int] = Gen.choose(1, 4)
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment