Skip to content
This repository has been archived by the owner on Apr 20, 2024. It is now read-only.

Add floorplan compiler (round 2) #121

Draft
wants to merge 73 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
73 commits
Select commit Hold shift + click to select a range
767affa
Add a rough draft of the floorplan IR and plumbing to generate annota…
jwright6323 Oct 23, 2019
63b9e05
This emits the right firrtl collateral, but barstools does not accept…
jwright6323 Oct 24, 2019
445564f
Fix FPIR serialization
jwright6323 Oct 25, 2019
95f147e
Add basic compiler App
jwright6323 Oct 29, 2019
d9e3deb
Updates for rocket-chip bump
colinschmidt Oct 31, 2019
89114ff
Move aoplib from fcl-floorplan
colinschmidt Oct 31, 2019
07084e1
Refactor IR/Constraints a bit
jwright6323 Oct 31, 2019
e04bc62
Fix? generate floorplan IR pass
colinschmidt Nov 1, 2019
2ae5046
Clean up firrtl pass
jwright6323 Nov 1, 2019
65dac5a
Make grids work in the Chisel API
jwright6323 Nov 1, 2019
e756cf3
Aspect compatibility
jwright6323 Nov 1, 2019
c213ea9
Fix naming and serialization; still need to figure out how to seriali…
jwright6323 Nov 2, 2019
8e5706c
Clean up the Floorplan IR emission pass
jwright6323 Nov 6, 2019
7021d0c
Make the MultiTargetAnnotation stuff work; TODO: get rid of some of t…
jwright6323 Nov 7, 2019
7eb6991
Start adding compiler infrastructure
jwright6323 Nov 7, 2019
87c62ba
Add Layouts
jwright6323 Nov 7, 2019
7d3de45
Rename relative placement to ratio, add length layout
jwright6323 Nov 8, 2019
f5738fd
Add preliminary README
jwright6323 Apr 6, 2020
94a1d82
Start working on new Aspects stuff, WIP
jwright6323 May 12, 2020
612c962
Some API tweaks
jwright6323 May 14, 2020
a1131ff
Update build.sbt
jwright6323 Jul 11, 2021
f658e0d
Make something that actually produces floorplan IR
jwright6323 Jul 11, 2021
10ac560
chisel API cleanup
jwright6323 Jul 12, 2021
5a98ec0
Fix relative pathing
jwright6323 Jul 12, 2021
4a8a533
Start adding Mem support
jwright6323 Jul 13, 2021
d580f7a
Style
jwright6323 Jul 13, 2021
471e7a0
Handle ReplSeqMem in the records
jwright6323 Jul 13, 2021
e324d83
Add text file that lists the macrocompiler mapping
jwright6323 Jul 13, 2021
9da78d0
Remove aoplib
jwright6323 Jul 13, 2021
128ef30
Make SRAM replacement work
jwright6323 Jul 14, 2021
5913abd
Move floorplan
jwright6323 Jul 14, 2021
46d7db2
Get top-level annotations working
jwright6323 Jul 16, 2021
7bb7d28
Replace MemElementArray with MemMacroArray
jwright6323 Jul 17, 2021
4d84447
Clean up names
jwright6323 Jul 17, 2021
d5fe7bd
Add first pass at HammerIR serialization
jwright6323 Jul 18, 2021
e0150ee
Simplify units, no longer separate area and length
jwright6323 Jul 18, 2021
f7a62a2
Add ofModule to hierarchical elements
jwright6323 Jul 18, 2021
e5e0612
Add grid elements
jwright6323 Jul 18, 2021
5eb084e
Get sideband annotations working
jwright6323 Jul 18, 2021
cf1bc0c
Clean up ofModule
jwright6323 Jul 18, 2021
cf77be6
try to un-break sbt test
jwright6323 Jul 18, 2021
79b458b
Add parents to IR
jwright6323 Jul 18, 2021
6a4ca62
Implement ReplaceHierarchicalPass
jwright6323 Jul 18, 2021
df3fa48
Temporary commit, this compiles but some implementations are intentio…
jwright6323 Jul 19, 2021
0947b05
Fix unimplemented methods
jwright6323 Jul 19, 2021
71e9606
Some constraint prop works
jwright6323 Jul 19, 2021
128c298
Remove accidental println
jwright6323 Jul 19, 2021
e292849
API tweak
jwright6323 Jul 21, 2021
9d96f3e
weights -> [xy]Weights
jwright6323 Jul 21, 2021
4b2a787
Sideband->OutOfBand
jwright6323 Jul 25, 2021
d968ab3
root->scope
jwright6323 Jul 25, 2021
36c97e4
Remove unnecessary Abstract*Grid
jwright6323 Jul 25, 2021
2739971
FloorplanElementRecord->FloorplanRecord
jwright6323 Jul 25, 2021
684d35a
ConstrainedHierarchicalTop should be level 2
jwright6323 Jul 26, 2021
662ff3b
Change PlacedHierarchicalTop topGroup to elements
jwright6323 Aug 9, 2021
150188b
Add weighted grid to chisel API
jwright6323 Aug 9, 2021
d296291
Clean up constraint prop
jwright6323 Aug 10, 2021
f00c305
Add basic mem array implementation
jwright6323 Aug 10, 2021
526fb29
Temporary commit, this compiles but we need to fix elements
jwright6323 Aug 10, 2021
23d24ca
Remove options from elements arrays
jwright6323 Aug 10, 2021
5389eb9
Add some basic implementations of resolve constraints
jwright6323 Aug 10, 2021
466ae30
Comment cleanup
jwright6323 Aug 10, 2021
322c17e
First pass of CalculatePlacementsPass
jwright6323 Aug 10, 2021
cae4d92
Legalize placements (crudely) and fix HammerIR serialization of enums
jwright6323 Aug 10, 2021
8b911d8
HammerIR compliance
jwright6323 Aug 10, 2021
35b5380
fix bug in placement calculation
jwright6323 Aug 10, 2021
c980eb9
Add mirroring
jwright6323 Aug 11, 2021
b4c1bd0
match package rearrangement + chisel bump
harrisonliew Apr 7, 2022
886393f
delete moved files
harrisonliew Apr 7, 2022
b0318c3
fixed targetinstance casting
harrisonliew Apr 13, 2022
a929923
fixed the path
Apr 20, 2022
f827a53
save current working fp complier [skip ci]
Sep 27, 2022
7501889
floorplan tools fixed bugs and add functions to be more flexible
Nov 18, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,10 @@ libraryDependencies ++= Seq(
"com.typesafe.play" %% "play-json" % "2.9.2",
"org.scalatest" %% "scalatest" % "3.2.9" % "test",
"org.apache.logging.log4j" % "log4j-api" % "2.11.2",
"org.apache.logging.log4j" % "log4j-core" % "2.11.2"
"org.apache.logging.log4j" % "log4j-core" % "2.11.2",
"org.json4s" %% "json4s-jackson" % "3.6.1",
"org.json4s" %% "json4s-ext" % "3.6.1",
"org.json4s" %% "json4s-native" % "3.6.1",
)
addCompilerPlugin("edu.berkeley.cs" % "chisel3-plugin" % defaultVersions("chisel3") cross CrossVersion.full)
resolvers ++= Seq(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
barstools.floorplan.firrtl.GenerateFloorplanIRPass
Binary file not shown.
5 changes: 5 additions & 0 deletions src/main/scala/barstools/floorplan/.vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"files.watcherExclude": {
"**/target": true
}
}
363 changes: 363 additions & 0 deletions src/main/scala/barstools/floorplan/Constraints.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,363 @@
// See LICENSE for license details
package barstools.floorplan

