package MemArbiter; import Connectable::*; import Vector::*; export MemArbiterOp(..); export MemArbiterServer(..); export MemArbiterClient(..); export MemArbiter(..), mkPriorityMemArbiter, mkRoundRobinMemArbiter; typedef struct { Bool write; addr addr; } MemArbiterOp#(type addr) deriving (Bits, Eq, FShow); // A MemArbiterServer receives requests for memory access and emits // grants. interface MemArbiterServer#(type addr); method Action request(MemArbiterOp#(addr) req); method Bool grant(); endinterface // A MemArbiterClient emits requests for memory access and emits // grants. interface MemArbiterClient#(type addr); method Maybe#(MemArbiterOp#(addr)) request(); method Action grant(); endinterface instance Connectable#(MemArbiterClient#(addr), MemArbiterServer#(addr)); module mkConnection(MemArbiterClient#(addr) client, MemArbiterServer#(addr) server, Empty ifc); rule send_request (client.request matches tagged Valid .req); server.request(req); endrule rule send_grant (server.grant()); client.grant(); endrule endmodule endinstance interface MemArbiter#(numeric type num_clients, type addr); interface Vector#(num_clients, MemArbiterServer#(addr)) ports; method Action forbid_addr(addr addr); method addr forbidden_addr(); endinterface module mkPriorityMemArbiter(MemArbiter#(num_clients, addr)) provisos (Bits#(addr, _), Eq#(addr), Min#(num_clients, 1, 1)); Vector#(num_clients, RWire#(MemArbiterOp#(addr))) reqs <- replicateM(mkRWire()); Wire#(Vector#(num_clients, Bool)) grants <- mkBypassWire(); RWire#(addr) blocked_in <- mkRWire(); RWire#(addr) blocked_out <- mkRWire(); function Bool is_blocked(addr addr); return blocked_in.wget() == tagged Valid addr; endfunction (* no_implicit_conditions, fire_when_enabled *) rule grant_requests; Vector#(num_clients, Bool) grant = replicate(False); Bool done = False; for (Integer i=0; i