From 6e3b3e91789c924a723133fcf73f1ed933aaf343 Mon Sep 17 00:00:00 2001 From: Yehowshua Immanuel Date: Mon, 24 Mar 2025 22:46:42 -0400 Subject: [PATCH 01/12] Preliminary cleaning before repairing TagEngine * clean up state machine in Top * `requestTag` method now emits Maybe type * put more thought into comments around asynchronous bus --- bs/BusTypes.bs | 6 ++-- bs/TagEngine.bs | 30 ++++++++++++++++++-- bs/Top.bs | 74 ++++++++++++++++++++++++------------------------- 3 files changed, 67 insertions(+), 43 deletions(-) diff --git a/bs/BusTypes.bs b/bs/BusTypes.bs index d633ee6..99d0fb4 100644 --- a/bs/BusTypes.bs +++ b/bs/BusTypes.bs @@ -57,9 +57,9 @@ interface BusMaster = -- This has implications about for the implementor of BusMaster, namely, that it -- should hold its request until it's request method gets called. request :: BusRequest - -- From the masters's perspective, the response should not be called until - -- the client is ready to accept the response. In other words, response - -- should be guarded by the client. + -- From the masters's perspective, the response should not be called by the + -- arbiter until the master is ready to accept the response. In other words, + -- response should be guarded by the client. response :: BusResponse -> Action type Token = UInt 5 diff --git a/bs/TagEngine.bs b/bs/TagEngine.bs index df60839..4d67898 100644 --- a/bs/TagEngine.bs +++ b/bs/TagEngine.bs @@ -9,7 +9,7 @@ import Util #define UIntLog2N(n) (UInt (TLog n)) interface (TagEngine :: # -> *) numTags = - requestTag :: ActionValue UIntLog2N(numTags) + requestTag :: ActionValue (Maybe UIntLog2N(numTags)) retireTag :: UIntLog2N(numTags) -> ActionValue BasicResult -- The tag engine returns a tag that is unique for the duration of @@ -19,6 +19,7 @@ interface (TagEngine :: # -> *) numTags = mkTagEngine :: Module (TagEngine numTags) mkTagEngine = do + let reifiedNumTags = fromInteger |> valueOf numTags freeStackVec :: Vector numTags (Reg UIntLog2N(numTags)) @@ -30,8 +31,20 @@ mkTagEngine = stackPtr :: (Reg (Maybe(UIntLog2N(numTags)))) stackPtr <- mkReg |> Just |> reifiedNumTags - 1 + methodRequestTagCalled :: PulseWire + methodRequestTagCalled <- mkPulseWire + + + methodRetireTagCalled :: PulseWire + methodRetireTagCalled <- mkPulseWire + + tagResponse :: RWire UIntLog2N(numTags) + tagResponse <- mkRWireSBR + debugOnce <- mkReg True + tt :: Reg Bool <- mkReg False + addRules $ rules "display": when (debugOnce == True) ==> @@ -40,20 +53,30 @@ mkTagEngine = $display "inUseVec : " (fshow |> readVReg inUseVec) $display "stackPtr : " (fshow stackPtr) debugOnce := False + <+> + rules + when (methodRequestTagCalled && methodRetireTagCalled) ==> + do + $display "ho ho ho" + -- let + -- nextStackPtr = + -- case of (methodRequestTagCalled, methodRetireTagCalled) of + -- (True, True) -> counter <- mkReg(0 :: UIntLog2N(numTags)) return $ interface TagEngine - requestTag :: ActionValue UIntLog2N(numTags) + requestTag :: ActionValue (Maybe UIntLog2N(numTags)) requestTag = do + methodRequestTagCalled.send stackPtr := if sampledStackPtr == 0 then Nothing else Just |> sampledStackPtr - 1 (select inUseVec sampledStackPtr) := True - return |> readReg (select freeStackVec sampledStackPtr) + return |> Just |> readReg (select freeStackVec sampledStackPtr) when Just sampledStackPtr <- stackPtr @@ -64,6 +87,7 @@ mkTagEngine = retireTag :: UIntLog2N(numTags) -> ActionValue BasicResult retireTag tag = do + methodRetireTagCalled.send let tagValid = tag < reifiedNumTags tagInUse = readReg (select inUseVec tag) diff --git a/bs/Top.bs b/bs/Top.bs index 59344b2..023fce2 100644 --- a/bs/Top.bs +++ b/bs/Top.bs @@ -108,43 +108,43 @@ mkSim = do core :: Core FCLK <- mkCore; s :: ActionSeq - s <- actionSeq - $ do - $display "got tag : " tagEngine.requestTag - |> do - $display "got tag : " tagEngine.requestTag - |> do - $display "got tag : " tagEngine.requestTag - |> do - res <- tagEngine.retireTag 3 - $display "retiring tag : 3 " (fshow res) - action {} - |> do - $display "got tag : " tagEngine.requestTag - |> do - $display "got tag : " tagEngine.requestTag - |> do - res <- tagEngine.retireTag 4 - $display "retiring tag : 4 " (fshow res) - action {} - |> do - res <- tagEngine.retireTag 4 - $display "retiring tag : 4 " (fshow res) - action {} - |> do - res <- tagEngine.retireTag 0 - $display "retiring tag : 0 " (fshow res) - action {} - |> do - $display "got tag : " tagEngine.requestTag - |> do - $display "got tag : " tagEngine.requestTag - |> do - res <- tagEngine.retireTag 1 - $display "retiring tag : 1 " (fshow res) - action {} - |> do - $display "got tag : " tagEngine.requestTag + s <- + let + requestTagAction :: Action + requestTagAction = + do + tag <- tagEngine.requestTag + $display "got tag : " (fshow tag) + in + actionSeq $ + do requestTagAction + |> do requestTagAction + |> do requestTagAction + |> do + res <- tagEngine.retireTag 3 + $display "retiring tag : 3 " (fshow res) + action {} + |> do requestTagAction + |> do requestTagAction + |> do + res <- tagEngine.retireTag 4 + $display "retiring tag : 4 " (fshow res) + action {} + |> do + res <- tagEngine.retireTag 4 + $display "retiring tag : 4 " (fshow res) + action {} + |> do + res <- tagEngine.retireTag 0 + $display "retiring tag : 0 " (fshow res) + action {} + |> do requestTagAction + |> do requestTagAction + |> do + res <- tagEngine.retireTag 1 + $display "retiring tag : 1 " (fshow res) + action {} + |> do requestTagAction addRules $ rules -- 2.48.1 From 5588fafebdf5ce1e149fd3daef6249e9b0dad98d Mon Sep 17 00:00:00 2001 From: Yehowshua Immanuel Date: Mon, 24 Mar 2025 23:23:39 -0400 Subject: [PATCH 02/12] refactor into standalone TagEngineTester --- Makefile | 2 +- bs/Tests/TagEngineTester.bs | 48 +++++++++++++++++++++++++++++++++++++ bs/Top.bs | 47 +++--------------------------------- 3 files changed, 52 insertions(+), 45 deletions(-) create mode 100644 bs/Tests/TagEngineTester.bs diff --git a/Makefile b/Makefile index 52863b1..7579e84 100644 --- a/Makefile +++ b/Makefile @@ -61,7 +61,7 @@ $(BDPI_OBJ): $(BDPI_SRC) BSC_LINK_FLAGS += -keep-fires -BSC_PATHS = -p bs/:bsv/:+ +BSC_PATHS = -p bs/:bs/Tests/:bsv/:+ .PHONY: help help: diff --git a/bs/Tests/TagEngineTester.bs b/bs/Tests/TagEngineTester.bs new file mode 100644 index 0000000..9cbab60 --- /dev/null +++ b/bs/Tests/TagEngineTester.bs @@ -0,0 +1,48 @@ +package TagEngineTester(mkTagEngineTester) where + +import TagEngine +import ActionSeq + +mkTagEngineTester :: Module Empty +mkTagEngineTester = do + tagEngine :: TagEngine 5 <- mkTagEngine + count :: Reg (UInt 4) <- mkReg 0; + + s :: ActionSeq + s <- + let + requestTagAction :: Action + requestTagAction = + do + tag <- tagEngine.requestTag + $display "got tag : " (fshow tag) + + retireTagAction :: UInt 3 -> Action + retireTagAction tag = + do + res <- tagEngine.retireTag tag + $display "retiring tag : " (fshow tag) " " (fshow res) + action {} + + in + actionSeq $ + do requestTagAction + |> do requestTagAction + |> do requestTagAction + |> do retireTagAction 3 + |> do requestTagAction + |> do requestTagAction + |> do retireTagAction 4 + |> do retireTagAction 4 + |> do retireTagAction 0 + |> do requestTagAction + |> do requestTagAction + |> do retireTagAction 1 + |> do requestTagAction + + addRules $ + rules + "testIncrement": when (count < 10) ==> + do + count := count + 1 + s.start \ No newline at end of file diff --git a/bs/Top.bs b/bs/Top.bs index 023fce2..5541bf6 100644 --- a/bs/Top.bs +++ b/bs/Top.bs @@ -10,6 +10,8 @@ import TagEngine import List import ActionSeq +import TagEngineTester + type FCLK = 25000000 type BAUD = 9600 @@ -102,56 +104,13 @@ mkSim :: Module Empty mkSim = do let cfg :: BRAM_Configure = defaultValue - tagEngine :: TagEngine 5 <- mkTagEngine + tagEngineTester :: Empty <- mkTagEngineTester count :: Reg (UInt 4) <- mkReg 0; initCFunctions :: Reg Bool <- mkReg False; core :: Core FCLK <- mkCore; - s :: ActionSeq - s <- - let - requestTagAction :: Action - requestTagAction = - do - tag <- tagEngine.requestTag - $display "got tag : " (fshow tag) - in - actionSeq $ - do requestTagAction - |> do requestTagAction - |> do requestTagAction - |> do - res <- tagEngine.retireTag 3 - $display "retiring tag : 3 " (fshow res) - action {} - |> do requestTagAction - |> do requestTagAction - |> do - res <- tagEngine.retireTag 4 - $display "retiring tag : 4 " (fshow res) - action {} - |> do - res <- tagEngine.retireTag 4 - $display "retiring tag : 4 " (fshow res) - action {} - |> do - res <- tagEngine.retireTag 0 - $display "retiring tag : 0 " (fshow res) - action {} - |> do requestTagAction - |> do requestTagAction - |> do - res <- tagEngine.retireTag 1 - $display "retiring tag : 1 " (fshow res) - action {} - |> do requestTagAction - addRules $ rules - "testIncrement": when (count < 10) ==> - do - count := count + 1 - s.start "initCFunctionsOnce": when not initCFunctions ==> do initTerminal -- 2.48.1 From ed8e0b8337539e4de4fab80883c381bf18da2a1d Mon Sep 17 00:00:00 2001 From: Yehowshua Immanuel Date: Tue, 25 Mar 2025 01:15:49 -0400 Subject: [PATCH 03/12] tag engine now allows from simultaneous retire and request - but had to use unsafe --- bs/TagEngine.bs | 83 +++++++++++++++++++++++-------------- bs/Tests/TagEngineTester.bs | 13 ++++-- 2 files changed, 62 insertions(+), 34 deletions(-) diff --git a/bs/TagEngine.bs b/bs/TagEngine.bs index 4d67898..134e2c8 100644 --- a/bs/TagEngine.bs +++ b/bs/TagEngine.bs @@ -34,12 +34,8 @@ mkTagEngine = methodRequestTagCalled :: PulseWire methodRequestTagCalled <- mkPulseWire - - methodRetireTagCalled :: PulseWire - methodRetireTagCalled <- mkPulseWire - - tagResponse :: RWire UIntLog2N(numTags) - tagResponse <- mkRWireSBR + methodRetireTagCalledValid :: RWire UIntLog2N(numTags) + methodRetireTagCalledValid <- mkUnsafeRWire debugOnce <- mkReg True @@ -53,15 +49,48 @@ mkTagEngine = $display "inUseVec : " (fshow |> readVReg inUseVec) $display "stackPtr : " (fshow stackPtr) debugOnce := False - <+> - rules - when (methodRequestTagCalled && methodRetireTagCalled) ==> + + "update stack pointer": when True ==> do - $display "ho ho ho" - -- let - -- nextStackPtr = - -- case of (methodRequestTagCalled, methodRetireTagCalled) of - -- (True, True) -> + stackPtr := + case (methodRequestTagCalled, methodRetireTagCalledValid.wget) of + (True, Just tag) -> stackPtr + (True, Nothing) -> + case stackPtr of + Just 0 -> Nothing + Just sampledStackPtr -> Just |> sampledStackPtr - 1 + Nothing -> Nothing + (False, Just tag) -> + 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 tag) -> 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 tag) -> 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 {} counter <- mkReg(0 :: UIntLog2N(numTags)) return $ @@ -71,23 +100,19 @@ mkTagEngine = requestTag = do methodRequestTagCalled.send - stackPtr := - if sampledStackPtr == 0 - then Nothing - else Just |> sampledStackPtr - 1 - (select inUseVec sampledStackPtr) := True - return |> Just |> readReg (select freeStackVec sampledStackPtr) - when - Just sampledStackPtr <- stackPtr + case methodRetireTagCalledValid.wget of + Just tag -> do + return |> Just tag + Nothing -> do + return |> + case stackPtr of + Just sampledStackPtr -> + Just |> readReg (select freeStackVec sampledStackPtr) + Nothing -> Nothing - -- retireTag isn't guarded so its up to external module to only attempt to - -- retire valid tags... At any rate, we can notify the requestor of failures - -- to retire tags - although the requestor can merely ignore this - -- notification. retireTag :: UIntLog2N(numTags) -> ActionValue BasicResult retireTag tag = do - methodRetireTagCalled.send let tagValid = tag < reifiedNumTags tagInUse = readReg (select inUseVec tag) @@ -97,9 +122,7 @@ mkTagEngine = Just n -> n + 1 if (tagValid && tagInUse) then do - (select inUseVec tag) := False - (select freeStackVec nextStackPtrUint) := tag - stackPtr := Just nextStackPtrUint + methodRetireTagCalledValid.wset tag return Success else do return Failure diff --git a/bs/Tests/TagEngineTester.bs b/bs/Tests/TagEngineTester.bs index 9cbab60..334b8d2 100644 --- a/bs/Tests/TagEngineTester.bs +++ b/bs/Tests/TagEngineTester.bs @@ -7,6 +7,7 @@ mkTagEngineTester :: Module Empty mkTagEngineTester = do tagEngine :: TagEngine 5 <- mkTagEngine count :: Reg (UInt 4) <- mkReg 0; + runOnce :: Reg Bool <- mkReg False s :: ActionSeq s <- @@ -30,7 +31,11 @@ mkTagEngineTester = do |> do requestTagAction |> do requestTagAction |> do retireTagAction 3 - |> do requestTagAction + |> do $display "BEGIN TRY SIMULTANEOUS RETIRE and REQUEST" + |> do + retireTagAction 4 + requestTagAction + |> do $display "END TRY SIMULTANEOUS RETIRE and REQUEST" |> do requestTagAction |> do retireTagAction 4 |> do retireTagAction 4 @@ -42,7 +47,7 @@ mkTagEngineTester = do addRules $ rules - "testIncrement": when (count < 10) ==> + "testIncrement": when (runOnce == False) ==> do - count := count + 1 - s.start \ No newline at end of file + s.start + runOnce := True \ No newline at end of file -- 2.48.1 From e89254ebef8b5b780e79faec25752b4cab71fbfd Mon Sep 17 00:00:00 2001 From: Yehowshua Immanuel Date: Tue, 25 Mar 2025 08:03:04 -0400 Subject: [PATCH 04/12] eliminate warnings --- bs/TagEngine.bs | 24 ++++++++++-------------- bs/Top.bs | 7 +------ 2 files changed, 11 insertions(+), 20 deletions(-) diff --git a/bs/TagEngine.bs b/bs/TagEngine.bs index 134e2c8..edca9fa 100644 --- a/bs/TagEngine.bs +++ b/bs/TagEngine.bs @@ -37,9 +37,10 @@ mkTagEngine = methodRetireTagCalledValid :: RWire UIntLog2N(numTags) methodRetireTagCalledValid <- mkUnsafeRWire - debugOnce <- mkReg True + -- computedTagResult :: BypassWire (Maybe UIntLog2N(numTags)) + -- methodRetireTagCalledValid <- mkBypassWire - tt :: Reg Bool <- mkReg False + debugOnce <- mkReg True addRules $ rules @@ -52,15 +53,15 @@ mkTagEngine = "update stack pointer": when True ==> do - stackPtr := + stackPtr := case (methodRequestTagCalled, methodRetireTagCalledValid.wget) of - (True, Just tag) -> stackPtr + (True, Just _) -> stackPtr (True, Nothing) -> case stackPtr of Just 0 -> Nothing Just sampledStackPtr -> Just |> sampledStackPtr - 1 Nothing -> Nothing - (False, Just tag) -> + (False, Just _) -> case stackPtr of Just sampledStackPtr -> Just |> sampledStackPtr + 1 Nothing -> Nothing @@ -69,7 +70,7 @@ mkTagEngine = "update free stack": when True ==> do case (methodRequestTagCalled, methodRetireTagCalledValid.wget) of - (True, Just tag) -> do action {} + (True, Just _) -> do action {} (True, Nothing) -> do action {} (False, Just tag) -> do case stackPtr of @@ -82,7 +83,7 @@ mkTagEngine = "update in use": when True ==> do case (methodRequestTagCalled, methodRetireTagCalledValid.wget) of - (True, Just tag) -> do action {} + (True, Just _) -> do action {} (True, Nothing) -> case stackPtr of Just sampledStackPtr -> do @@ -92,7 +93,6 @@ mkTagEngine = (select inUseVec tag) := False (False, Nothing) -> do action {} - counter <- mkReg(0 :: UIntLog2N(numTags)) return $ interface TagEngine @@ -104,9 +104,9 @@ mkTagEngine = Just tag -> do return |> Just tag Nothing -> do - return |> + return |> case stackPtr of - Just sampledStackPtr -> + Just sampledStackPtr -> Just |> readReg (select freeStackVec sampledStackPtr) Nothing -> Nothing @@ -116,10 +116,6 @@ mkTagEngine = let tagValid = tag < reifiedNumTags tagInUse = readReg (select inUseVec tag) - nextStackPtrUint = - case stackPtr of - Nothing -> 0 - Just n -> n + 1 if (tagValid && tagInUse) then do methodRetireTagCalledValid.wset tag diff --git a/bs/Top.bs b/bs/Top.bs index 5541bf6..373589c 100644 --- a/bs/Top.bs +++ b/bs/Top.bs @@ -68,8 +68,6 @@ mkTop = do bus :: Bus <- mkBus busClient :: BusClient <- mkBusClient - let a :: List Integer = 1 :> 2 :> Nil - b = length a persistLed :: Reg (Bit 8) <- mkReg 0 messageM $ "Hallo!!" + (realToString 5) @@ -102,10 +100,7 @@ mkTop = do mkSim :: Module Empty mkSim = do - let cfg :: BRAM_Configure = defaultValue - - tagEngineTester :: Empty <- mkTagEngineTester - count :: Reg (UInt 4) <- mkReg 0; + _ :: Empty <- mkTagEngineTester initCFunctions :: Reg Bool <- mkReg False; core :: Core FCLK <- mkCore; -- 2.48.1 From 6247ae3b70aabd78402b0a28dfe3f27925e5f13d Mon Sep 17 00:00:00 2001 From: Yehowshua Immanuel Date: Tue, 25 Mar 2025 08:48:43 -0400 Subject: [PATCH 05/12] clean unused experiments --- bs/Top.bs | 44 -------------------------------------------- 1 file changed, 44 deletions(-) diff --git a/bs/Top.bs b/bs/Top.bs index 373589c..f4f1cda 100644 --- a/bs/Top.bs +++ b/bs/Top.bs @@ -21,44 +21,6 @@ interface ITop = { ;ftdi_txd :: Bit 1 -> Action {-# always_ready , always_enabled #-} }; -interface BusClient = - request :: Bit 1 - response :: Bit 1 -> Action - -mkBusClient :: Module BusClient -mkBusClient = module - reqReg :: Reg (Bit 1) <- mkReg 0 - return $ - interface BusClient - request = reqReg - response resp = do - reqReg := 0 -- Reset request after receiving response - -interface Bus = - request :: Bit 1 -> Action - response :: Bit 1 - -mkBus :: Module Bus -mkBus = module - respReg :: Reg (Bit 1) <- mkReg 0 - return $ - interface Bus - request req = do - respReg := req -- Simple pass-through for this example - response = respReg - --- -- Function to connect Bus to BusClient -connectBusToClient :: Bus -> BusClient -> Rules -connectBusToClient bus client = - rules - "busConnection": when True ==> do - bus.request client.request - client.response bus.response - --- need to implement mkBus - --- need function that can connect Bus to BusClient - mkTop :: Module ITop mkTop = do fileHandle :: Handle <- openFile "compile.log" WriteMode @@ -66,15 +28,9 @@ mkTop = do serializer :: ISerializer FCLK BAUD <- mkSerialize fileHandle core :: Core FCLK <- mkCore - bus :: Bus <- mkBus - busClient :: BusClient <- mkBusClient - persistLed :: Reg (Bit 8) <- mkReg 0 messageM $ "Hallo!!" + (realToString 5) - -- need to instantiate a Bus and BusClient - addRules $ connectBusToClient bus busClient - addRules $ rules -- need new rule that always connects Bus to BusClient -- 2.48.1 From d436209f545e2d5ee576ec226eb4f0abde3fd9f7 Mon Sep 17 00:00:00 2001 From: Yehowshua Immanuel Date: Wed, 2 Apr 2025 02:09:41 -0400 Subject: [PATCH 06/12] seemingly reasonable stopping point --- bs/TagEngine.bs | 119 ++++++++++++++---------------------- bs/Tests/TagEngineTester.bs | 1 + 2 files changed, 48 insertions(+), 72 deletions(-) diff --git a/bs/TagEngine.bs b/bs/TagEngine.bs index edca9fa..91c5fdf 100644 --- a/bs/TagEngine.bs +++ b/bs/TagEngine.bs @@ -5,40 +5,41 @@ package TagEngine( import Vector import Util +import FIFO +import FIFOF #define UIntLog2N(n) (UInt (TLog n)) interface (TagEngine :: # -> *) numTags = - requestTag :: ActionValue (Maybe UIntLog2N(numTags)) - retireTag :: UIntLog2N(numTags) -> ActionValue BasicResult + requestTag :: ActionValue UIntLog2N(numTags) + retireTag :: UIntLog2N(numTags) -> Action -- 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 -- on a bus for example. --- This implementation is stack based. +-- This implementation is FIFO based. mkTagEngine :: Module (TagEngine numTags) mkTagEngine = do - let reifiedNumTags = fromInteger |> valueOf numTags - freeStackVec :: Vector numTags (Reg UIntLog2N(numTags)) - freeStackVec <- mapM (\i -> mkReg |> fromInteger i) genVector - inUseVec :: Vector numTags (Reg Bool) inUseVec <- replicateM |> mkReg False - stackPtr :: (Reg (Maybe(UIntLog2N(numTags)))) - stackPtr <- mkReg |> Just |> reifiedNumTags - 1 + -- Since Bluespec doesn't allow us to initialize FIFOs with values at + -- 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 - methodRequestTagCalled <- mkPulseWire + retireQueue :: FIFOF UIntLog2N(numTags) + retireQueue <- mkSizedFIFOF reifiedNumTags - methodRetireTagCalledValid :: RWire UIntLog2N(numTags) - methodRetireTagCalledValid <- mkUnsafeRWire - - -- computedTagResult :: BypassWire (Maybe UIntLog2N(numTags)) - -- methodRetireTagCalledValid <- mkBypassWire + freeQueue :: FIFOF UIntLog2N(numTags) + freeQueue <- mkSizedFIFOF reifiedNumTags debugOnce <- mkReg True @@ -46,71 +47,46 @@ mkTagEngine = rules "display": when (debugOnce == True) ==> do - $display "freeStackVec : " (fshow |> readVReg freeStackVec) $display "inUseVec : " (fshow |> readVReg inUseVec) - $display "stackPtr : " (fshow stackPtr) 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 - stackPtr := - case (methodRequestTagCalled, methodRetireTagCalledValid.wget) of - (True, Just _) -> stackPtr - (True, Nothing) -> - case stackPtr of - 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 {} + let tag = retireQueue.first + $display "firing retire_tags" (fshow tag) + retireQueue.deq + freeQueue.enq tag + (select inUseVec tag) := False return $ interface TagEngine - requestTag :: ActionValue (Maybe UIntLog2N(numTags)) + requestTag :: ActionValue UIntLog2N(numTags) requestTag = do - methodRequestTagCalled.send - case methodRetireTagCalledValid.wget of + case resetTagCounter of + Just 0 -> do + resetTagCounter := Nothing + (select inUseVec 0) := True + return 0 Just tag -> do - return |> Just tag + resetTagCounter := Just |> tag - 1 + (select inUseVec tag) := True + return tag Nothing -> do - return |> - case stackPtr of - Just sampledStackPtr -> - Just |> readReg (select freeStackVec sampledStackPtr) - Nothing -> Nothing + let tag = freeQueue.first + freeQueue.deq + return tag - 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 = do let @@ -118,7 +94,6 @@ mkTagEngine = tagInUse = readReg (select inUseVec tag) if (tagValid && tagInUse) then do - methodRetireTagCalledValid.wset tag - return Success + retireQueue.enq tag else do - return Failure + action {} diff --git a/bs/Tests/TagEngineTester.bs b/bs/Tests/TagEngineTester.bs index 334b8d2..e4bf3c4 100644 --- a/bs/Tests/TagEngineTester.bs +++ b/bs/Tests/TagEngineTester.bs @@ -44,6 +44,7 @@ mkTagEngineTester = do |> do requestTagAction |> do retireTagAction 1 |> do requestTagAction + |> do $finish addRules $ rules -- 2.48.1 From e055b1bbdfa2d871425c0196e1be713f7dee827d Mon Sep 17 00:00:00 2001 From: Yehowshua Immanuel Date: Wed, 2 Apr 2025 02:59:49 -0400 Subject: [PATCH 07/12] reduced latency --- bs/TagEngine.bs | 27 +++++++++++++++------------ bs/Tests/TagEngineTester.bs | 35 +++++++++++++++++++++++------------ 2 files changed, 38 insertions(+), 24 deletions(-) diff --git a/bs/TagEngine.bs b/bs/TagEngine.bs index 91c5fdf..e54eff4 100644 --- a/bs/TagEngine.bs +++ b/bs/TagEngine.bs @@ -23,8 +23,10 @@ mkTagEngine = do let reifiedNumTags = fromInteger |> valueOf numTags + -- we really only use inUseVec after emptying out our `resetTagCounter` buffer + -- perhaps rename this variable to better communicate that inUseVec :: Vector numTags (Reg Bool) - inUseVec <- replicateM |> mkReg False + inUseVec <- replicateM |> mkReg True -- Since Bluespec doesn't allow us to initialize FIFOs with values at -- reset, we can pretend as if the buffer within our tagFIFO is populated @@ -32,11 +34,12 @@ mkTagEngine = -- 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`. + -- Maybe resetTagCounter isn't the greatest name? resetTagCounter :: (Reg (Maybe UIntLog2N(numTags))) resetTagCounter <- mkReg |> Just |> reifiedNumTags - 1 - retireQueue :: FIFOF UIntLog2N(numTags) - retireQueue <- mkSizedFIFOF reifiedNumTags + retireTag :: Wire UIntLog2N(numTags) + retireTag <- mkWire freeQueue :: FIFOF UIntLog2N(numTags) freeQueue <- mkSizedFIFOF reifiedNumTags @@ -56,11 +59,9 @@ mkTagEngine = -- 2. the `requestTag` method handles the case where there are some tags to retire. "retire_tags": when True ==> do - let tag = retireQueue.first - $display "firing retire_tags" (fshow tag) - retireQueue.deq - freeQueue.enq tag - (select inUseVec tag) := False + $display "firing retire_tags" (fshow retireTag) + freeQueue.enq retireTag + (select inUseVec retireTag) := False return $ interface TagEngine @@ -71,11 +72,9 @@ mkTagEngine = case resetTagCounter of Just 0 -> do resetTagCounter := Nothing - (select inUseVec 0) := True return 0 Just tag -> do resetTagCounter := Just |> tag - 1 - (select inUseVec tag) := True return tag Nothing -> do let tag = freeQueue.first @@ -86,14 +85,18 @@ mkTagEngine = -- 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. + -- Also worth noting the TagEngin will ignore attempts to retire a tag you just + -- requested in the same cycle. This is enforce with `tag > tagCounter` below. retireTag :: UIntLog2N(numTags) -> Action retireTag tag = do let tagValid = tag < reifiedNumTags - tagInUse = readReg (select inUseVec tag) + tagInUse = case resetTagCounter of + Just tagCounter -> tag > tagCounter + Nothing -> readReg (select inUseVec tag) if (tagValid && tagInUse) then do - retireQueue.enq tag + retireTag := tag else do action {} diff --git a/bs/Tests/TagEngineTester.bs b/bs/Tests/TagEngineTester.bs index e4bf3c4..6c140c3 100644 --- a/bs/Tests/TagEngineTester.bs +++ b/bs/Tests/TagEngineTester.bs @@ -6,7 +6,7 @@ import ActionSeq mkTagEngineTester :: Module Empty mkTagEngineTester = do tagEngine :: TagEngine 5 <- mkTagEngine - count :: Reg (UInt 4) <- mkReg 0; + count :: Reg (UInt 32) <- mkReg 0; runOnce :: Reg Bool <- mkReg False s :: ActionSeq @@ -30,24 +30,35 @@ mkTagEngineTester = do do requestTagAction |> do requestTagAction |> do requestTagAction - |> do retireTagAction 3 - |> do $display "BEGIN TRY SIMULTANEOUS RETIRE and REQUEST" + |> do requestTagAction + |> do requestTagAction + |> do retireTagAction 2 + -- |> do $display "BEGIN TRY SIMULTANEOUS RETIRE and REQUEST" |> do retireTagAction 4 requestTagAction - |> do $display "END TRY SIMULTANEOUS RETIRE and REQUEST" - |> do requestTagAction - |> do retireTagAction 4 - |> do retireTagAction 4 - |> do retireTagAction 0 - |> do requestTagAction - |> do requestTagAction - |> do retireTagAction 1 - |> do requestTagAction + -- |> do $display "END TRY SIMULTANEOUS RETIRE and REQUEST" + -- |> do $display "BEGIN TRY SIMULTANEOUS RETIRE and REQUEST" + |> do + retireTagAction 4 + requestTagAction + -- |> do $display "END TRY SIMULTANEOUS RETIRE and REQUEST" |> do $finish + -- |> do retireTagAction 4 + -- |> do retireTagAction 4 + -- |> do retireTagAction 0 + -- |> do requestTagAction + -- |> do requestTagAction + -- |> do retireTagAction 1 + -- |> do requestTagAction + -- |> do $finish addRules $ rules + "counter": when True ==> + do + count := count + 1 + $display "count : " (fshow count) "testIncrement": when (runOnce == False) ==> do s.start -- 2.48.1 From d1e335819710f785d86ef496b069a57d0f22f372 Mon Sep 17 00:00:00 2001 From: Yehowshua Immanuel Date: Wed, 2 Apr 2025 03:03:39 -0400 Subject: [PATCH 08/12] now using wire instead of FIFO --- bs/TagEngine.bs | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/bs/TagEngine.bs b/bs/TagEngine.bs index e54eff4..b5f04b1 100644 --- a/bs/TagEngine.bs +++ b/bs/TagEngine.bs @@ -26,7 +26,7 @@ mkTagEngine = -- we really only use inUseVec after emptying out our `resetTagCounter` buffer -- perhaps rename this variable to better communicate that inUseVec :: Vector numTags (Reg Bool) - inUseVec <- replicateM |> mkReg True + inUseVec <- replicateM |> mkReg False -- Since Bluespec doesn't allow us to initialize FIFOs with values at -- reset, we can pretend as if the buffer within our tagFIFO is populated @@ -72,9 +72,11 @@ mkTagEngine = case resetTagCounter of Just 0 -> do resetTagCounter := Nothing + (select inUseVec 0) := True return 0 Just tag -> do resetTagCounter := Just |> tag - 1 + (select inUseVec tag) := True return tag Nothing -> do let tag = freeQueue.first @@ -85,16 +87,12 @@ mkTagEngine = -- 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. - -- Also worth noting the TagEngin will ignore attempts to retire a tag you just - -- requested in the same cycle. This is enforce with `tag > tagCounter` below. retireTag :: UIntLog2N(numTags) -> Action retireTag tag = do let tagValid = tag < reifiedNumTags - tagInUse = case resetTagCounter of - Just tagCounter -> tag > tagCounter - Nothing -> readReg (select inUseVec tag) + tagInUse = readReg (select inUseVec tag) if (tagValid && tagInUse) then do retireTag := tag -- 2.48.1 From 271148e53840b2fd5fdc33e742e9831b50a7b857 Mon Sep 17 00:00:00 2001 From: Yehowshua Immanuel Date: Thu, 3 Apr 2025 09:15:53 -0400 Subject: [PATCH 09/12] better names in TagEngine --- bs/TagEngine.bs | 43 +++++++++++++++++++------------------------ 1 file changed, 19 insertions(+), 24 deletions(-) diff --git a/bs/TagEngine.bs b/bs/TagEngine.bs index b5f04b1..d8e0736 100644 --- a/bs/TagEngine.bs +++ b/bs/TagEngine.bs @@ -23,10 +23,10 @@ mkTagEngine = do let reifiedNumTags = fromInteger |> valueOf numTags - -- we really only use inUseVec after emptying out our `resetTagCounter` buffer - -- perhaps rename this variable to better communicate that - inUseVec :: Vector numTags (Reg Bool) - inUseVec <- replicateM |> mkReg False + -- we really only use tagUsageTracker after emptying out our + -- `initialTagDistributor` buffer + tagUsageTracker :: Vector numTags (Reg Bool) + tagUsageTracker <- replicateM |> mkReg False -- Since Bluespec doesn't allow us to initialize FIFOs with values at -- reset, we can pretend as if the buffer within our tagFIFO is populated @@ -34,15 +34,14 @@ mkTagEngine = -- 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`. - -- Maybe resetTagCounter isn't the greatest name? - resetTagCounter :: (Reg (Maybe UIntLog2N(numTags))) - resetTagCounter <- mkReg |> Just |> reifiedNumTags - 1 + initialTagDistributor :: (Reg (Maybe UIntLog2N(numTags))) + initialTagDistributor <- mkReg |> Just |> reifiedNumTags - 1 retireTag :: Wire UIntLog2N(numTags) retireTag <- mkWire - freeQueue :: FIFOF UIntLog2N(numTags) - freeQueue <- mkSizedFIFOF reifiedNumTags + tagFIFO :: FIFOF UIntLog2N(numTags) + tagFIFO <- mkSizedFIFOF reifiedNumTags debugOnce <- mkReg True @@ -50,18 +49,14 @@ mkTagEngine = rules "display": when (debugOnce == True) ==> do - $display "inUseVec : " (fshow |> readVReg inUseVec) + $display "tagUsageTracker : " (fshow |> readVReg tagUsageTracker) debugOnce := False - -- 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 $display "firing retire_tags" (fshow retireTag) - freeQueue.enq retireTag - (select inUseVec retireTag) := False + tagFIFO.enq retireTag + (select tagUsageTracker retireTag) := False return $ interface TagEngine @@ -69,18 +64,18 @@ mkTagEngine = requestTag :: ActionValue UIntLog2N(numTags) requestTag = do - case resetTagCounter of + case initialTagDistributor of Just 0 -> do - resetTagCounter := Nothing - (select inUseVec 0) := True + initialTagDistributor := Nothing + (select tagUsageTracker 0) := True return 0 Just tag -> do - resetTagCounter := Just |> tag - 1 - (select inUseVec tag) := True + initialTagDistributor := Just |> tag - 1 + (select tagUsageTracker tag) := True return tag Nothing -> do - let tag = freeQueue.first - freeQueue.deq + let tag = tagFIFO.first + tagFIFO.deq return tag -- `retireTag` isn't guarded on tag validity(this would break Bluespec's safety model) @@ -92,7 +87,7 @@ mkTagEngine = do let tagValid = tag < reifiedNumTags - tagInUse = readReg (select inUseVec tag) + tagInUse = readReg (select tagUsageTracker tag) if (tagValid && tagInUse) then do retireTag := tag -- 2.48.1 From ca59e6eaeceff683d781883db0d3b6effdccc161 Mon Sep 17 00:00:00 2001 From: Yehowshua Immanuel Date: Fri, 4 Apr 2025 15:09:56 -0400 Subject: [PATCH 10/12] handled tag engine edge case --- bs/TagEngine.bs | 59 +++++++++++++++++++++++++++++-------- bs/Tests/TagEngineTester.bs | 21 +++++++------ 2 files changed, 57 insertions(+), 23 deletions(-) diff --git a/bs/TagEngine.bs b/bs/TagEngine.bs index d8e0736..f5a00ba 100644 --- a/bs/TagEngine.bs +++ b/bs/TagEngine.bs @@ -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 {} diff --git a/bs/Tests/TagEngineTester.bs b/bs/Tests/TagEngineTester.bs index 6c140c3..4fc700e 100644 --- a/bs/Tests/TagEngineTester.bs +++ b/bs/Tests/TagEngineTester.bs @@ -6,23 +6,22 @@ import ActionSeq mkTagEngineTester :: Module Empty mkTagEngineTester = do tagEngine :: TagEngine 5 <- mkTagEngine - count :: Reg (UInt 32) <- mkReg 0; runOnce :: Reg Bool <- mkReg False s :: ActionSeq - s <- + s <- let requestTagAction :: Action requestTagAction = do tag <- tagEngine.requestTag - $display "got tag : " (fshow tag) + $display $time " got tag : " (fshow tag) retireTagAction :: UInt 3 -> Action retireTagAction tag = do res <- tagEngine.retireTag tag - $display "retiring tag : " (fshow tag) " " (fshow res) + $display $time " retiring tag : " (fshow tag) " " (fshow res) action {} in @@ -34,12 +33,12 @@ mkTagEngineTester = do |> do requestTagAction |> do retireTagAction 2 -- |> do $display "BEGIN TRY SIMULTANEOUS RETIRE and REQUEST" - |> do + |> do retireTagAction 4 requestTagAction -- |> do $display "END TRY SIMULTANEOUS RETIRE and REQUEST" -- |> do $display "BEGIN TRY SIMULTANEOUS RETIRE and REQUEST" - |> do + |> do retireTagAction 4 requestTagAction -- |> do $display "END TRY SIMULTANEOUS RETIRE and REQUEST" @@ -55,11 +54,11 @@ mkTagEngineTester = do addRules $ rules - "counter": when True ==> - do - count := count + 1 - $display "count : " (fshow count) + -- "counter": when True ==> + -- do + -- count := count + 1 + -- $display "count : " (fshow count) "testIncrement": when (runOnce == False) ==> do s.start - runOnce := True \ No newline at end of file + runOnce := True -- 2.48.1 From 020bc5b6460dd422e2170f5466ae8c8d90174760 Mon Sep 17 00:00:00 2001 From: Yehowshua Immanuel Date: Fri, 4 Apr 2025 15:27:25 -0400 Subject: [PATCH 11/12] notable refactor with grok --- bs/TagEngine.bs | 155 ++++++++++++++++++++---------------------------- 1 file changed, 64 insertions(+), 91 deletions(-) diff --git a/bs/TagEngine.bs b/bs/TagEngine.bs index f5a00ba..0d28fce 100644 --- a/bs/TagEngine.bs +++ b/bs/TagEngine.bs @@ -20,111 +20,84 @@ interface (TagEngine :: # -> *) numTags = -- on a bus for example. -- This implementation is FIFO based. mkTagEngine :: Module (TagEngine numTags) -mkTagEngine = - do - let reifiedNumTags = fromInteger |> valueOf numTags +mkTagEngine = do + -- Constants + let maxTagCount = fromInteger (valueOf numTags) - -- we really only use tagUsageTracker after emptying out our - -- `initialTagDistributor` buffer - tagUsageTracker :: Vector numTags (Reg Bool) - tagUsageTracker <- replicateM |> mkReg False + -- State + tagUsage :: Vector numTags (Reg Bool) <- replicateM (mkReg False) -- Tracks which tags are in use + initialTagCounter <- mkReg (Just (maxTagCount - 1)) -- Distributes initial tags + retireQueue <- mkBypassFIFO -- Queue for tags being retired + freeTagQueue <- mkSizedFIFOF maxTagCount -- Queue of available tags - -- Since Bluespec doesn't allow us to initialize FIFOs with values at - -- 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`. - initialTagDistributor :: (Reg (Maybe UIntLog2N(numTags))) - initialTagDistributor <- mkReg |> Just |> reifiedNumTags - 1 + -- Signals + retireSignal <- mkRWire -- Signals a tag retirement + requestSignal <- mkRWire -- Signals a tag request - validatedTagToRetire :: FIFO UIntLog2N(numTags) - validatedTagToRetire <- mkBypassFIFO + -- Debug + debugOnce <- mkReg True - updateUsageRetireTag :: RWire UIntLog2N(numTags) - updateUsageRetireTag <- mkRWire + -- Rules + addRules $ + rules + "debug_initial_state": when debugOnce ==> do + $display "tagUsage: " (fshow (readVReg tagUsage)) + debugOnce := False - updateUsageRequestTag :: RWire UIntLog2N(numTags) - updateUsageRequestTag <- mkRWire + "retire_tag": when True ==> do + let tag = retireQueue.first + $display "Retiring tag: " (fshow tag) + retireQueue.deq + freeTagQueue.enq tag + retireSignal.wset tag - tagFIFO :: FIFOF UIntLog2N(numTags) - tagFIFO <- mkSizedFIFOF reifiedNumTags - - debugOnce <- mkReg True - - addRules $ - rules - "display": when (debugOnce == True) ==> - 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 - let tagToRetire = validatedTagToRetire.first - $display "firing retire_tags" (fshow tagToRetire) - validatedTagToRetire.deq - tagFIFO.enq tagToRetire - updateUsageRetireTag.wset tagToRetire - - return $ - interface TagEngine + -- Combined update rules (simplified below) + "update_usage": when True ==> do + let mRetireTag = retireSignal.wget + mRequestTag = requestSignal.wget + case (mRetireTag, mRequestTag) of + (Just retireTag, Just requestTag) -> do + let usage = readVReg tagUsage + usage' = update usage requestTag True + usage'' = update usage' retireTag False + writeVReg tagUsage usage'' + $display $time " Updated usage (request + retire): " (fshow |> readVReg tagUsage) + (Just retireTag, Nothing) -> do + (select tagUsage retireTag) := False + $display $time " Updated usage (retire): " (fshow (readVReg tagUsage)) + (Nothing, Just requestTag) -> do + (select tagUsage requestTag) := True + $display $time " Updated usage (request): " (fshow (readVReg tagUsage)) + (Nothing, Nothing) -> action {} + -- Interface + return $ + interface TagEngine requestTag :: ActionValue UIntLog2N(numTags) - requestTag = - do - case initialTagDistributor of - Just 0 -> do - initialTagDistributor := Nothing - updateUsageRequestTag.wset 0 - return 0 - Just tag -> do - initialTagDistributor := Just |> tag - 1 - updateUsageRequestTag.wset tag - return tag - Nothing -> do - let tag = tagFIFO.first - tagFIFO.deq - updateUsageRequestTag.wset tag - return tag + requestTag = do + case initialTagCounter of + Just 0 -> do + initialTagCounter := Nothing + requestSignal.wset 0 + return 0 + Just tag -> do + initialTagCounter := Just (tag - 1) + requestSignal.wset tag + return tag + Nothing -> do + let tag = freeTagQueue.first + freeTagQueue.deq + requestSignal.wset tag + return tag - -- `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 = do let - tagValid = tag < reifiedNumTags - tagInUse = readReg (select tagUsageTracker tag) + tagValid = tag < maxTagCount + tagInUse = readReg (select tagUsage tag) if (tagValid && tagInUse) then do - validatedTagToRetire.enq tag + retireQueue.enq tag else do action {} -- 2.48.1 From e415d981f9b40bf4a4667395245d4f3d6fa2e6bb Mon Sep 17 00:00:00 2001 From: Yehowshua Immanuel Date: Fri, 4 Apr 2025 15:31:46 -0400 Subject: [PATCH 12/12] add some comments --- bs/TagEngine.bs | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/bs/TagEngine.bs b/bs/TagEngine.bs index 0d28fce..921e58e 100644 --- a/bs/TagEngine.bs +++ b/bs/TagEngine.bs @@ -24,9 +24,15 @@ mkTagEngine = do -- Constants let maxTagCount = fromInteger (valueOf numTags) - -- State tagUsage :: Vector numTags (Reg Bool) <- replicateM (mkReg False) -- Tracks which tags are in use - initialTagCounter <- mkReg (Just (maxTagCount - 1)) -- Distributes initial tags + + -- Since Bluespec doesn't allow us to initialize FIFOs with values at + -- reset, we can pretend as if the buffer within our freeTagQueue 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 (maxTagCount - 1) for the first n tag requests made + -- to TagEngine where `n := maxTagCount`. + initialTagDistributor <- mkReg (Just (maxTagCount - 1)) -- Distributes initial tags retireQueue <- mkBypassFIFO -- Queue for tags being retired freeTagQueue <- mkSizedFIFOF maxTagCount -- Queue of available tags @@ -75,13 +81,13 @@ mkTagEngine = do interface TagEngine requestTag :: ActionValue UIntLog2N(numTags) requestTag = do - case initialTagCounter of + case initialTagDistributor of Just 0 -> do - initialTagCounter := Nothing + initialTagDistributor := Nothing requestSignal.wset 0 return 0 Just tag -> do - initialTagCounter := Just (tag - 1) + initialTagDistributor := Just (tag - 1) requestSignal.wset tag return tag Nothing -> do @@ -90,6 +96,10 @@ mkTagEngine = do requestSignal.wset tag return tag + -- `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 = do -- 2.48.1