Skip to content

Commit

Permalink
fix chkp + some ad hoc stuff
Browse files Browse the repository at this point in the history
  • Loading branch information
yy665 committed Oct 25, 2023
1 parent 5176c08 commit 6cc3a76
Show file tree
Hide file tree
Showing 16 changed files with 833 additions and 39 deletions.
4 changes: 2 additions & 2 deletions bscRuntime/memories/Locks.bsv
Original file line number Diff line number Diff line change
Expand Up @@ -159,8 +159,8 @@ module mkCheckpointQueueLock(Put#(winfo) mem, CheckpointQueueLock#(LockId#(d), L

method Action abort();
nextId[0] <= 0;
owner <= 0;
empty <= True;
owner <= 0;
empty <= True;
wdata <= tagged Invalid;
endmethod

Expand Down
51 changes: 50 additions & 1 deletion bscRuntime/memories/Memories.bsv
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ export AsyncMem(..);
export AsyncMem2(..);
export QueueLockCombMem(..);
export CheckpointQueueLockCombMem(..);
export CheckpointQueueLockAsyncMem(..);
export QueueLockAsyncMem(..);
export QueueLockAsyncMem2(..);
export BypassLockCombMem(..);
Expand All @@ -38,6 +39,7 @@ export mkAsyncMem;
export mkAsyncMem2;
export mkQueueLockCombMem;
export mkCheckpointQueueLockCombMem;
export mkCheckpointQueueLockAsyncMem;
export mkQueueLockAsyncMem;
export mkQueueLockAsyncMem2;
export mkFAAddrLockCombMem;
Expand All @@ -62,6 +64,14 @@ function Bool isNewer(UInt#(sz) a, UInt#(sz) b, UInt#(sz) h);
return !isOlder(a, b, h);
endfunction

function Put#(Tuple3#(Bit#(nsz), addr, elem)) asyncMemToPut (AsyncMem#(addr, elem, MemId#(inflight), nsz) amem);
return (interface Put;
method Action put(Tuple3#(Bit#(nsz), addr, elem) x);
amem.silentReq1(tpl_2(x), tpl_3(x), tpl_1(x));
endmethod
endinterface);
endfunction

function Put#(Tuple2#(addr, elem)) rfToPut (RegFile#(addr, elem) rf);
return (interface Put;
method Action put(Tuple2#(addr, elem) x);
Expand All @@ -84,6 +94,7 @@ endinterface

interface AsyncMem#(type addr, type elem, type mid, numeric type nsz);
method ActionValue#(mid) req1(addr a, elem b, Bit#(nsz) wmask);
method Action silentReq1(addr a, elem b, Bit#(nsz) wmask);
method elem peekResp1(mid a);
method Bool checkRespId1(mid a);
method Action resp1(mid a);
Expand Down Expand Up @@ -130,6 +141,14 @@ interface CheckpointQueueLockCombMem#(type addr, type elem, type id, type cid);
method Action atom_w(addr a, elem b);
endinterface

interface CheckpointQueueLockAsyncMem#(type addr, type elem, type rid, numeric type nsz, type id, type cid);
interface AsyncMem#(addr, elem, rid, nsz) mem;
interface CheckpointQueueLock#(id, cid, Tuple3#(Bit#(nsz), addr, elem)) lock;
method Action write(addr a, elem b, Bit#(nsz) wmask);
method Bool canAtom1(addr a);
method ActionValue#(rid) atom_req1(addr a, elem b, Bit#(nsz) wmask);
endinterface

interface QueueLockAsyncMem#(type addr, type elem, type rid, numeric type nsz, type lid);
interface AsyncMem#(addr, elem, rid, nsz) mem;
interface QueueLock#(lid) lock;
Expand Down Expand Up @@ -243,14 +262,15 @@ module mkBramPort#(parameter Bool init, parameter String file)(BramPort#(addr, e
interface Server bram_server;
interface Put request;
method Action put (Tuple3#(Bit#(nsz), addr, elem) req);
// $display("Sending request %t", $time());
//$display("Sending request %t %d %d ", $time(), tpl_1(req), tpl_3(req));
p.put(tpl_1(req), tpl_2(req), tpl_3(req));
doRead <= True;
endmethod
endinterface

interface Get response;
method ActionValue#(elem) get();
//$display("Returning data %t %d", nextData);
return nextData;
endmethod
endinterface
Expand Down Expand Up @@ -378,6 +398,11 @@ module mkAsyncMem(AsyncMem#(addr, elem, MemId#(inflight), n) _unused_)
return head;
endmethod

method Action silentReq1(addr a, elem b, Bit#(n) wmask) if (okToRequest);
toMem <= tuple3(wmask, a, b);
head <= head + 1;
endmethod

method elem peekResp1(MemId#(inflight) a);
return outData[a][1];
endmethod
Expand Down Expand Up @@ -681,6 +706,30 @@ module mkDMAddrLockCombMem(RegFile#(addr, elem) rf, AddrLockCombMem#(addr, elem,
interface lock = l;
endmodule

module mkCheckpointQueueLockAsyncMem(AsyncMem#(addr, elem, MemId#(inflight), nsz) amem, CheckpointQueueLockAsyncMem#(addr, elem, MemId#(inflight), nsz, LockId#(d), LockId#(d)) _unused_)
provisos(Bits#(Tuple3#(Bit#(nsz), addr, elem), tuplsz));

Put#(Tuple3#(Bit#(nsz), addr, elem)) doWrite = asyncMemToPut(amem);
CheckpointQueueLock#(LockId#(d), LockId#(d), Tuple3#(Bit#(nsz), addr, elem)) l <- mkCheckpointQueueLock(doWrite);

interface lock = l;
interface mem = amem;

method Action write(addr a, elem b, Bit#(nsz) wmask);
l.write(tuple3(wmask, a, b));
endmethod

method Bool canAtom1(addr a);
return l.isEmpty;
endmethod

method ActionValue#(MemId#(inflight)) atom_req1(addr a, elem b, Bit#(nsz) wmask);
let r <- amem.req1(a, b, wmask);
return r;
endmethod

endmodule

module mkQueueLockAsyncMem(AsyncMem#(addr, elem, MemId#(inflight), n) amem, QueueLockAsyncMem#(addr, elem, MemId#(inflight), n, LockId#(d)) _unused_)
provisos(Bits#(addr, szAddr), Bits#(elem, szElem));

Expand Down
6 changes: 4 additions & 2 deletions src/main/scala/pipedsl/codegen/bsv/BSVPrettyPrinter.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
package pipedsl.codegen.bsv

import java.io.{File, FileOutputStream, OutputStreamWriter, Writer}
import java.math.BigInteger

import pipedsl.codegen.bsv.BSVSyntax._
import pipedsl.common.Errors.BaseError
Expand Down Expand Up @@ -69,7 +70,7 @@ object BSVPrettyPrinter {
case BInteger() => "Integer"
}

private def toIntString(base: Int, value: Int): String = base match {
private def toIntString(base: Int, value: Int, bits: Int): String = base match {
case 16 => "h" + value.toHexString
case 10 => "d" + value.toString
case 8 => "o" + value.toOctalString
Expand Down Expand Up @@ -97,7 +98,7 @@ object BSVPrettyPrinter {
"False"
}
case BUnsizedInt(v) => v.toString
case BIntLit(v, base, bits) => bits.toString + "'" + toIntString(base, v)
case BIntLit(v, base, bits) => bits.toString + "'" + toIntString(base, v, bits)
case BStringLit(v) => "\"" + v + "\""
case BStructLit(typ, fields) =>
val fieldStr = fields.keys.map(k => {
Expand Down Expand Up @@ -129,6 +130,7 @@ object BSVPrettyPrinter {
val argstring = args.map(a => toBSVExprStr(a)).mkString(", ")
mkExprString(name, "(", argstring, ")")
case BMethodInvoke(mod, method, args) =>
println(mod, method, args)
val argstring = args.map(a => toBSVExprStr(a)).mkString(", ")
val argStringFull = if (argstring.isEmpty) "" else "(" + argstring + ")"
toBSVExprStr(mod) + "." + method + argStringFull
Expand Down
6 changes: 5 additions & 1 deletion src/main/scala/pipedsl/codegen/bsv/BSVSyntax.scala
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,11 @@ object BSVSyntax {
}

def toExpr(e: Expr): BExpr = e match {
case EInt(v, base, bits) => BIntLit(v, base, bits)
case EInt(v, base, bits) => bits match {
case -1 if v == 0 => BZero
case -1 if v == 1 => BAllOnes
case _ => BIntLit(v, base, bits)
} // TODO - EXN: Very ad-hoc stuff.. need Fix
case EBool(v) => BBoolLit(v)
case EString(v) => BStringLit(v)
case eu@EUop(_, _) => translateUOp(eu)
Expand Down
10 changes: 5 additions & 5 deletions src/main/scala/pipedsl/codegen/bsv/BluespecGeneration.scala
Original file line number Diff line number Diff line change
Expand Up @@ -717,7 +717,7 @@ object BluespecGeneration {
} else {
l
}
case im@IMemWrite(mem, addr, data, _, _, isAtomic) if isAtomic =>
case im@IMemWrite(mem, addr, data, writeMask, _, _, isAtomic) if isAtomic =>
val methodInfo = LockImplementation.getCanAtomicWrite(mem, addr, data, im.portNum)
if (methodInfo.isDefined) {
l :+ translateMethod(getLockName(mem), methodInfo.get)
Expand Down Expand Up @@ -1058,7 +1058,7 @@ object BluespecGeneration {
private def getCombinationalDeclaration(cmd: Command): Option[BDecl] = cmd match {
case CAssign(lhs, _) => Some(BDecl(translator.toVar(lhs), None))
case IMemSend(_, _, _, _, _, _, outH, _) if outH.isDefined => Some(BDecl(translator.toVar(outH.get), None))
case IMemWrite(_, _, _, _, outH, _) if outH.isDefined => Some(BDecl(translator.toVar(outH.get), None))
case IMemWrite(_, _, _, _, _, outH, _) if outH.isDefined => Some(BDecl(translator.toVar(outH.get), None))
case IMemRecv(_, _, data) => data match {
case Some(v) => Some(BDecl(translator.toVar(v), None))
case None => None
Expand Down Expand Up @@ -1104,7 +1104,7 @@ object BluespecGeneration {
case CExpr(exp) => Some(BExprStmt(translator.toExpr(exp)))
case IMemSend(_, _, _, _, _, inH, outH, _) if inH.isDefined && outH.isDefined =>
Some(BAssign(translator.toVar(outH.get), translator.toExpr(inH.get)))
case IMemWrite(_, _, _, inH, outH, _) if inH.isDefined && outH.isDefined =>
case IMemWrite(_, _, _, _, inH, outH, _) if inH.isDefined && outH.isDefined =>
Some(BAssign(translator.toVar(outH.get), translator.toExpr(inH.get)))
case IMemRecv(mem: Id, handle: EVar, data: Option[EVar]) => data match {
case Some(v) => Some(BAssign(translator.toVar(v),
Expand Down Expand Up @@ -1253,15 +1253,15 @@ object BluespecGeneration {
//This is an effectful op b/c is modifies the mem queue its reading from
case IMemRecv(mem: Id, handle: EVar, _: Option[EVar]) =>
Some(BExprStmt(bsInts.getMemResp(modParams(mem), translator.toVar(handle), cmd.portNum, isLockedMemory(mem))))
case IMemWrite(mem, addr, data, lHandle, _, isAtomic) =>
case IMemWrite(mem, addr, data, writeMask, lHandle, _, isAtomic) =>
val portNum = mem.typ.get match {
case memType: TLockedMemType => if (memType.limpl.usesWritePortNum) cmd.portNum else None
case _ => None //In the future we may allow unlocked mems with port annotations
}
Some(BExprStmt(
if (isLockedMemory(mem)) {
//ask lock for its translation
translateMethod(modParams(mem), LockImplementation.getWriteInfo(mem, addr, lHandle, data, portNum, isAtomic).get)
translateMethod(modParams(mem), LockImplementation.getWriteInfo(mem, addr, lHandle, data, writeMask, portNum, isAtomic).get)
} else {
//use unlocked translation
bsInts.getUnlockedCombWrite(modParams(mem), translator.toExpr(addr), translator.toExpr(data), portNum)
Expand Down
15 changes: 12 additions & 3 deletions src/main/scala/pipedsl/common/LockImplementation.scala
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
/* LockImplementation.scala */
package pipedsl.common

import pipedsl.codegen.bsv.BSVSyntax.BPack
import pipedsl.common.Errors.{MissingType, UnexpectedLockImpl}
import pipedsl.common.Locks.{General, LockGranularity, Specific}
import pipedsl.common.Syntax.Latency.{Combinational, Latency, Sequential}
import pipedsl.common.Syntax._
import pipedsl.codegen.bsv.BluespecInterfaces


object LockImplementation {
Expand All @@ -31,6 +33,7 @@ object LockImplementation {
private val dataType = TNamedType(Id("data"))
private val handleType = TNamedType(Id("handle"))
private val checkType = TNamedType(Id("checkHandle"))
private val maskType = TNamedType(Id("wmask"))
//Lock Object Method Names
private val canResName = "canRes"
private val canResReadName = canResName + "_r"
Expand Down Expand Up @@ -235,10 +238,10 @@ object LockImplementation {
}
}

def getWriteInfo(mem: Id, addr: Expr, inHandle: Option[Expr], data: Expr, portNum: Option[Int], isAtomic: Boolean): Option[MethodInfo] = {
def getWriteInfo(mem: Id, addr: Expr, inHandle: Option[Expr], data: Expr, writeMask: Option[Expr], portNum: Option[Int], isAtomic: Boolean): Option[MethodInfo] = {
val interface = getLockImplFromMemTyp(mem)
val (funTyp, latency) = getAccess(interface, Some(LockWrite), isAtomic).get
val args = getArgs(funTyp, Some(addr), inHandle, Some(data))
val args = getArgs(funTyp, Some(addr), inHandle, Some(data), writeMask)
val methodName = getAccessName(Some(LockWrite), isAtomic).v + toPortString(portNum)
Some(MethodInfo(methodName, latency != Combinational, args))
}
Expand Down Expand Up @@ -304,13 +307,14 @@ object LockImplementation {
e
}
private def getArgs(fun: TFun, addr: Option[Expr] = None,
handle: Option[Expr] = None, data: Option[Expr] = None): List[Expr] = {
handle: Option[Expr] = None, data: Option[Expr] = None, writeMask: Option[Expr] = None): List[Expr] = {
fun.args.foldLeft(List[Expr]())((l, argTyp) => {
argTyp match {
//TODO throw better exception if missing arg
case t: TNamedType if t == dataType => l :+ data.get
case t: TNamedType if t == addrType => l :+ addr.get
case t: TNamedType if t == handleType => l :+ extractHandle(handle.get)
case t: TNamedType if t == maskType && writeMask.isDefined => l :+ writeMask.get
case _ => l //should be unreachable TODO throw badly formatted type
}
})
Expand Down Expand Up @@ -430,6 +434,8 @@ object LockImplementation {
//LSQ doesn't need a separate lock id so use this to differentiate
def useUniqueLockId(): Boolean = true

def canSilentWrite(): Boolean = false

def getLockIdSize: Int = defaultLockHandleSize
def getChkIdSize(lidSize: Int): Option[Int] = None

Expand Down Expand Up @@ -492,6 +498,8 @@ object LockImplementation {
val parent = super.getType
TObject(queueLockName, List(),
parent.methods ++ Map(
Id(writeName) -> (TFun(List(addrType, dataType, maskType), TVoid()), Combinational),
Id(atomicAccessName) -> (TFun(List(addrType), TVoid()), Combinational),
Id(checkpointName) -> (TFun(List(), checkType), Sequential),
Id(rollbackName) -> (TFun(List(checkType), TVoid()), Sequential),
Id(abortName) -> (TFun(List(), TVoid()), Sequential)
Expand All @@ -507,6 +515,7 @@ object LockImplementation {

override def getModInstArgs(m: TMemType, szParams: List[Int]): List[Int] = List()

override def canSilentWrite(): Boolean = true
//Checkpoint id must equal the lock id size
override def getChkIdSize(lidSize: Int): Option[Int] = Some(lidSize)
}
Expand Down
2 changes: 1 addition & 1 deletion src/main/scala/pipedsl/common/Syntax.scala
Original file line number Diff line number Diff line change
Expand Up @@ -670,7 +670,7 @@ object Syntax {
}
case class IMemRecv(mem: Id, handle: EVar, data: Option[EVar]) extends InternalCommand with LockInfoAnnotation
//used for sequential memories that don't commit writes immediately but don't send a response
case class IMemWrite(mem: Id, addr: EVar, data: EVar,
case class IMemWrite(mem: Id, addr: EVar, data: EVar, writeMask: Option[Expr],
inHandle: Option[EVar], outHandle: Option[EVar], isAtomic: Boolean) extends InternalCommand with LockInfoAnnotation
case class ICheckLockOwned(mem: LockArg, inHandle: EVar, outHandle :EVar) extends InternalCommand with LockInfoAnnotation
case class IReserveLock(outHandle: EVar, mem: LockArg) extends InternalCommand with LockInfoAnnotation
Expand Down
9 changes: 7 additions & 2 deletions src/main/scala/pipedsl/common/Utilities.scala
Original file line number Diff line number Diff line change
Expand Up @@ -180,8 +180,13 @@ object Utilities {
Set()
})
case IMemRecv(_, handle, _) => Set(handle.id)
case IMemWrite(_, addr, data, inHandle, _, _) =>
Set(addr.id, data.id).union(inHandle.map(h => Set(h.id)).getOrElse(Set()))
case IMemWrite(_, addr, data, writeMask, inHandle, _, _) =>
Set(addr.id, data.id).union(inHandle.map(h => Set(h.id)).getOrElse(Set())) ++ (
if (writeMask.isDefined) {
getUsedVars(writeMask.get)
} else {
Set()
})
case IRecv(handle, _, _) => Set(handle.id)
case ISend(_, _, args) => args.map(a => a.id).toSet
case IReserveLock(_, larg) => larg.evar match {
Expand Down
14 changes: 10 additions & 4 deletions src/main/scala/pipedsl/passes/ConvertAsyncPass.scala
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ package pipedsl.passes
import pipedsl.common.Syntax._
import pipedsl.common.DAGSyntax.PStage
import pipedsl.common.Errors.{UnexpectedExpr, UnexpectedType}
import pipedsl.common.LockImplementation
import pipedsl.common.Utilities.flattenStageList
import pipedsl.passes.Passes.StagePass

Expand Down Expand Up @@ -77,12 +78,12 @@ class ConvertAsyncPass(modName: Id) extends StagePass[List[PStage]] {
recv.portNum = c.portNum
(send, recv)
case _ :TMemType =>
val write = IMemWrite(mem, index, data, inHandle, outHandle, isAtomic).setPos(e.pos)
val write = IMemWrite(mem, index, data, wm, inHandle, outHandle, isAtomic).setPos(e.pos)
write.memOpType = e.memOpType
write.granularity = e.granularity
write.portNum = c.portNum
(write, CEmpty())
case TLockedMemType(TMemType(_, _, _, Latency.Asynchronous, _, _),_, _) =>
case TLockedMemType(TMemType(_, _, _, Latency.Asynchronous, _, _),_, lock) if !lock.canSilentWrite() =>
val handle = freshMessage(mem)
val send = IMemSend(handle, writeMask = wm, mem, Some(data), index, inHandle, outHandle, isAtomic)
val recv = IMemRecv(mem, handle, None)
Expand All @@ -95,8 +96,13 @@ class ConvertAsyncPass(modName: Id) extends StagePass[List[PStage]] {
(send, recv)
//if the memory is sequential we don't use handle since it
//is assumed to complete at the end of the cycle
case TLockedMemType(_,_,_) =>
val write = IMemWrite(mem, index, data, inHandle, outHandle, isAtomic).setPos(e.pos)
case TLockedMemType(TMemType(_, _, _, lat, _, _),_, lock) =>
val newwm = wm match {
case _: Expr => wm
case _ if lat == Latency.Asynchronous => Some(EInt(1, 2, -1))
case _ => None
}
val write = IMemWrite(mem, index, data, newwm, inHandle, outHandle, isAtomic).setPos(e.pos)
write.memOpType = e.memOpType
write.granularity = e.granularity
write.portNum = c.portNum
Expand Down
8 changes: 5 additions & 3 deletions src/test/tests/exception/exn-recovery-spec.pdl
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// exn-recovery-spec.pdl
//Expect 5 Success, 1 Exception, 1 Success post recovery
exn-pipe cpu(pc :uint<16>)[acc :uint<4>[0]<c,s>(CheckpointQueue)] :uint<4> {
exn-pipe cpu(pc :uint<16>)[acc :uint<8>[0]<a,a>(CheckpointQueue)] :uint<4> {
spec_check();
start(acc);
reserve(acc);
Expand All @@ -12,7 +12,9 @@ exn-pipe cpu(pc :uint<16>)[acc :uint<4>[0]<c,s>(CheckpointQueue)] :uint<4> {
---
spec_check();
block(acc);
acc_val = acc[0];
acc_val <- acc[0];
---
spec_check();
acc[0] <- acc_val + 1;
---
spec_barrier();
Expand Down Expand Up @@ -53,7 +55,7 @@ except(arg: uint<4>):

circuit {
ti = memory(uint<8>, 16);
acc = register(uint<4>, 0);
acc = memory(uint<8>, 0);
locked = CheckpointQueue(acc);
c = new cpu[locked];
call c(u1<16>);
Expand Down
Loading

0 comments on commit 6cc3a76

Please sign in to comment.