import scala.math.{BigInt, BigDecimal, sqrt}

sealed trait Constraint {
def and(that: Constraint): Constraint
def +(that: Constraint): Constraint
def *(that: BigDecimal): Constraint
def /(that: BigDecimal): Constraint
def test(value: BigDecimal): Boolean
def minimize: Constraint

def resolveMin: BigDecimal = this.minimize match {
case c: Impossible => throw new Exception("Cannot reduce impossible constraint. TODO provide more detailed debug info.")
case c: Unconstrained => BigDecimal(0)
case c: Constrained =>
c.eq.foreach { x => return x }
c.geq.foreach { x =>
c.mof.foreach { m =>
val n = (x/m).setScale(0, BigDecimal.RoundingMode.UP)
m*n
}
return x
}
BigDecimal(0)
}
def getConstraint: BigDecimal = this.minimize match {
case c: Impossible => throw new Exception("This is not constrined")
case c: Unconstrained => BigDecimal(0)
case c: Constrained =>
c.eq.foreach {x => return x }
c.geq.foreach { x =>
c.mof.foreach { m =>
val n = (x/m).setScale(0, BigDecimal.RoundingMode.UP)
m*n
}
return x
}
c.leq.foreach {x => return x}
BigDecimal(0)
}

def isConstrained: Boolean
}

final class Unconstrained extends Constraint {
def and(that: Constraint) = that
def +(that: Constraint) = that // ???
def *(that: BigDecimal) = this
def /(that: BigDecimal) = this
def test(value: BigDecimal) = true
def minimize = this
def isConstrained = false
}

object Unconstrained {
private val u = new Unconstrained
def apply() = u
}

object UnconstrainedSeq {
def apply(x: Int) = Seq.fill(x) { Unconstrained() }
}

