Skip to content

Commit

Permalink
Eliminate global when, switch stacks
Browse files Browse the repository at this point in the history
This supports instantiation of modules within when statements.  Note
this is not conditional instantiation, which does not make sense. It
is equivalent to instantiating a module outside of the when statement.
  • Loading branch information
aswaterman committed Feb 10, 2014
1 parent 35dc209 commit f6bee8a
Show file tree
Hide file tree
Showing 8 changed files with 35 additions and 48 deletions.
2 changes: 1 addition & 1 deletion src/main/scala/Bits.scala
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ abstract class Bits extends Data with proc {
else ChiselError.error({"reassignment to Wire " + this + " with inputs " + this.inputs(0) + " RHS: " + src});

override def procAssign(src: Node): Unit =
if (inputs.isEmpty) updates += ((genCond(), src))
if (inputs.isEmpty) updates += ((Module.current.whenCond, src))
else ChiselError.error({"reassignment to Wire " + this + " with inputs " + this.inputs(0) + " RHS: " + src});

//code generation stuff
Expand Down
13 changes: 7 additions & 6 deletions src/main/scala/Mem.scala
Original file line number Diff line number Diff line change
Expand Up @@ -119,21 +119,22 @@ class Mem[T <: Data](gen: () => T, val n: Int, val seqRead: Boolean, val ordered
}

def write(addr: UInt, data: T): Unit = {
val cond = Module.current.whenCond
if (seqRead && Module.backend.isInstanceOf[CppBackend] && gen().isInstanceOf[Bits]) {
// generate bogus data when reading & writing same address on same cycle
val reg_data = new Reg().init("", widthOf(0), data)
val random16 = LFSR16()
val random_data = Cat(random16, Array.fill((width-1)/16){random16}:_*)
doWrite(Reg(next=addr), Reg(next=conds.top), reg_data, null.asInstanceOf[UInt])
doWrite(addr, conds.top, random_data, null.asInstanceOf[UInt])
doWrite(Reg(next=addr), Reg(next=cond), reg_data, null.asInstanceOf[UInt])
doWrite(addr, cond, random_data, null.asInstanceOf[UInt])
} else {
doWrite(addr, conds.top, data, null.asInstanceOf[UInt])
doWrite(addr, cond, data, null.asInstanceOf[UInt])
}
}

def write(addr: UInt, data: T, wmask: UInt): Unit =
if (!Module.isInlineMem) doWrite(addr, conds.top, data, wmask)
else doWrite(addr, conds.top, gen().fromBits(data.toBits & wmask | read(addr).toBits & ~wmask), null.asInstanceOf[UInt])
if (!Module.isInlineMem) doWrite(addr, Module.current.whenCond, data, wmask)
else doWrite(addr, Module.current.whenCond, gen().fromBits(data.toBits & wmask | read(addr).toBits & ~wmask), null.asInstanceOf[UInt])

def apply(addr: UInt): T = {
val rdata = read(addr)
Expand Down Expand Up @@ -216,7 +217,7 @@ class MemSeqRead(mem: Mem[_], addri: Node) extends MemAccess(mem, addri) {

class PutativeMemWrite(mem: Mem[_], addri: UInt) extends Node with proc {
override def procAssign(src: Node) =
mem.doWrite(addri, conds.top, src, null.asInstanceOf[UInt])
mem.doWrite(addri, Module.current.whenCond, src, null.asInstanceOf[UInt])
}

class MemReadWrite(val read: MemSeqRead, val write: MemWrite) extends MemAccess(read.mem, null)
Expand Down
14 changes: 8 additions & 6 deletions src/main/scala/Module.scala
Original file line number Diff line number Diff line change
Expand Up @@ -176,11 +176,7 @@ object Module {
clk = UInt(INPUT, 1)
clk.setName("clk")

isCoercingArgs = true
isInGetWidth = false
conds.clear()
conds.push(Bool(true))
keys.clear()
}

//component stack handling stuff
Expand Down Expand Up @@ -268,8 +264,14 @@ abstract class Module(var clock: Clock = null, private var _reset: Bool = null)
val children = new ArrayBuffer[Module];
val debugs = HashSet[Node]();

val switchKeys = Stack[Bits]()
val whenConds = Stack[Bool]()
private lazy val trueCond = Bool(true)
def hasWhenCond: Boolean = !whenConds.isEmpty
def whenCond: Bool = if (hasWhenCond) whenConds.top else trueCond

val nodes = new ArrayBuffer[Node]
val mods = new ArrayBuffer[Node];
val mods = new ArrayBuffer[Node];
val omods = new ArrayBuffer[Node];

val regs = new ArrayBuffer[Reg];
Expand Down Expand Up @@ -374,7 +376,7 @@ abstract class Module(var clock: Clock = null, private var _reset: Bool = null)
}

def printf(message: String, args: Node*): Unit = {
val p = new Printf(conds.top && !this.reset, message, args)
val p = new Printf(Module.current.whenCond && !this.reset, message, args)
printfs += p
debug(p)
p.inputs.foreach(debug _)
Expand Down
6 changes: 0 additions & 6 deletions src/main/scala/Node.scala
Original file line number Diff line number Diff line change
Expand Up @@ -48,12 +48,6 @@ object Node {
s
}

var isCoercingArgs = true;
val conds = new Stack[Bool]();
conds.push(Bool(true));
// XXX ??
val keys = new Stack[Bits]();

var isInGetWidth = false

def fixWidth(w: Int) = {
Expand Down
4 changes: 2 additions & 2 deletions src/main/scala/Reg.scala
Original file line number Diff line number Diff line change
Expand Up @@ -176,8 +176,8 @@ class Reg extends Delay with proc {
if (assigned) {
ChiselError.error("reassignment to Reg");
}
val cond = genCond();
if (conds.length >= 1) {
val cond = Module.current.whenCond
if (Module.current.hasWhenCond) {
enable = if (isEnable) enable || cond else cond
isEnable = true
}
Expand Down
1 change: 0 additions & 1 deletion src/main/scala/Verilog.scala
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,6 @@ object VerilogBackend {

class VerilogBackend extends Backend {
Module.isEmittingComponents = true
isCoercingArgs = false
val keywords = VerilogBackend.keywords

val flushedTexts = HashSet[String]()
Expand Down
38 changes: 15 additions & 23 deletions src/main/scala/hcl.scala
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,9 @@ import ChiselError._

object when {
def execWhen(cond: Bool)(block: => Unit) {
conds.push(conds.top && cond);
block;
conds.pop();
Module.current.whenConds.push(Module.current.whenCond && cond)
block
Module.current.whenConds.pop()
}
def apply(cond: Bool)(block: => Unit): when = {
execWhen(cond){ block }
Expand All @@ -55,7 +55,7 @@ class when (prevCond: Bool) {
}
def otherwise (block: => Unit) {
val cond = !prevCond
if (conds.length == 1) cond.canBeUsedAsDefault = true
if (!Module.current.hasWhenCond) cond.canBeUsedAsDefault = true
when.execWhen(cond){ block }
}
}
Expand All @@ -68,27 +68,20 @@ object unless {

object switch {
def apply(c: Bits)(block: => Unit) {
keys.push(c);
block;
keys.pop();
Module.current.switchKeys.push(c)
block
Module.current.switchKeys.pop()
}
}
object is {
def apply(v: Bits)(block: => Unit) {
if (keys.length == 0) {
ChiselError.error("NO KEY SPECIFIED");
} else {
val c = keys(0) === v;
when (c) { block; }
}
}
def apply(v: Bits, vr: Bits*)(block: => Unit) {
if (keys.length == 0) {
ChiselError.error("NO KEY SPECIFIED");
} else {
val c = vr.foldLeft(keys(0) === v)( (p: Bool, v: Bits) => keys(0) === v || p );
when (c) { block; }
}
def apply(v: Bits)(block: => Unit): Unit =
apply(Seq(v))(block)
def apply(v: Bits, vr: Bits*)(block: => Unit): Unit =
apply(v :: vr.toList)(block)
def apply(v: Iterable[Bits])(block: => Unit): Unit = {
val keys = Module.current.switchKeys
if (keys.isEmpty) ChiselError.error("The 'is' keyword may not be used outside of a switch.")
else if (!v.isEmpty) when (v.map(_ === keys.top).reduce(_||_)) { block }
}
}

Expand Down Expand Up @@ -228,7 +221,6 @@ object chiselMainTest {

trait proc extends Node {
val updates = new collection.mutable.ListBuffer[(Bool, Node)]
def genCond(): Bool = conds.top;
def genMuxes(default: Node, others: Seq[(Bool, Node)]): Unit = {
val update = others.foldLeft(default)((v, u) => Multiplex(u._1, u._2, v))
if (inputs.isEmpty) inputs += update else inputs(0) = update
Expand Down
5 changes: 2 additions & 3 deletions src/test/scala/WhenTest.scala
Original file line number Diff line number Diff line change
Expand Up @@ -135,14 +135,12 @@ class WhenSuite extends TestSuite {

/** instantiate module in a when block.
*/
@Ignore("to fix: emit correct code with no error messages.")
@Test def testModuleInWhenBlock() {
class Submodule extends Module {
val io = new Bundle {
val in = UInt(INPUT,4)
val out = UInt(OUTPUT,4)
}
/* XXX This generates an error: NO DEFAULT SPECIFIED FOR WIRE */
io.out := io.in
}

Expand All @@ -155,7 +153,8 @@ class WhenSuite extends TestSuite {
io.out := UInt(0)
when( io.en ) {
val sub = Module(new Submodule)
io <> sub.io
io.out := sub.io.out
io <> sub.io /* connect only io.in to sub.io.in */
}
}

Expand Down

0 comments on commit f6bee8a

Please sign in to comment.