Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Exn #71

Open
wants to merge 44 commits into
base: main
Choose a base branch
from
Open

Exn #71

Show file tree
Hide file tree
Changes from 30 commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
c31c456
basics
Mar 13, 2022
263fed8
commit
Mar 14, 2022
c11d649
tmp
Mar 17, 2022
5269a3e
add exceptions task description
Mar 17, 2022
28f0c60
Update exceptions.md
dz333 Mar 17, 2022
30953ef
start exn typechecking. currently working on typeinference
Mar 28, 2022
86409a8
type inference
Apr 4, 2022
b0ca5cd
type inference
Apr 4, 2022
d3d7bfc
add typechecking based on the rules we discussed
yy665 Apr 19, 2022
7840a73
fix some ast
yy665 Apr 19, 2022
4f5a9a5
type checking working for exceptions? only positively
May 2, 2022
8c8f56b
untested, but done?
May 5, 2022
c60610e
added useful code for generating abort calls
dz333 May 5, 2022
2431f4d
added a simple abort-able lock
dz333 May 5, 2022
64a4d86
testing for exceptions
May 9, 2022
efe940a
Merge branch 'exn' of github.com:apl-cornell/PDL into exn
May 9, 2022
f13e86a
yeet old code
May 9, 2022
1a1f94c
exn_translation
yy665 Jun 22, 2022
9fcf978
add testcase
yy665 Jun 22, 2022
bd4d886
updated this example to reflect a bug - BaseTypeChecker should check …
dz333 Jun 22, 2022
16c8893
updated example to do a write
dz333 Jun 22, 2022
6f1b359
fixed some bugs in pretty printer, and made port checker pass run on …
dz333 Jun 23, 2022
f465d0d
partially resolved comments, enables exn_args and kill_rules
yy665 Jul 7, 2022
730997e
debugs and change kill rule impl
yy665 Jul 12, 2022
96a465b
added a spectable.clear() function that resets it to initial state
dz333 Jul 12, 2022
dc84843
added a clear method for our async mems that clears their request queues
dz333 Jul 12, 2022
68245bf
finish problem with old ModLock instantiations
dz333 Jul 12, 2022
7626eeb
tests passed
yy665 Jul 30, 2022
60c58bb
tests and fixes
yy665 Nov 29, 2022
7ac58af
Merge pull request #72 from yy665/exn
yy665 Nov 29, 2022
7fdfe43
resolve all comments and fix bugs, add ehr
yy665 Mar 1, 2023
d562687
Merge pull request #74 from yy665/exn
yy665 Mar 1, 2023
d9e204c
fix tests
yy665 Mar 1, 2023
3ea3e34
Merge pull request #75 from yy665/exn
yy665 Mar 1, 2023
b386fb4
rewrite impl with stgclear
yy665 Apr 6, 2023
635d92d
fix sq
yy665 Apr 6, 2023
24e6edd
fix
yy665 Apr 6, 2023
15231cd
Merge pull request #77 from yy665/exn
yy665 Apr 6, 2023
7935064
Update scala.yml
dz333 Apr 7, 2023
737bc6d
further exn change
yy665 Aug 8, 2023
ef2f70f
fix problem wrt iverilog version
yy665 Oct 11, 2023
5176c08
some fixes and testcases
yy665 Oct 16, 2023
6cc3a76
fix chkp + some ad hoc stuff
yy665 Oct 25, 2023
1b0f426
Merge pull request #78 from yy665/exn
yy665 Oct 25, 2023
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
104 changes: 63 additions & 41 deletions bscRuntime/memories/Locks.bsv
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import FIFOF :: *;
import Ehr :: *;
import Vector :: *;
import ConfigReg :: *;
import GetPut :: *;
export LockId(..);
export QueueLock(..);
export CheckpointQueueLock(..);
Expand All @@ -25,14 +26,16 @@ interface QueueLock#(type id);
method Bool canRes1();
endinterface

interface CheckpointQueueLock#(type id, type cid);
interface CheckpointQueueLock#(type id, type cid, type winfo);
method ActionValue#(id) res1();
method Bool owns1(id i);
method Action rel1(id i);
method Bool isEmpty();
method Bool canRes1();
method Action write(winfo wd);
method ActionValue#(cid) checkpoint();
method Action rollback(cid id, Bool doRoll, Bool doRel);
method Action abort();
endinterface