// TODO add a reason?
final class Impossible extends Constraint {
def and(that: Constraint) = this
def +(that: Constraint) = this
def *(that: BigDecimal) = this
def /(that: BigDecimal) = this
def test(value: BigDecimal) = false
def minimize = this
def isConstrained = true
}

object Impossible {
private val i = new Impossible
def apply() = i
}

final case class Constrained(
eq: Option[BigDecimal] = None,
geq: Option[BigDecimal] = None,
leq: Option[BigDecimal] = None,
mof: Option[BigDecimal] = None
) extends Constraint {

def isConstrained: Boolean = eq.isDefined || geq.isDefined || leq.isDefined || mof.isDefined

def and(that: Constraint): Constraint = {
that match {
case that: Unconstrained => this
case that: Impossible => that
case that: Constrained =>

// Combine raw constraints
val newMof = if (this.mof.isDefined && that.mof.isDefined) {
Some(lcm(this.mof.get, that.mof.get))
} else {
this.mof.orElse(that.mof)
}

val newLeq = if (this.leq.isDefined && that.leq.isDefined) {
Some(Seq(this.leq.get, that.leq.get).min)
} else {
this.leq.orElse(that.leq)
}

val newGeq = if (this.geq.isDefined && that.geq.isDefined) {
Some(Seq(this.geq.get, that.geq.get).max)
} else {
this.geq.orElse(that.geq)
}

if (this.eq.isDefined && that.eq.isDefined && (this.eq != that.eq)) {
return Impossible()
}
val newEq = this.eq.orElse(that.eq)

Constrained(eq=newEq, geq=newGeq, leq=newLeq, mof=newMof).minimize
case _ => ???
}
}

def minimize: Constraint = {
// Check range on LEQ/GEQ
val newEq = if (leq.isDefined && geq.isDefined) {
if (leq.get < geq.get) {
return Impossible()
} else if (leq.get == geq.get) {
if (eq.isDefined && (eq.get != leq.get)) {
return Impossible()
}
leq
} else {
eq
}
} else {
eq
}

// Check multiples
if (eq.isDefined && mof.isDefined && (eq.get % mof.get != BigDecimal(0))) {
return Impossible()
}

if (eq.isDefined) {
if (leq.isDefined) {
if (eq.get > leq.get) {
return Impossible()
}
}
if (geq.isDefined) {
if (eq.get < geq.get) {
return Impossible()
}
}
}
// TODO check if there exists a multiple in range
this.copy(eq=newEq)
}

def +(that: Constraint): Constraint = {
that match {
case that: Unconstrained => this
case that: Impossible => that
case that: Constrained =>

// Combine raw constraints
val newMof = if (this.mof == that.mof) {
this.mof
} else {
None
}

val newLeq = if (this.leq.isDefined && that.eq.isDefined) {
Some(this.leq.get + that.eq.get)
} else if (this.eq.isDefined && that.leq.isDefined) {
Some(this.eq.get + that.leq.get)
} else if (this.leq.isDefined && that.leq.isDefined) {
Some(this.leq.get + that.leq.get)
} else {
None
}

val newGeq = if (this.geq.isDefined && that.eq.isDefined) {
Some(this.geq.get + that.eq.get)
} else if (this.eq.isDefined && that.geq.isDefined) {
Some(this.eq.get + that.geq.get)
} else if (this.geq.isDefined && that.geq.isDefined) {
Some(this.geq.get + that.geq.get)
} else {
None
}

val newEq = if (this.eq.isDefined && that.eq.isDefined) {
Some(this.eq.get + that.eq.get)
} else {
None
}

Constrained(eq=newEq, geq=newGeq, leq=newLeq, mof=newMof).minimize
case _ => ???
}
}

def *(that: BigDecimal): Constraint = Constrained(
eq = this.eq.map(_ * that),
geq = this.geq.map(_ * that),
leq = this.leq.map(_ * that),
mof = this.mof.map(_ * that)
)

def /(that: BigDecimal): Constraint = Constrained(
eq = this.eq.map(_ / that),
geq = this.geq.map(_ / that),
leq = this.leq.map(_ / that),
mof = this.mof.map(_ / that)
)

def test(value: BigDecimal): Boolean = {
val eqTest = this.eq.map(_ == value).getOrElse(true)
val geqTest = this.geq.map(_ <= value).getOrElse(true)
val leqTest = this.leq.map(_ >= value).getOrElse(true)
val mofTest = this.mof.map(x => (value % x) == 0).getOrElse(true)
return eqTest && geqTest && leqTest && mofTest
}
}

object EqualTo {
def apply(value: BigDecimal) = Constrained(Some(value), None, None, None)
}

object GreaterThanOrEqualTo {
def apply(value: BigDecimal) = Constrained(None, Some(value), None, None)
}

