seemingly reasonable stopping point

This commit is contained in:
Yehowshua Immanuel 2025-04-02 02:09:41 -04:00
parent 6247ae3b70
commit d436209f54
2 changed files with 48 additions and 72 deletions

View file

@ -5,40 +5,41 @@ package TagEngine(
import Vector import Vector
import Util import Util
import FIFO
import FIFOF
#define UIntLog2N(n) (UInt (TLog n)) #define UIntLog2N(n) (UInt (TLog n))
interface (TagEngine :: # -> *) numTags = interface (TagEngine :: # -> *) numTags =
requestTag :: ActionValue (Maybe UIntLog2N(numTags)) requestTag :: ActionValue UIntLog2N(numTags)
retireTag :: UIntLog2N(numTags) -> ActionValue BasicResult retireTag :: UIntLog2N(numTags) -> Action
-- The tag engine returns a tag that is unique for the duration of -- The tag engine returns a tag that is unique for the duration of
-- the lifetime of the tag. Useful when you need to tag transactions -- the lifetime of the tag. Useful when you need to tag transactions
-- on a bus for example. -- on a bus for example.
-- This implementation is stack based. -- This implementation is FIFO based.
mkTagEngine :: Module (TagEngine numTags) mkTagEngine :: Module (TagEngine numTags)
mkTagEngine = mkTagEngine =
do do
let reifiedNumTags = fromInteger |> valueOf numTags let reifiedNumTags = fromInteger |> valueOf numTags
freeStackVec :: Vector numTags (Reg UIntLog2N(numTags))
freeStackVec <- mapM (\i -> mkReg |> fromInteger i) genVector
inUseVec :: Vector numTags (Reg Bool) inUseVec :: Vector numTags (Reg Bool)
inUseVec <- replicateM |> mkReg False inUseVec <- replicateM |> mkReg False
stackPtr :: (Reg (Maybe(UIntLog2N(numTags)))) -- Since Bluespec doesn't allow us to initialize FIFOs with values at
stackPtr <- mkReg |> Just |> reifiedNumTags - 1 -- 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
-- to TagEngine where `n := numTags`.
resetTagCounter :: (Reg (Maybe UIntLog2N(numTags)))
resetTagCounter <- mkReg |> Just |> reifiedNumTags - 1
methodRequestTagCalled :: PulseWire retireQueue :: FIFOF UIntLog2N(numTags)
methodRequestTagCalled <- mkPulseWire retireQueue <- mkSizedFIFOF reifiedNumTags
methodRetireTagCalledValid :: RWire UIntLog2N(numTags) freeQueue :: FIFOF UIntLog2N(numTags)
methodRetireTagCalledValid <- mkUnsafeRWire freeQueue <- mkSizedFIFOF reifiedNumTags
-- computedTagResult :: BypassWire (Maybe UIntLog2N(numTags))
-- methodRetireTagCalledValid <- mkBypassWire
debugOnce <- mkReg True debugOnce <- mkReg True
@ -46,71 +47,46 @@ mkTagEngine =
rules rules
"display": when (debugOnce == True) ==> "display": when (debugOnce == True) ==>
do do
$display "freeStackVec : " (fshow |> readVReg freeStackVec)
$display "inUseVec : " (fshow |> readVReg inUseVec) $display "inUseVec : " (fshow |> readVReg inUseVec)
$display "stackPtr : " (fshow stackPtr)
debugOnce := False debugOnce := False
"update stack pointer": when True ==> -- The "retire_tags" rule can't fire when the `requestTag` method is called.
-- In practice, this is Ok since:
-- 1. the `requestTag` method should take priority over the "retire_tags" rule
-- 2. the `requestTag` method handles the case where there are some tags to retire.
"retire_tags": when True ==>
do do
stackPtr := let tag = retireQueue.first
case (methodRequestTagCalled, methodRetireTagCalledValid.wget) of $display "firing retire_tags" (fshow tag)
(True, Just _) -> stackPtr retireQueue.deq
(True, Nothing) -> freeQueue.enq tag
case stackPtr of (select inUseVec tag) := False
Just 0 -> Nothing
Just sampledStackPtr -> Just |> sampledStackPtr - 1
Nothing -> Nothing
(False, Just _) ->
case stackPtr of
Just sampledStackPtr -> Just |> sampledStackPtr + 1
Nothing -> Nothing
(False, Nothing) -> stackPtr
"update free stack": when True ==>
do
case (methodRequestTagCalled, methodRetireTagCalledValid.wget) of
(True, Just _) -> do action {}
(True, Nothing) -> do action {}
(False, Just tag) -> do
case stackPtr of
Just sampledStackPtr -> do
(select freeStackVec (sampledStackPtr + 1)) := tag
Nothing -> do
(select freeStackVec 0) := tag
(False, Nothing) -> do action {}
"update in use": when True ==>
do
case (methodRequestTagCalled, methodRetireTagCalledValid.wget) of
(True, Just _) -> do action {}
(True, Nothing) ->
case stackPtr of
Just sampledStackPtr -> do
(select inUseVec sampledStackPtr) := True
Nothing -> do action {}
(False, Just tag) -> do
(select inUseVec tag) := False
(False, Nothing) -> do action {}
return $ return $
interface TagEngine interface TagEngine
requestTag :: ActionValue (Maybe UIntLog2N(numTags)) requestTag :: ActionValue UIntLog2N(numTags)
requestTag = requestTag =
do do
methodRequestTagCalled.send case resetTagCounter of
case methodRetireTagCalledValid.wget of Just 0 -> do
resetTagCounter := Nothing
(select inUseVec 0) := True
return 0
Just tag -> do Just tag -> do
return |> Just tag resetTagCounter := Just |> tag - 1
(select inUseVec tag) := True
return tag
Nothing -> do Nothing -> do
return |> let tag = freeQueue.first
case stackPtr of freeQueue.deq
Just sampledStackPtr -> return tag
Just |> readReg (select freeStackVec sampledStackPtr)
Nothing -> Nothing
retireTag :: UIntLog2N(numTags) -> ActionValue BasicResult -- `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.
retireTag :: UIntLog2N(numTags) -> Action
retireTag tag = retireTag tag =
do do
let let
@ -118,7 +94,6 @@ mkTagEngine =
tagInUse = readReg (select inUseVec tag) tagInUse = readReg (select inUseVec tag)
if (tagValid && tagInUse) if (tagValid && tagInUse)
then do then do
methodRetireTagCalledValid.wset tag retireQueue.enq tag
return Success
else do else do
return Failure action {}

View file

@ -44,6 +44,7 @@ mkTagEngineTester = do
|> do requestTagAction |> do requestTagAction
|> do retireTagAction 1 |> do retireTagAction 1
|> do requestTagAction |> do requestTagAction
|> do $finish
addRules $ addRules $
rules rules