diff --git a/bs/BusTypes.bs b/bs/BusTypes.bs index e7cba2c..422ed9e 100644 --- a/bs/BusTypes.bs +++ b/bs/BusTypes.bs @@ -1,4 +1,10 @@ -package BusTypes(BusVal, TransactionSize) where +package BusTypes( + BusVal(..), + BusError(..), + TransactionSize(..), + ReadRequest(..), + WriteRequest(..) + ) where import Types @@ -29,5 +35,34 @@ data ReadRequest = ReadRequest Addr TransactionSize data WriteRequest = WriteRequest Addr BusVal deriving (Bits, Eq, FShow) +type ReadResponse = Either BusError BusVal +type WriteResponse = Either BusError () + +data BusRequest + = BusReadRequest ReadRequest + | WriteReadRequest WriteRequest + deriving (Bits, Eq, FShow) + +data BusResponse + = BusReadResponse ReadResponse + | BusWriteResponse WriteResponse + deriving (Bits, Eq, FShow) + +interface BusMaster = + -- The Bus arbiter will call the Bus Client's request method + -- if and only if it's the Bus Client's turn to make a request, and the Bus Client + -- has a request to make. + -- It is up to the BusMaster to guard it's request method such that calling + -- it's request method is only valid when the BusMaster has a request to make. + -- 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 client'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. + response :: BusResponse -> Action + +type Token = UInt 5 + a :: UInt 5 a = 3 diff --git a/bs/Top.bs b/bs/Top.bs index b1f7105..5efb1d4 100644 --- a/bs/Top.bs +++ b/bs/Top.bs @@ -6,6 +6,7 @@ import Serializer import BRAM import CBindings import Bus +import List type FCLK = 25000000 type BAUD = 9600 @@ -16,19 +17,65 @@ 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 deserializer :: IDeserializer FCLK BAUD <- mkDeserialize fileHandle serializer :: ISerializer FCLK BAUD <- mkSerialize fileHandle core :: Core FCLK <- mkCore + + 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) - -- refactor such that the following rules are let-bound to - -- `attachIO` identifier + -- need to instantiate a Bus and BusClient + addRules $ connectBusToClient bus busClient + addRules $ rules + -- need new rule that always connects Bus to BusClient "coreLedO" : when True ==> persistLed := core.getLed