adding AXI4Lite transactor for now.
authorNeel <neelgala@gmail.com>
Tue, 20 Mar 2018 09:56:52 +0000 (15:26 +0530)
committerNeel <neelgala@gmail.com>
Tue, 20 Mar 2018 09:56:52 +0000 (15:26 +0530)
Need to add TileLink support as well later.

Makefile
src/bsv_lib/AXI4_Lite_Types.bsv [new file with mode: 0644]
src/bsv_lib/Semi_FIFOF.bsv [new file with mode: 0644]
src/bus_transactors.py [new file with mode: 0644]
src/pinmux_generator.py

index b978409ca889823e0223e9fe23c02af537ed08d9..a6ab3bf23fc9de56ebf3df8038a17c15d679c792 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,11 +1,11 @@
 ### Makefile for the cclass project
 
-TOP_MODULE:=mkPinTop
-TOP_FILE:=PinTop.bsv
+TOP_MODULE:=mkbus
+TOP_FILE:=bus.bsv
 TOP_DIR:=./bsv_src/
 WORKING_DIR := $(shell pwd)
 
-BSVINCDIR:= .:%/Prelude:%/Libraries:%/Libraries/BlueNoC:./bsv_src
+BSVINCDIR:= .:%/Prelude:%/Libraries:%/Libraries/BlueNoC:./bsv_src:./src/bsv_lib/
 default: gen_pinmux gen_verilog
 
 check-blue:
