Skip to content

Commit

Permalink
Major cleanups to AXI4 and addition of documentation
Browse files Browse the repository at this point in the history
* Added some unit tests in testing/bsc.contrib/AMBA_Fabrics
    Also fixed up many Library/AMBA_Fabrics/ files to simplify unit testing.
    Minor tweaks to doc/How_to_Contribute.{adoc,html}

* Major cleanup of Libraries/AMBA_Fabrics/AXI4
    Uniform AMBA names,
    Clean Separation of BSV FIFO-like communication
         and AMBA RTL signaling with ready-valid handshake
    Rewrote several modules and created new tests.

* Added READMEs to all AMBA_Fabrics directories
  • Loading branch information
rsnikhil authored Dec 14, 2024
1 parent 2691426 commit 154d564
Show file tree
Hide file tree
Showing 61 changed files with 9,182 additions and 4,391 deletions.
247 changes: 110 additions & 137 deletions Libraries/AMBA_Fabrics/AXI4/AXI4_Addr_Translator.bsv
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
// Copyright (c) 2020 Bluespec, Inc. All Rights Reserved
// Copyright (c) 2024 Rishiyur S. Nikhil.
//
// SPDX-License-Identifier: BSD-3-Clause

Expand All @@ -8,176 +9,148 @@ package AXI4_Addr_Translator;
// This package defines transformers for AXI4_M and AXI4_S interfaces
// that perform a simple 'address-translator' (add/subtract a fixed
// constant from address).
// Each transformer copies AW and AR, just adjusting the address,
// and just copies W, B and R.

// ================================================================
// Bluespec library imports

// none

// ----------------
// BSV additional libs
// Bluespec misc. libs

// none
import Semi_FIFOF :: *;

// ================================================================
// Project imports

import AXI4_Types :: *;
import AXI4_Types :: *;

// ================================================================
// M-to-M interface transformer with address translation
// M-to-M interface transformer with address translation.

function AXI4_M_IFC #(wd_id, wd_addr, wd_data, wd_user)
fv_AXI4_M_Address_Translator (Bool add_not_sub,
Bit #(wd_addr) addr_delta,
AXI4_M_IFC #(wd_id, wd_addr, wd_data, wd_user) ifc);
function AXI4_M_IFC #(wd_id, wd_addr, wd_data, wd_user)
fv_AXI4_M_Address_Translator (Bool add_not_sub,
Bit #(wd_addr) addr_delta,
AXI4_M_IFC #(wd_id,
wd_addr,
wd_data,
wd_user) ifc_M);

function Bit #(wd_addr) fv_addr_translate (Bit #(wd_addr) addr);
return (add_not_sub ? addr + addr_delta : addr - addr_delta);
endfunction

return interface AXI4_M_IFC
// Wr Addr channel
method Bool m_awvalid = ifc.m_awvalid; // out
method Bit #(wd_id) m_awid = ifc.m_awid; // out
method Bit #(wd_addr) m_awaddr = fv_addr_translate (ifc.m_awaddr); // out
method Bit #(8) m_awlen = ifc.m_awlen; // out
method AXI4_Size m_awsize = ifc.m_awsize; // out
method Bit #(2) m_awburst = ifc.m_awburst; // out
method Bit #(1) m_awlock = ifc.m_awlock; // out
method Bit #(4) m_awcache = ifc.m_awcache; // out
method Bit #(3) m_awprot = ifc.m_awprot; // out
method Bit #(4) m_awqos = ifc.m_awqos; // out
method Bit #(4) m_awregion = ifc.m_awregion; // out
method Bit #(wd_user) m_awuser = ifc.m_awuser; // out
method Action m_awready (Bool awready) = ifc.m_awready (awready); // in

// Wr Data channel
method Bool m_wvalid = ifc.m_wvalid; // out
method Bit #(wd_data) m_wdata = ifc.m_wdata; // out
method Bit #(TDiv #(wd_data, 8)) m_wstrb = ifc.m_wstrb; // out
method Bool m_wlast = ifc.m_wlast; // out
method Bit #(wd_user) m_wuser = ifc.m_wuser; // out

method Action m_wready (Bool wready) = ifc.m_wready (wready); // in

