handled tag engine edge case
This commit is contained in:
parent
271148e538
commit
ca59e6eaec
2 changed files with 57 additions and 23 deletions
|
@ -7,6 +7,7 @@ import Vector
|
|||
import Util
|
||||
import FIFO
|
||||
import FIFOF
|
||||
import SpecialFIFOs
|
||||
|
||||
#define UIntLog2N(n) (UInt (TLog n))
|
||||
|
||||
|
@ -23,7 +24,7 @@ mkTagEngine =
|
|||
do
|
||||
let reifiedNumTags = fromInteger |> valueOf numTags
|
||||
|
||||
-- we really only use tagUsageTracker after emptying out our
|
||||
-- we really only use tagUsageTracker after emptying out our
|
||||
-- `initialTagDistributor` buffer
|
||||
tagUsageTracker :: Vector numTags (Reg Bool)
|
||||
tagUsageTracker <- replicateM |> mkReg False
|
||||
|
@ -32,13 +33,19 @@ mkTagEngine =
|
|||
-- reset, we can pretend as if the buffer within our tagFIFO is populated
|
||||
-- with sequentially incrementing values(starting from 0) on reset
|
||||
-- by having our tag engine effectively return the value of a decrementing
|
||||
-- counter initialized to (numTags - 1) for the first n tag requests made
|
||||
-- counter initialized to (numTags - 1) for the first n tag requests made
|
||||
-- to TagEngine where `n := numTags`.
|
||||
initialTagDistributor :: (Reg (Maybe UIntLog2N(numTags)))
|
||||
initialTagDistributor <- mkReg |> Just |> reifiedNumTags - 1
|
||||
|
||||
retireTag :: Wire UIntLog2N(numTags)
|
||||
retireTag <- mkWire
|
||||
validatedTagToRetire :: FIFO UIntLog2N(numTags)
|
||||
validatedTagToRetire <- mkBypassFIFO
|
||||
|
||||
updateUsageRetireTag :: RWire UIntLog2N(numTags)
|
||||
updateUsageRetireTag <- mkRWire
|
||||
|
||||
updateUsageRequestTag :: RWire UIntLog2N(numTags)
|
||||
updateUsageRequestTag <- mkRWire
|
||||
|
||||
tagFIFO :: FIFOF UIntLog2N(numTags)
|
||||
tagFIFO <- mkSizedFIFOF reifiedNumTags
|
||||
|
@ -51,12 +58,39 @@ mkTagEngine =
|
|||
do
|
||||
$display "tagUsageTracker : " (fshow |> readVReg tagUsageTracker)
|
||||
debugOnce := False
|
||||
|
||||
|
||||
"update_usage_just_retire": when
|
||||
Just tag <- updateUsageRetireTag.wget,
|
||||
Nothing <- updateUsageRequestTag.wget ==>
|
||||
do
|
||||
$display $time " tagUsageTracker after update retire: " (fshow |> readVReg tagUsageTracker)
|
||||
(select tagUsageTracker tag) := False
|
||||
|
||||
"update_usage_just_request": when
|
||||
Nothing <- updateUsageRetireTag.wget,
|
||||
Just tag <- updateUsageRequestTag.wget ==>
|
||||
do
|
||||
$display $time " tagUsageTracker after update request: " (fshow |> readVReg tagUsageTracker)
|
||||
(select tagUsageTracker tag) := True
|
||||
|
||||
"update_usage_request_and_retire": when
|
||||
Just retireTag <- updateUsageRetireTag.wget,
|
||||
Just requestTag <- updateUsageRequestTag.wget ==>
|
||||
do
|
||||
$display $time " tagUsageTracker after update request and retire: " (fshow |> readVReg tagUsageTracker)
|
||||
let
|
||||
tagUsageTrackerInner = readVReg tagUsageTracker
|
||||
tagUsageTracker' = update tagUsageTrackerInner requestTag True
|
||||
tagUsageTracker'' = update tagUsageTracker' retireTag False
|
||||
writeVReg tagUsageTracker tagUsageTracker''
|
||||
|
||||
"retire_tags": when True ==>
|
||||
do
|
||||
$display "firing retire_tags" (fshow retireTag)
|
||||
tagFIFO.enq retireTag
|
||||
(select tagUsageTracker retireTag) := False
|
||||
let tagToRetire = validatedTagToRetire.first
|
||||
$display "firing retire_tags" (fshow tagToRetire)
|
||||
validatedTagToRetire.deq
|
||||
tagFIFO.enq tagToRetire
|
||||
updateUsageRetireTag.wset tagToRetire
|
||||
|
||||
return $
|
||||
interface TagEngine
|
||||
|
@ -67,18 +101,19 @@ mkTagEngine =
|
|||
case initialTagDistributor of
|
||||
Just 0 -> do
|
||||
initialTagDistributor := Nothing
|
||||
(select tagUsageTracker 0) := True
|
||||
updateUsageRequestTag.wset 0
|
||||
return 0
|
||||
Just tag -> do
|
||||
initialTagDistributor := Just |> tag - 1
|
||||
(select tagUsageTracker tag) := True
|
||||
updateUsageRequestTag.wset tag
|
||||
return tag
|
||||
Nothing -> do
|
||||
let tag = tagFIFO.first
|
||||
tagFIFO.deq
|
||||
updateUsageRequestTag.wset tag
|
||||
return tag
|
||||
|
||||
-- `retireTag` isn't guarded on tag validity(this would break Bluespec's safety model)
|
||||
-- `retireTag` isn't guarded on tag validity(this would break Bluespec's safety model)
|
||||
-- so it is advisable that the caller of `retireTag` only attempt to retire valid tags.
|
||||
-- Internally, the tagEngine will keep a correct and consistent state since TagEngine
|
||||
-- validates tags before attempting to retire them.
|
||||
|
@ -90,6 +125,6 @@ mkTagEngine =
|
|||
tagInUse = readReg (select tagUsageTracker tag)
|
||||
if (tagValid && tagInUse)
|
||||
then do
|
||||
retireTag := tag
|
||||
validatedTagToRetire.enq tag
|
||||
else do
|
||||
action {}
|
||||
|
|
Reference in a new issue