interface AddrLock#(type id, type addr, numeric type size);
Expand All @@ -47,54 +50,55 @@ module mkQueueLock(QueueLock#(LockId#(d)));

Reg#(LockId#(d)) nextId <- mkReg(0);
FIFOF#(LockId#(d)) held <- mkSizedFIFOF(valueOf(d));

Reg#(LockId#(d)) cnt <- mkReg(0);

Bool lockFree = !held.notEmpty;
LockId#(d) owner = held.first;

method Bool isEmpty();
return lockFree;
endmethod

method Bool canRes1();
return held.notFull;
endmethod

//Returns True if thread `tid` already owns the lock
method Bool owns1(LockId#(d) tid);
return owner == tid;
endmethod

//Releases the lock iff thread `tid` owns it already
method Action rel1(LockId#(d) tid);
if (owner == tid)
begin
held.deq();
end
endmethod

//Reserves the lock and returns the associated id
method ActionValue#(LockId#(d)) res1();
held.enq(nextId);
nextId <= nextId + 1;
cnt <= cnt + 1;
return nextId;
endmethod

endmodule

module mkCountingLock(QueueLock#(LockId#(d)));

Ehr#(2, LockId#(d)) nextId <- mkEhr(0);
Ehr#(2, LockId#(d)) nextId <- mkEhr(0);
Reg#(LockId#(d)) owner <- mkReg(0);
Reg#(Bool) empty <- mkReg(True);

Bool full = !empty && nextId[0] == owner;

RWire#(Bool) doRes <- mkRWire();
RWire#(LockId#(d)) doRel <- mkRWire();

//i think i need to add a doAbrt wire here

(*fire_when_enabled*)
rule updateEmpty;
let res = fromMaybe(False, doRes.wget());
Expand All @@ -108,79 +112,97 @@ module mkCountingLock(QueueLock#(LockId#(d)));
method Bool isEmpty();
return empty;
endmethod

method Bool canRes1();
return !full;
endmethod

//Returns True if thread `tid` already owns the lock
method Bool owns1(LockId#(d) tid);
return owner == tid;
endmethod

//Releases the lock
method Action rel1(LockId#(d) tid);
owner <= owner + 1;
doRel.wset(owner + 1);
endmethod

//Reserves the lock and returns the associated id
method ActionValue#(LockId#(d)) res1();
nextId[0] <= nextId[0] + 1;
doRes.wset(True);
return nextId[0];
endmethod

endmodule

module mkCheckpointQueueLock(CheckpointQueueLock#(LockId#(d), LockId#(d)));
module mkCheckpointQueueLock(Put#(winfo) mem, CheckpointQueueLock#(LockId#(d), LockId#(d), winfo) _unused_)
provisos(Bits#(winfo,wsz));

Ehr#(2, LockId#(d)) nextId <- mkEhr(0);
Reg#(LockId#(d)) owner <- mkReg(0);
Reg#(Bool) empty <- mkReg(True);


Reg#(Maybe#(winfo)) wdata <- mkReg(tagged Invalid);
RWire#(Bool) doRes <- mkRWire();
RWire#(LockId#(d)) doRel <- mkRWire();

//for when you're doing not rollback
(*fire_when_enabled*)
rule updateEmpty;
let res = fromMaybe(False, doRes.wget());
if (res &&& doRel.wget() matches tagged Invalid) empty <= False;
if (!res &&& doRel.wget() matches tagged Valid.nextOwner) empty <= nextOwner == nextId[1];
endrule

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

method Bool isEmpty();
return empty;
endmethod

method Bool canRes1();
return empty || nextId[0] != owner;
endmethod

//Returns True if thread `tid` already owns the lock
method Bool owns1(LockId#(d) tid);
return owner == tid;
endmethod


//store the write data
method Action write(winfo wd);
wdata <= tagged Valid wd;
endmethod

//Releases the lock, assume `tid` owns it
method Action rel1(LockId#(d) tid);
owner <= owner + 1; //assign next owner
doRel.wset(owner + 1);
if (wdata matches tagged Valid.wd) begin
mem.put(wd);
wdata <= tagged Invalid;
end
endmethod

//Reserves the lock and returns the associated id
method ActionValue#(LockId#(d)) res1();
nextId[0] <= nextId[0] + 1;
doRes.wset(True);
return nextId[0];
endmethod

method ActionValue#(LockId#(d)) checkpoint();
//return point after this cycle's reservations
return nextId[1];
endmethod

method Action rollback(LockId#(d) i, Bool doRoll, Bool doRollRel);
//rollback release is noop
//conflicts with other update rules - cannot res/rel and rollback
Expand All @@ -189,15 +211,15 @@ module mkCheckpointQueueLock(CheckpointQueueLock#(LockId#(d), LockId#(d)));
nextId[0] <= i;
empty <= i == owner; //if i is Owner, then this is actually empty after rollback
end
endmethod
endmethod

endmodule

typedef UInt#(TLog#(n)) LockIdx#(numeric type n);

module mkFAAddrLock(AddrLock#(LockId#(d), addr, numlocks)) provisos(Bits#(addr, szAddr), Eq#(addr));


Vector#(numlocks, QueueLock#(LockId#(d))) lockVec <- replicateM( mkCountingLock() );
Vector#(numlocks, Reg#(Maybe#(addr))) entryVec <- replicateM( mkConfigReg(tagged Invalid) );
//Signal that a reservation used an already-allocated lock this cycle
Expand All @@ -206,18 +228,18 @@ module mkFAAddrLock(AddrLock#(LockId#(d), addr, numlocks)) provisos(Bits#(addr,

//Allow each lock entry to be freed once it's no longer used,
//but tagged as valid, *AND* was there isn't a reservation this cycle to it.
for (Integer i = 0; i < valueOf(numlocks); i = i + 1) begin
for (Integer i = 0; i < valueOf(numlocks); i = i + 1) begin
rule freelock(lockVec[i].isEmpty && isValid(entryVec[i]) && !isValid(resVec[i].wget()));
entryVec[i] <= tagged Invalid;
endrule
end

//returns the index of the lock associated with loc
//returns invalid if no lock is associated with loc
function Maybe#(LockIdx#(numlocks)) getLockIndex(addr loc);
Maybe#(LockIdx#(numlocks)) result = tagged Invalid;
for (Integer idx = 0; idx < valueOf(numlocks); idx = idx + 1)
if (result matches tagged Invalid &&&
if (result matches tagged Invalid &&&
entryVec[idx] matches tagged Valid.t &&& t == loc)
result = tagged Valid fromInteger(idx);
return result;
Expand All @@ -229,30 +251,30 @@ module mkFAAddrLock(AddrLock#(LockId#(d), addr, numlocks)) provisos(Bits#(addr,
else
return tagged Invalid;
endfunction

//gets the first index where an address is not assigned to the lock OR the lock is empty
//returns invalid if all locks are in use
function Maybe#(LockIdx#(numlocks)) getFreeLock();
Maybe#(LockIdx#(numlocks)) result = tagged Invalid;
for (Integer idx = 0; idx < valueOf(numlocks); idx = idx + 1)
if (result matches tagged Invalid &&&
entryVec[idx] matches tagged Invalid)
result = tagged Valid fromInteger(idx);
result = tagged Valid fromInteger(idx);
return result;
endfunction

//returns true iff there is a lock location free
function Bool isFreeLock();
return isValid(getFreeLock());
endfunction
endfunction

//true if lock is associated w/ addr or there is a location free
method Bool canRes1(addr loc);
let lockAddr = getLock(loc);
if (lockAddr matches tagged Valid.l) return True;
else return isFreeLock();
endmethod

//true if lock associated w/ address is empty or there is a lock lockation free
method Bool isEmpty(addr loc);
Maybe#(QueueLock#(LockId#(d))) addrLock = getLock(loc);
Expand All @@ -275,7 +297,7 @@ module mkFAAddrLock(AddrLock#(LockId#(d), addr, numlocks)) provisos(Bits#(addr,
//free then this location is acquirable
return hasFree;
endmethod

method Action rel1(LockId#(d) tid, addr loc);
Maybe#(LockIdx#(numlocks)) lockIdx = getLockIndex(loc);
if (lockIdx matches tagged Valid.idx)
Expand All @@ -286,7 +308,7 @@ module mkFAAddrLock(AddrLock#(LockId#(d), addr, numlocks)) provisos(Bits#(addr,
end
//else no lock is associated with loc, do nothing
endmethod

method ActionValue#(LockId#(d)) res1(addr loc);
Maybe#(LockIdx#(numlocks)) lockIdx = getLockIndex(loc);
if (lockIdx matches tagged Valid.idx)
Expand All @@ -312,7 +334,7 @@ module mkFAAddrLock(AddrLock#(LockId#(d), addr, numlocks)) provisos(Bits#(addr,
endmodule: mkFAAddrLock

module mkDMAddrLock(AddrLock#(LockId#(d), addr, unused)) provisos(PrimIndex#(addr, szAddr));

Vector#(TExp#(szAddr), QueueLock#(LockId#(d))) lockVec <- replicateM( mkCountingLock() );

method Bool isEmpty(addr loc);
Expand All @@ -322,20 +344,20 @@ module mkDMAddrLock(AddrLock#(LockId#(d), addr, unused)) provisos(PrimIndex#(add
method Bool owns1(LockId#(d) tid, addr loc);
return lockVec[loc].owns1(tid);
endmethod

method Bool canRes1(addr loc);
return True;
endmethod

method Action rel1(LockId#(d) tid, addr loc);
lockVec[loc].rel1(tid);
endmethod

method ActionValue#(LockId#(d)) res1(addr loc);
let id <- lockVec[loc].res1();
return id;
endmethod

endmodule: mkDMAddrLock

endpackage
Loading