// Wr Response channel
method Action m_bvalid (Bool bvalid, // in
Bit #(wd_id) bid, // in
Bit #(2) bresp, // in
Bit #(wd_user) buser); // in
ifc.m_bvalid (bvalid, bid, bresp, buser);
endmethod
method Bool m_bready = ifc.m_bready; // out

// Rd Addr channel
method Bool m_arvalid = ifc.m_arvalid; // out
method Bit #(wd_id) m_arid = ifc.m_arid; // out
method Bit #(wd_addr) m_araddr = fv_addr_translate (ifc.m_araddr); // out
method Bit #(8) m_arlen = ifc.m_arlen; // out
method AXI4_Size m_arsize = ifc.m_arsize; // out
method Bit #(2) m_arburst = ifc.m_arburst; // out
method Bit #(1) m_arlock = ifc.m_arlock; // out
method Bit #(4) m_arcache = ifc.m_arcache; // out
method Bit #(3) m_arprot = ifc.m_arprot; // out
method Bit #(4) m_arqos = ifc.m_arqos; // out
method Bit #(4) m_arregion = ifc.m_arregion; // out
method Bit #(wd_user) m_aruser = ifc.m_aruser; // out
method Action m_arready (Bool arready) = ifc.m_arready (arready); // in

// Rd Data channel
method Action m_rvalid (Bool rvalid, // in
Bit #(wd_id) rid, // in
Bit #(wd_data) rdata, // in
Bit #(2) rresp, // in
Bool rlast, // in
Bit #(wd_user) ruser); // in
ifc.m_rvalid (rvalid, rid, rdata, rresp, rlast, ruser);
endmethod
method Bool m_rready = ifc.m_rready; // out
interface FIFOF_O o_AW;
method first;
let aw_in = ifc_M.o_AW.first;
let aw_out = AXI4_AW {awid: aw_in.awid,
awaddr: fv_addr_translate (aw_in.awaddr),
awlen: aw_in.awlen,
awsize: aw_in.awsize,
awburst: aw_in.awburst,
awlock: aw_in.awlock,
awcache: aw_in.awcache,
awprot: aw_in.awprot,
awqos: aw_in.awqos,
awregion: aw_in.awregion,
awuser: aw_in.awuser};
return aw_out;
endmethod
method deq = ifc_M.o_AW.deq;
method notEmpty = ifc_M.o_AW.notEmpty;
endinterface

interface FIFOF_I o_W = ifc_M.o_W;

interface FIFOF_I i_B = ifc_M.i_B;

interface FIFOF_O o_AR;
method first;
let ar_in = ifc_M.o_AR.first;
let ar_out = AXI4_AR {arid: ar_in.arid,
araddr: fv_addr_translate (ar_in.araddr),
arlen: ar_in.arlen,
arsize: ar_in.arsize,
arburst: ar_in.arburst,
arlock: ar_in.arlock,
arcache: ar_in.arcache,
arprot: ar_in.arprot,
arqos: ar_in.arqos,
arregion: ar_in.arregion,
aruser: ar_in.aruser};
return ar_out;
endmethod
method deq = ifc_M.o_AR.deq;
method notEmpty = ifc_M.o_AR.notEmpty;
endinterface

interface FIFOF_I i_R = ifc_M.i_R;
endinterface;
endfunction

// ================================================================
// S-to-S interface transformer with address translation

function AXI4_S_IFC #(wd_id, wd_addr, wd_data, wd_user)
fv_AXI4_S_Address_Translator (Bool add_not_sub,
Bit #(wd_addr) addr_delta,
AXI4_S_IFC #(wd_id, wd_addr, wd_data, wd_user) ifc);
function AXI4_S_IFC #(wd_id, wd_addr, wd_data, wd_user)
fv_AXI4_S_Address_Translator (Bool add_not_sub,
Bit #(wd_addr) addr_delta,
AXI4_S_IFC #(wd_id,
wd_addr,
wd_data,
wd_user) ifc_S);

function Bit #(wd_addr) fv_addr_translate (Bit #(wd_addr) addr);
return (add_not_sub ? addr + addr_delta : addr - addr_delta);
endfunction

return interface AXI4_S_IFC
// Wr Addr channel
method Action m_awvalid (Bool awvalid,
Bit #(wd_id) awid,
Bit #(wd_addr) awaddr,
Bit #(8) awlen,
AXI4_Size awsize,
Bit #(2) awburst,
Bit #(1) awlock,
Bit #(4) awcache,
Bit #(3) awprot,
Bit #(4) awqos,
Bit #(4) awregion,
Bit #(wd_user) awuser);
ifc.m_awvalid (awvalid, awid,
fv_addr_translate (awaddr),
awlen, awsize, awburst,
awlock, awcache, awprot, awqos, awregion, awuser);
endmethod
method Bool m_awready = ifc.m_awready;

// Wr Data channel
method Action m_wvalid (Bool wvalid,
Bit #(wd_data) wdata,
Bit #(TDiv #(wd_data, 8)) wstrb,
Bool wlast,
Bit #(wd_user) wuser);
ifc.m_wvalid (wvalid, wdata, wstrb, wlast, wuser);
endmethod
method Bool m_wready = ifc.m_wready;

// Wr Response channel
method Bool m_bvalid = ifc.m_bvalid;
method Bit #(wd_id) m_bid = ifc.m_bid;
method Bit #(2) m_bresp = ifc.m_bresp;
method Bit #(wd_user) m_buser = ifc.m_buser;
method Action m_bready (Bool bready) = ifc.m_bready (bready);

// Rd Addr channel
method Action m_arvalid (Bool arvalid,
Bit #(wd_id) arid,
Bit #(wd_addr) araddr,
Bit #(8) arlen,
AXI4_Size arsize,
Bit #(2) arburst,
Bit #(1) arlock,
Bit #(4) arcache,
Bit #(3) arprot,
Bit #(4) arqos,
Bit #(4) arregion,
Bit #(wd_user) aruser);
ifc.m_arvalid (arvalid, arid,
fv_addr_translate (araddr),
arlen, arsize, arburst,
arlock, arcache, arprot, arqos, arregion, aruser);
endmethod
method Bool m_arready = ifc.m_arready;

// Rd Data channel
method Bool m_rvalid = ifc.m_rvalid;
method Bit #(wd_id) m_rid = ifc.m_rid;
method Bit #(wd_data) m_rdata = ifc.m_rdata;
method Bit #(2) m_rresp = ifc.m_rresp;
method Bool m_rlast = ifc.m_rlast;
method Bit #(wd_user) m_ruser = ifc.m_ruser;
method Action m_rready (Bool rready);
ifc.m_rready (rready);
endmethod
interface FIFOF_I i_AW;
method Action enq (AXI4_AW #(wd_id, wd_addr, wd_user) aw_in);
action
let aw_out = AXI4_AW {awid: aw_in.awid,
awaddr: fv_addr_translate (aw_in.awaddr),
awlen: aw_in.awlen,
awsize: aw_in.awsize,
awburst: aw_in.awburst,
awlock: aw_in.awlock,
awcache: aw_in.awcache,
awprot: aw_in.awprot,
awqos: aw_in.awqos,
awregion: aw_in.awregion,
awuser: aw_in.awuser};
ifc_S.i_AW.enq (aw_out);
endaction
endmethod
method notFull = ifc_S.i_AW.notFull;
endinterface

interface FIFOF_I i_W = ifc_S.i_W;
interface FIFOF_O o_B = ifc_S.o_B;

interface FIFOF_I i_AR;
method Action enq (AXI4_AR #(wd_id, wd_addr, wd_user) ar_in);
action
let ar_out = AXI4_AR {arid: ar_in.arid,
araddr: fv_addr_translate (ar_in.araddr),
arlen: ar_in.arlen,
arsize: ar_in.arsize,
arburst: ar_in.arburst,
arlock: ar_in.arlock,
arcache: ar_in.arcache,
arprot: ar_in.arprot,
arqos: ar_in.arqos,
arregion: ar_in.arregion,
aruser: ar_in.aruser};
ifc_S.i_AR.enq (ar_out);
endaction
endmethod
method notFull = ifc_S.i_AR.notFull;
endinterface

interface FIFOF_O o_R = ifc_S.o_R;
endinterface;
endfunction

Expand Down
Loading

0 comments on commit 154d564

Please sign in to comment.