diff --git a/experiments/arbiter/Top.bsv b/experiments/arbiter/Top.bsv index de48446..8d39bb1 100644 --- a/experiments/arbiter/Top.bsv +++ b/experiments/arbiter/Top.bsv @@ -4,6 +4,7 @@ import MemArbiter::*; import Vector::*; import DReg::*; import DelayLine::*; +import Connectable::*; typedef UInt#(2) Addr; @@ -22,70 +23,51 @@ endinterface (* synthesize, clock_prefix="clk_25mhz", reset_prefix="rst_btn" *) module mkTop(Top); - Vector#(2, Reg#(Maybe#(MemArbiterWrite#(Addr)))) wrin <- replicateM(mkDReg(tagged Invalid)); - Vector#(4, Reg#(Maybe#(Addr))) rdin <- replicateM(mkDReg(tagged Invalid)); + Vector#(6, Reg#(Maybe#(MemArbiterOp#(Addr)))) wrin <- replicateM(mkDReg(tagged Invalid)); - MemArbiter#(Addr) ret <- mkMemArbiter(); + MemArbiter#(3, Addr) portA <- mkPriorityMemArbiter(); + MemArbiter#(3, Addr) portB <- mkRoundRobinMemArbiter(); + mkConnection(portA, portB); + + let arbiters = append(portA.ports, portB.ports); Reg#(Vector#(6, Bool)) ok <- mkReg(replicate(False)); - rule req_cpu (wrin[0] matches tagged Valid .req); - ret.cpu.request(req); - endrule - - rule req_debugger (wrin[1] matches tagged Valid .req); - ret.debugger.request(req); - endrule - - rule req_palette (rdin[0] matches tagged Valid .addr); - ret.palette.request(addr); - endrule - - rule req_tile1 (rdin[1] matches tagged Valid .addr); - ret.tile1.request(addr); - endrule - - rule req_tile2 (rdin[2] matches tagged Valid .addr); - ret.tile2.request(addr); - endrule - - rule req_sprite (rdin[3] matches tagged Valid .addr); - ret.sprite.request(addr); - endrule + for (Integer i=0; i<6; i=i+1) begin + rule req (wrin[i] matches tagged Valid .req); + arbiters[i].request(req); + endrule + end rule resp; - Vector#(6, Bool) r = newVector; - r[0] = ret.cpu.grant(); - r[1] = ret.debugger.grant(); - r[2] = ret.palette.grant(); - r[3] = ret.tile1.grant(); - r[4] = ret.tile2.grant(); - r[5] = ret.sprite.grant(); - ok <= r; + function Bool get(MemArbiterServer#(Addr) s); + return s.grant(); + endfunction + ok <= map(get, arbiters); endrule method Action cpu(Bool write, Addr addr); - wrin[0] <= tagged Valid MemArbiterWrite{write: write, addr: addr}; + wrin[0] <= tagged Valid MemArbiterOp{write: write, addr: addr}; endmethod method Action debugger(Bool write, Addr addr); - wrin[1] <= tagged Valid MemArbiterWrite{write: write, addr: addr}; + wrin[1] <= tagged Valid MemArbiterOp{write: write, addr: addr}; endmethod method Action palette(Addr addr); - rdin[0] <= tagged Valid addr; + wrin[2] <= tagged Valid MemArbiterOp{write: False, addr: addr}; endmethod method Action tile1(Addr addr); - rdin[1] <= tagged Valid addr; + wrin[3] <= tagged Valid MemArbiterOp{write: False, addr: addr}; endmethod method Action tile2(Addr addr); - rdin[2] <= tagged Valid addr; + wrin[4] <= tagged Valid MemArbiterOp{write: False, addr: addr}; endmethod method Action sprite(Addr addr); - rdin[3] <= tagged Valid addr; + wrin[5] <= tagged Valid MemArbiterOp{write: False, addr: addr}; endmethod method Bit#(6) grants(); diff --git a/vram/MemArbiter.bsv b/vram/MemArbiter.bsv index 70b1c4d..0387d01 100644 --- a/vram/MemArbiter.bsv +++ b/vram/MemArbiter.bsv @@ -15,6 +15,15 @@ typedef struct { addr addr; } MemArbiterOp#(type addr) deriving (Bits, Eq, FShow); +function Bool mem_ops_conflict(Maybe#(MemArbiterOp#(addr)) a, Maybe#(MemArbiterOp#(addr)) b) + provisos(Eq#(addr)); + + if (a matches tagged Valid .ar &&& b matches tagged Valid .br &&& ar.addr == br.addr) + return ar.write || br.write; + else + return False; +endfunction + // A MemArbiterServer receives requests and emits grants. interface MemArbiterServer#(type addr); method Action request(MemArbiterOp#(addr) req); @@ -54,22 +63,23 @@ interface MemArbiter#(numeric type num_clients, type addr); // each memory port must cooperate to avoid simultaneously granting // conflicting requests from their clients. // - // Calling forbid_addr prevents the arbiter from granting a - // concurrent request to access the given address. forbidden_addr - // emits the address for which a write access is being granted. + // Calling conflict prevents the arbiter from granting a concurrent + // request that would result in a write-write, read-write or + // write-read conflict. granted_op emits the operation that the + // arbiter is granting, if any. // // MemArbiter intances are Connectable: mkConnection(a, b) gives - // conflict priority to a. That is, b will not grant requests that - // conflict with the grant that a has emitted. - method Action forbid_addr(addr addr); - method addr forbidden_addr(); + // conflict priority to a. That is, b only grants requests that + // don't conflict with a's grant. + method Action conflict(MemArbiterOp#(addr) conflict); + method MemArbiterOp#(addr) granted_op(); endinterface instance Connectable#(MemArbiter#(m, addr), MemArbiter#(n, addr)); module mkConnection(MemArbiter#(m, addr) a, MemArbiter#(n, addr) b, Empty ifc); (* fire_when_enabled *) - rule forward_forbid; - b.forbid_addr(a.forbidden_addr); + rule forward_conflict; + b.conflict(a.granted_op); endrule endmodule endinstance @@ -84,12 +94,8 @@ module mkPriorityMemArbiter(MemArbiter#(num_clients, addr)) 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 + RWire#(MemArbiterOp#(addr)) conflict_in <- mkRWire(); + RWire#(MemArbiterOp#(addr)) granted_op_out <- mkRWire(); (* no_implicit_conditions, fire_when_enabled *) rule grant_requests; @@ -97,12 +103,13 @@ module mkPriorityMemArbiter(MemArbiter#(num_clients, addr)) Bool done = False; for (Integer i=0; i"); - tagged Valid .a: return $format("%0d", a); - endcase - endfunction - (* no_implicit_conditions, fire_when_enabled *) rule check (running); let test = tests[idx]; let reqs = test.reqs; let want_grants = test.want_grants; - let want_forbid_addr = test.want_forbid_addr; + let want_granted_op = test.want_granted_op; Vector#(n, Bool) got_grants = newVector; for (Integer i=0; i