diff --git a/src/bsv_lib/AXI4_Lite_Types.bsv b/src/bsv_lib/AXI4_Lite_Types.bsv
new file mode 100644 (file)
index 0000000..fe3457c
--- /dev/null
@@ -0,0 +1,253 @@
+/*
+Copyright (c) 2013, IIT Madras
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+*  Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+*  Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+*  Neither the name of IIT Madras  nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+*/
+// Copyright (c) 2017 Bluespec, Inc.  All Rights Reserved
+
+package AXI4_Lite_Types;
+
+// ================================================================
+// BSV library imports
+
+import FIFOF       :: *;
+import Connectable :: *;
+
+// ----------------
+// BSV additional libs
+
+import Semi_FIFOF :: *;
+
+// ****************************************************************
+// ****************************************************************
+// Section: RTL-level interfaces
+// ****************************************************************
+// ****************************************************************
+
+// ================================================================
+// These are the signal-level interfaces for an AXI4-Lite master.
+// The (*..*) attributes ensure that when bsc compiles this to Verilog,
+// we get exactly the signals specified in the ARM spec.
+
+interface AXI4_Lite_Slave_IFC #(numeric type wd_addr,
+                               numeric type wd_data,
+                               numeric type wd_user);
+   // Wr Addr channel
+   (* always_ready, always_enabled *)
+   method Action m_awvalid ((* port="awvalid" *) Bool           awvalid,    // in
+                           (* port="awaddr" *)  Bit #(wd_addr) awaddr,     // in
+                           (* port="awsize" *)   Bit #(3) awsize,                                              // in
+                           (* port="awuser" *)  Bit #(wd_user) awuser);    // in
+   (* always_ready, result="awready" *)
+   method Bool m_awready;                                                   // out
+
+   // Wr Data channel
+   (* always_ready, always_enabled *)
+   method Action m_wvalid ((* port="wvalid" *) Bool                     wvalid,    // in
+                          (* port="wdata" *)  Bit #(wd_data)           wdata,     // in
+                          (* port="wstrb" *)  Bit #(TDiv #(wd_data,8)) wstrb);    // in
+   (* always_ready, result="wready" *)
+   method Bool m_wready;                                                           // out
+
+   // Wr Response channel
+   (* always_ready, result="bvalid" *)  method Bool           m_bvalid;                                 // out
+   (* always_ready, result="bresp" *)   method Bit #(2)       m_bresp;                                  // out
+   (* always_ready, result="buser" *)   method Bit #(wd_user) m_buser;                                  // out
+   (* always_ready, always_enabled *)   method Action m_bready  ((* port="bready" *)   Bool bready);    // in
+
+   // Rd Addr channel
+   (* always_ready, always_enabled *)
+   method Action m_arvalid ((* port="arvalid" *) Bool           arvalid,    // in
+                           (* port="araddr" *)  Bit #(wd_addr) araddr,     // in
+                                (* port="arsize" *)     Bit #(3)  arsize,        // in
+                           (* port="aruser" *)  Bit #(wd_user) aruser);    // in
+   (* always_ready, result="arready" *)
+   method Bool m_arready;                                                   // out
+
+   // Rd Data channel
+   (* always_ready, result="rvalid" *)  method Bool           m_rvalid;                                 // out
+   (* always_ready, result="rresp" *)   method Bit #(2)       m_rresp;                                  // out
+   (* always_ready, result="rdata" *)   method Bit #(wd_data) m_rdata;                                  // out
+   (* always_ready, result="ruser" *)   method Bit #(wd_user) m_ruser;                                  // out
+   (* always_ready, always_enabled *)   method Action m_rready  ((* port="rready" *)   Bool rready);    // in
+endinterface: AXI4_Lite_Slave_IFC
+// ================================================================
+// Higher-level types for payloads (rather than just bits)
+
+typedef enum { AXI4_LITE_OKAY, AXI4_LITE_EXOKAY, AXI4_LITE_SLVERR, AXI4_LITE_DECERR } AXI4_Lite_Resp
+deriving (Bits, Eq, FShow);
+
+// Write Address channel
+
+typedef struct {
+   Bit #(wd_addr)  awaddr;
+   Bit #(wd_user)  awuser;
+       Bit#(3)                                 awsize;
+   } AXI4_Lite_Wr_Addr #(numeric type wd_addr, numeric type wd_user)
+deriving (Bits, FShow);
+
+// Write Data channel
+
+typedef struct {
+   Bit #(wd_data)             wdata;
+   Bit #(TDiv #(wd_data, 8))  wstrb;
+   } AXI4_Lite_Wr_Data #(numeric type wd_data)
+deriving (Bits, FShow);
+
+// Write Response channel
+
+typedef struct {
+   AXI4_Lite_Resp  bresp;
+   Bit #(wd_user)  buser;
+   } AXI4_Lite_Wr_Resp #(numeric type wd_user)
+deriving (Bits, FShow);
+
+// Read Address channel
+
+typedef struct {
+   Bit #(wd_addr)  araddr;
+   Bit #(wd_user)  aruser;
+       Bit#(3)                  arsize;
+   } AXI4_Lite_Rd_Addr #(numeric type wd_addr, numeric type wd_user)
+deriving (Bits, FShow);
+
+// Read Data channel
+
+typedef struct {
+   AXI4_Lite_Resp  rresp;
+   Bit #(wd_data)  rdata;
+   Bit #(wd_user)  ruser;
+   } AXI4_Lite_Rd_Data #(numeric type wd_data, numeric type wd_user)
+deriving (Bits, FShow);
+
+// ================================================================
+// Slave transactor interface
+
+interface AXI4_Lite_Slave_Xactor_IFC #(numeric type wd_addr,
+                                      numeric type wd_data,
+                                      numeric type wd_user);
+   method Action reset;
+
+   // AXI side
+   interface AXI4_Lite_Slave_IFC #(wd_addr, wd_data, wd_user) axi_side;
+
+   // FIFOF side
+   interface FIFOF_O #(AXI4_Lite_Wr_Addr #(wd_addr, wd_user)) o_wr_addr;
+   interface FIFOF_O #(AXI4_Lite_Wr_Data #(wd_data))          o_wr_data;
+   interface FIFOF_I #(AXI4_Lite_Wr_Resp #(wd_user))          i_wr_resp;
+
+   interface FIFOF_O #(AXI4_Lite_Rd_Addr #(wd_addr, wd_user)) o_rd_addr;
+   interface FIFOF_I #(AXI4_Lite_Rd_Data #(wd_data, wd_user)) i_rd_data;
+endinterface: AXI4_Lite_Slave_Xactor_IFC
+
+// ----------------------------------------------------------------
+// Slave transactor
+
+module mkAXI4_Lite_Slave_Xactor (AXI4_Lite_Slave_Xactor_IFC #(wd_addr, wd_data, wd_user));
+
+   Bool unguarded = True;
+   Bool guarded   = False;
+
+   // These FIFOs are guarded on BSV side, unguarded on AXI side
+   FIFOF #(AXI4_Lite_Wr_Addr #(wd_addr, wd_user)) f_wr_addr <- mkGFIFOF (unguarded, guarded);
+   FIFOF #(AXI4_Lite_Wr_Data #(wd_data))          f_wr_data <- mkGFIFOF (unguarded, guarded);
+   FIFOF #(AXI4_Lite_Wr_Resp #(wd_user))          f_wr_resp <- mkGFIFOF (guarded, unguarded);
+
+   FIFOF #(AXI4_Lite_Rd_Addr #(wd_addr, wd_user)) f_rd_addr <- mkGFIFOF (unguarded, guarded);
+   FIFOF #(AXI4_Lite_Rd_Data #(wd_data, wd_user)) f_rd_data <- mkGFIFOF (guarded, unguarded);
+
+   // ----------------------------------------------------------------
+   // INTERFACE
+
+   method Action reset;
+      f_wr_addr.clear;
+      f_wr_data.clear;
+      f_wr_resp.clear;
+      f_rd_addr.clear;
+      f_rd_data.clear;
+   endmethod
+
+   // AXI side
+   interface axi_side = interface AXI4_Lite_Slave_IFC;
+                          // Wr Addr channel
+                          method Action m_awvalid (Bool           awvalid,
+                                                   Bit #(wd_addr) awaddr,
+                                                        Bit#(3) awsize,
+                                                   Bit #(wd_user) awuser);
+                             if (awvalid && f_wr_addr.notFull)
+                                f_wr_addr.enq (AXI4_Lite_Wr_Addr {awaddr: awaddr,
+                                                                       awsize:awsize,
+                                                                  awuser: awuser});
+                          endmethod
+
+                          method Bool m_awready;
+                             return f_wr_addr.notFull;
+                          endmethod
+
+                          // Wr Data channel
+                          method Action m_wvalid (Bool                      wvalid,
+                                                  Bit #(wd_data)            wdata,
+                                                  Bit #(TDiv #(wd_data, 8)) wstrb);
+                             if (wvalid && f_wr_data.notFull)
+                                f_wr_data.enq (AXI4_Lite_Wr_Data {wdata: wdata, wstrb: wstrb});
+                          endmethod
+
+                          method Bool m_wready;
+                             return f_wr_data.notFull;
+                          endmethod
+
+                          // Wr Response channel
+                          method Bool           m_bvalid = f_wr_resp.notEmpty;
+                          method Bit #(2)       m_bresp  = pack (f_wr_resp.first.bresp);
+                          method Bit #(wd_user) m_buser  = f_wr_resp.first.buser;
+                          method Action m_bready (Bool bready);
+                             if (bready && f_wr_resp.notEmpty)
+                                f_wr_resp.deq;
+                          endmethod
+
+                          // Rd Addr channel
+                          method Action m_arvalid (Bool           arvalid,
+                                                   Bit #(wd_addr) araddr,
+                                                        Bit#(3)                                 arsize,
+                                                   Bit #(wd_user) aruser);
+                             if (arvalid && f_rd_addr.notFull)
+                                f_rd_addr.enq (AXI4_Lite_Rd_Addr {araddr: araddr,
+                                                                       arsize: arsize,
+                                                                  aruser: aruser});
+                          endmethod
+
+                          method Bool m_arready;
+                             return f_rd_addr.notFull;
+                          endmethod
+
+                          // Rd Data channel
+                          method Bool           m_rvalid = f_rd_data.notEmpty;
+                          method Bit #(2)       m_rresp  = pack (f_rd_data.first.rresp);
+                          method Bit #(wd_data) m_rdata  = f_rd_data.first.rdata;
+                          method Bit #(wd_user) m_ruser  = f_rd_data.first.ruser;
+                          method Action m_rready (Bool rready);
+                             if (rready && f_rd_data.notEmpty)
+                                f_rd_data.deq;
+                          endmethod
+                       endinterface;
+
+   // FIFOF side
+   interface o_wr_addr = to_FIFOF_O (f_wr_addr);
+   interface o_wr_data = to_FIFOF_O (f_wr_data);
+   interface i_wr_resp = to_FIFOF_I (f_wr_resp);
+
+   interface o_rd_addr = to_FIFOF_O (f_rd_addr);
+   interface i_rd_data = to_FIFOF_I (f_rd_data);
+endmodule: mkAXI4_Lite_Slave_Xactor
+
+// ================================================================
+
+endpackage
diff --git a/src/bsv_lib/Semi_FIFOF.bsv b/src/bsv_lib/Semi_FIFOF.bsv
new file mode 100644 (file)
index 0000000..a6ace27
--- /dev/null
@@ -0,0 +1,111 @@
+/*
+Copyright (c) 2013, IIT Madras
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+*  Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+*  Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+*  Neither the name of IIT Madras  nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+*/
+// Copyright (c) 2017 Bluespec, Inc.  All Rights Reserved
+
+package Semi_FIFOF;
+
+// ================================================================
+// Separate interfaces for input-side and output-side of FIFOF.
+// Conversion functions to these, from FIFOF interfaces.
+
+// ================================================================
+// BSV library imports
+
+import FIFOF       :: *;
+import Connectable :: *;
+
+// ================================================================
+// Semi-FIFOF interfaces
+
+interface FIFOF_I #(type t);
+   method Action  enq (t x);
+   method Bool    notFull ();
+endinterface
+
+interface FIFOF_O #(type t);
+   method t       first ();
+   method Action  deq ();
+   method Bool    notEmpty ();
+endinterface
+
+// ================================================================
+// Converters from FIFOF
+
+function FIFOF_I #(t) to_FIFOF_I (FIFOF #(t) f);
+   return interface FIFOF_I;
+            method enq (x) = f.enq (x);
+            method notFull = f.notFull;
+         endinterface;
+endfunction
+
+function FIFOF_O #(t) to_FIFOF_O (FIFOF #(t) f);
+   return interface FIFOF_O;
+            method first    = f.first;
+            method deq      = f.deq;
+            method notEmpty = f.notEmpty;
+         endinterface;
+endfunction
+
+// ================================================================
+// Connections
+
+// ----------------
+// FIFOF_O to a FIFOF_I
+
+instance Connectable #(FIFOF_O #(t), FIFOF_I #(t));
+   module mkConnection #(FIFOF_O #(t) fo, FIFOF_I #(t) fi) (Empty);
+      rule rl_connect;
+        fi.enq (fo.first);
+        fo.deq;
+      endrule
+   endmodule
+endinstance
+
+// ----------------
+// FIFOF_O to a FIFOF
+
+instance Connectable #(FIFOF_O #(t), FIFOF #(t));
+   module mkConnection #(FIFOF_O #(t) fo, FIFOF #(t) fi) (Empty);
+      rule rl_connect;
+        fi.enq (fo.first);
+        fo.deq;
+      endrule
+   endmodule
+endinstance
+
+// ----------------
+// FIFOF to a FIFOF_I
+
+instance Connectable #(FIFOF #(t), FIFOF_I #(t));
+   module mkConnection #(FIFOF #(t) fo, FIFOF_I #(t) fi) (Empty);
+      rule rl_connect;
+        fi.enq (fo.first);
+        fo.deq;
+      endrule
+   endmodule
+endinstance
+
+// ================================================================
+// Convenience function combining first/enq
+
+function ActionValue #(t) pop_o (FIFOF_O #(t) f);
+   actionvalue
+      f.deq;
+      return f.first;
+   endactionvalue
+endfunction
+
+// ================================================================
+
+endpackage
diff --git a/src/bus_transactors.py b/src/bus_transactors.py
new file mode 100644 (file)
index 0000000..d8857fe
--- /dev/null
@@ -0,0 +1,42 @@
+
+axi4_lite = '''
+package bus;
+
+  /*=== Project imports ===*/
+  import AXI4_Lite_Types::*;
+  import PinTop::*;
+  import pinmux::*;
+  import Semi_FIFOF::*;
+  /*======================*/
+
+  interface Ifc_bus;
+    interface AXI4_Lite_Slave_IFC #({0}, {1}, 0) axi_side;
+    interface PeripheralSide peripheral_side;
+  endinterface
+
+  module mkbus(Ifc_bus);
+    Ifc_PintTop pintop <-mkPinTop;
+    AXI4_Lite_Slave_Xactor_IFC#({0}, {1}, 0) slave_xactor <-
+                                                    mkAXI4_Lite_Slave_Xactor();
+    rule read_transaction;
+      let req<-pop_o(slave_xactor.o_rd_addr);
+      let {{err,data}}=pintop.read(req.araddr);
+      AXI4_Lite_Rd_Data#({0}, 0) r = AXI4_Lite_Rd_Data {{
+                                  rresp: err?AXI4_LITE_SLVERR:AXI4_LITE_OKAY,
+                                  rdata: zeroExtend(data) , ruser: 0}};
+      slave_xactor.i_rd_data.enq(r);
+    endrule
+
+    rule write_transaction;
+      let addr_req<-pop_o(slave_xactor.o_wr_addr);
+      let data_req<-pop_o(slave_xactor.o_wr_data);
+      let err<-pintop.write(addr_req.awaddr, data_req.wdata);
+      let b = AXI4_Lite_Wr_Resp {{bresp: err?AXI4_LITE_SLVERR:AXI4_LITE_OKAY,
+                                buser: ?}};
+      slave_xactor.i_wr_resp.enq (b);
+    endrule
+    interface axi_side= slave_xactor.axi_side;
+    interface peripheral_side=pintop.peripheral_side;
+  endmodule
+endpackage
+'''
index 3e216c2eba5d2ae76612a54f5df20b869416fbb1..1fb7df2ed46faaf8f8e05a09a16686d76aed2d8e 100644 (file)
@@ -27,6 +27,7 @@ from interface_def import *
 from parse import *
 from wire_def import *
 from actual_pinmux import *
+from bus_transactors import *
 
 if not os.path.exists("bsv_src"):
     os.makedirs("bsv_src")
@@ -301,3 +302,8 @@ bsv_file.write('''
 endpackage
 ''')
 bsv_file.close
+# ######## Generate bus transactors ################
+bsv_file = open('bsv_src/bus.bsv', 'w')
+bsv_file.write(axi4_lite.format(ADDR_WIDTH, DATA_WIDTH))
+bsv_file.close
+# ##################################################