object LessThanOrEqualTo {
def apply(value: BigDecimal) = Constrained(None, None, Some(value), None)
}

object MultipleOf {
def apply(value: BigDecimal) = Constrained(None, None, None, Some(value))
}

case class Constraints(
width: Constraint = Unconstrained(),
height: Constraint = Unconstrained(),
area: Constraint = Unconstrained(),
aspectRatio: Constraint = Unconstrained()
) {
def test(widthValue: BigDecimal, heightValue: BigDecimal): Boolean = {
val widthTest = width.test(widthValue)
val heightTest = height.test(heightValue)
val areaTest = area.test(widthValue*heightValue)
val arTest = aspectRatio.test(heightValue/widthValue)
widthTest && heightTest && areaTest && arTest
}

def weightXY(xWeight: BigDecimal, yWeight: BigDecimal): Constraints = Constraints(
width = this.width * xWeight,
height = this.height * yWeight,
area = this.area * (xWeight * yWeight),
aspectRatio = this.aspectRatio * (yWeight / xWeight)
)

def resolveMinDimensions(): (BigDecimal, BigDecimal) = resolveMinDimensions(BigDecimal(0), BigDecimal(0))

def resolveMinDimensions(defaultWidth: BigDecimal, defaultHeight: BigDecimal): (BigDecimal, BigDecimal) = {
if (this.aspectRatio.isConstrained) {
if (this.area.isConstrained) {
// AspectRatio with Area
if (this.width == Unconstrained() && this.height == Unconstrained()) {
val heightConstraint = BigDecimal(sqrt((this.area.resolveMin * this.aspectRatio.resolveMin).doubleValue)) // TODO clean up rounding
(this.area.resolveMin / heightConstraint, heightConstraint)
} else {
// TODO resolve 3- or 4-way constraint (this is wrong)
???
}
} else {
// AspectRatio with no Area
// Use defaultWidth (TODO make this an option?)
if (this.width == Unconstrained() && this.height == Unconstrained()) {
(defaultWidth, this.aspectRatio.resolveMin * defaultWidth)
} else if (this.height == Unconstrained()) {
(this.height.resolveMin / this.aspectRatio.resolveMin, this.height.resolveMin)
} else if (this.width == Unconstrained()) {
(this.width.resolveMin, this.aspectRatio.resolveMin * this.width.resolveMin)
} else {
// TODO resolve 3-way constraint
???
}
}
} else {
if (this.area.isConstrained) {
// Area with no AspectRatio
// Use defaultWidth (TODO make this an option?)
if (this.width == Unconstrained() && this.height == Unconstrained()) {
(defaultWidth, this.area.resolveMin / defaultWidth)
} else if (this.height == Unconstrained()) {
(this.width.resolveMin, this.area.resolveMin / this.width.resolveMin)
} else if (this.width == Unconstrained()) {
(this.area.resolveMin / this.height.resolveMin, this.height.resolveMin)
} else {
// TODO resolve 3-way constraint (this is wrong)
val widthReq = Seq(this.width.resolveMin, this.area.resolveMin / this.height.resolveMin).max
val heightReq = Seq(this.width.resolveMin, this.area.resolveMin / this.width.resolveMin).max
(widthReq, heightReq)
}
} else {
// No Area or AspectRatio
val widthConstraint = this.width match {
case x: Unconstrained => defaultWidth
case x => x.resolveMin
}
val heightConstraint = this.height match {
case x: Unconstrained => defaultHeight
case x => x.resolveMin
}
(widthConstraint, heightConstraint)
}
}
}

}

object Constraints {

def sized(w: BigDecimal, h: BigDecimal): Constraints = {
Constraints(
EqualTo(w),
EqualTo(h),
Unconstrained(),
Unconstrained()
)
}

}

sealed trait PlacementAnchor

// TODO use this and convert to Enum
class LowerLeft extends PlacementAnchor
class LowerMiddle extends PlacementAnchor
class LowerRight extends PlacementAnchor
class CenterLeft extends PlacementAnchor
class CenterMiddle extends PlacementAnchor
class CenterRight extends PlacementAnchor
class UpperLeft extends PlacementAnchor
class UpperMiddle extends PlacementAnchor
class UpperRight extends PlacementAnchor

object LowerLeft { def apply() = new LowerLeft }
object LowerMiddle { def apply() = new LowerMiddle }
object LowerRight { def apply() = new LowerRight }
object CenterLeft { def apply() = new CenterLeft }
object CenterMiddle { def apply() = new CenterMiddle }
object CenterRight { def apply() = new CenterRight }
object UpperLeft { def apply() = new UpperLeft }
object UpperMiddle { def apply() = new UpperMiddle }
object UpperRight { def apply() = new UpperRight }

Loading