From: Luke Kenneth Casson Leighton Date: Fri, 23 Mar 2018 16:43:44 +0000 (+0000) Subject: move pinmux generator function to src/bsv directory X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=17ab361abe56c3311d39b4141a68aefca09119ca;p=pinmux.git move pinmux generator function to src/bsv directory --- diff --git a/src/bsv/__init__.py b/src/bsv/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/bsv/bsv_lib/AXI4_Lite_Types.bsv b/src/bsv/bsv_lib/AXI4_Lite_Types.bsv new file mode 100644 index 0000000..a1bb465 --- /dev/null +++ b/src/bsv/bsv_lib/AXI4_Lite_Types.bsv @@ -0,0 +1,272 @@ +/* +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/bsv_lib/Semi_FIFOF.bsv b/src/bsv/bsv_lib/Semi_FIFOF.bsv new file mode 100644 index 0000000..08ff7c1 --- /dev/null +++ b/src/bsv/bsv_lib/Semi_FIFOF.bsv @@ -0,0 +1,129 @@ +/* +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/bsv/pinmux_generator.py b/src/bsv/pinmux_generator.py new file mode 100644 index 0000000..7513d68 --- /dev/null +++ b/src/bsv/pinmux_generator.py @@ -0,0 +1,239 @@ +# ================================== Steps to add peripherals ============ +# Step-1: create interface declaration for the peripheral to be added. +# Remember these are interfaces defined for the pinmux and hence +# will be opposite to those defined at the peripheral. +# For eg. the output TX from the UART will be input (method Action) +# for the pinmux. +# These changes will have to be done in interface_decl.py +# Step-2 define the wires that will be required to transfer data from the +# peripheral interface to the IO cell and vice-versa. Create a +# mkDWire for each input/output between the peripheral and the +# pinmux. Also create an implicit wire of GenericIOType for each cell +# that can be connected to a each bit from the peripheral. +# These changes will have to be done in wire_def.py +# Step-3: create the definitions for each of the methods defined above. +# These changes will have to be done in interface_decl.py +# ======================================================================== + +# default module imports +import os +import os.path +import time +import math + +# project module imports +from interface_decl import Interfaces, mux_interface, io_interface +from parse import Parse +from actual_pinmux import init +from bus_transactors import axi4_lite + +copyright = ''' +/* + This BSV file has been generated by the PinMux tool available at: + https://bitbucket.org/casl/pinmux. + + Authors: Neel Gala, Luke + Date of generation: ''' + time.strftime("%c") + ''' +*/ +''' +header = copyright + ''' +package pinmux; + + typedef struct{ + Bit#(1) outputval; // output from core to pad bit7 + Bit#(1) output_en; // output enable from core to pad bit6 + Bit#(1) input_en; // input enable from core to io_cell bit5 + Bit#(1) pullup_en; // pullup enable from core to io_cell bit4 + Bit#(1) pulldown_en; // pulldown enable from core to io_cell bit3 + Bit#(1) drivestrength; // drivestrength from core to io_cell bit2 + Bit#(1) pushpull_en; // pushpull enable from core to io_cell bit1 + Bit#(1) opendrain_en; // opendrain enable form core to io_cell bit0 + } GenericIOType deriving(Eq,Bits,FShow); + +''' +footer = ''' + endinterface; + endmodule +endpackage +''' + + +def pinmuxgen(pth=None, verify=True): + """ populating the file with the code + """ + + p = Parse(pth, verify) + init(p) + ifaces = Interfaces(pth) + ifaces.ifaceadd('io', p.N_IO, io_interface, 0) + + bp = 'bsv_src' + if pth: + bp = os.path.join(pth, bp) + if not os.path.exists(bp): + os.makedirs(bp) + + pmp = os.path.join(bp, 'pinmux.bsv') + ptp = os.path.join(bp, 'PinTop.bsv') + bvp = os.path.join(bp, 'bus.bsv') + + # package and interface declaration followed by + # the generic io_cell definition + with open(pmp, "w") as bsv_file: + bsv_file.write(header) + + bsv_file.write('''\ + interface MuxSelectionLines; + + // declare the method which will capture the user pin-mux + // selection values.The width of the input is dependent on the number + // of muxes happening per IO. For now we have a generalized width + // where each IO will have the same number of muxes.''') + + for cell in p.muxed_cells: + cnum = int(math.log(len(cell) - 1, 2)) + bsv_file.write(mux_interface.ifacefmt(cell[0], cnum)) + + bsv_file.write(''' + endinterface + + interface PeripheralSide; + // declare the interface to the IO cells. + // Each IO cell will have 8 input field (output from pin mux + // and on output field (input to pinmux)''') + # ============================================================== + + # == create method definitions for all peripheral interfaces ==# + ifaces.ifacefmt(bsv_file) + + # ============================================================== + + # ===== finish interface definition and start module definition======= + bsv_file.write(''' + endinterface + + interface Ifc_pinmux; + interface MuxSelectionLines mux_lines; + interface PeripheralSide peripheral_side; + endinterface + (*synthesize*) + module mkpinmux(Ifc_pinmux); +''') + # ==================================================================== + + # ======================= create wire and registers =================# + bsv_file.write(''' + // the followins wires capture the pin-mux selection + // values for each mux assigned to a CELL +''') + for cell in p.muxed_cells: + bsv_file.write(mux_interface.wirefmt( + cell[0], int(math.log(len(cell) - 1, 2)))) + + ifaces.wirefmt(bsv_file) + + bsv_file.write("\n") + # ==================================================================== + # ========================= Actual pinmuxing ========================# + bsv_file.write(''' + /*====== This where the muxing starts for each io-cell======*/ +''') + bsv_file.write(p.pinmux) + bsv_file.write(''' + /*============================================================*/ +''') + # ==================================================================== + # ================= interface definitions for each method =============# + bsv_file.write(''' + interface mux_lines = interface MuxSelectionLines +''') + for cell in p.muxed_cells: + bsv_file.write(mux_interface.ifacedef(cell[0], + int(math.log(len(cell) - 1, 2)))) + bsv_file.write(''' + endinterface; + interface peripheral_side = interface PeripheralSide +''') + ifaces.ifacedef(bsv_file) + bsv_file.write(footer) + print("BSV file successfully generated: bsv_src/pinmux.bsv") + # ====================================================================== + + with open(ptp, 'w') as bsv_file: + bsv_file.write(copyright + ''' +package PinTop; + import pinmux::*; + interface Ifc_PintTop; + method ActionValue#(Bool) write(Bit#({0}) addr, Bit#({1}) data); + method Tuple2#(Bool,Bit#({1})) read(Bit#({0}) addr); + interface PeripheralSide peripheral_side; + endinterface + + module mkPinTop(Ifc_PintTop); + // instantiate the pin-mux module here + Ifc_pinmux pinmux <-mkpinmux; + + // declare the registers which will be used to mux the IOs +'''.format(p.ADDR_WIDTH, p.DATA_WIDTH)) + + for cell in p.muxed_cells: + bsv_file.write(''' + Reg#(Bit#({0})) rg_muxio_{1} <-mkReg(0);'''.format( + int(math.log(len(cell) - 1, 2)), cell[0])) + + bsv_file.write(''' + // rule to connect the registers to the selection lines of the + // pin-mux module + rule connect_selection_registers;''') + + for cell in p.muxed_cells: + bsv_file.write(''' + pinmux.mux_lines.cell{0}_mux(rg_muxio_{0});'''.format(cell[0])) + + bsv_file.write(''' + endrule + // method definitions for the write user interface + method ActionValue#(Bool) write(Bit#({2}) addr, Bit#({3}) data); + Bool err=False; + case (addr[{0}:{1}])'''.format(p.upper_offset, p.lower_offset, + p.ADDR_WIDTH, p.DATA_WIDTH)) + index = 0 + for cell in p.muxed_cells: + bsv_file.write(''' + {0}: rg_muxio_{1}<=truncate(data);'''.format(index, cell[0])) + index = index + 1 + + bsv_file.write(''' + default: err=True; + endcase + return err; + endmethod''') + + bsv_file.write(''' + // method definitions for the read user interface + method Tuple2#(Bool,Bit#({3})) read(Bit#({2}) addr); + Bool err=False; + Bit#(32) data=0; + case (addr[{0}:{1}])'''.format(p.upper_offset, p.lower_offset, + p.ADDR_WIDTH, p.DATA_WIDTH)) + index = 0 + for cell in p.muxed_cells: + bsv_file.write(''' + {0}: data=zeroExtend(rg_muxio_{1});'''.format(index, cell[0])) + index = index + 1 + + bsv_file.write(''' + default:err=True; + endcase + return tuple2(err,data); + endmethod + interface peripheral_side=pinmux.peripheral_side; + endmodule +endpackage +''') + + # ######## Generate bus transactors ################ + with open(bvp, 'w') as bsv_file: + bsv_file.write(axi4_lite.format(p.ADDR_WIDTH, p.DATA_WIDTH)) + # ################################################## + diff --git a/src/bsv_lib/AXI4_Lite_Types.bsv b/src/bsv_lib/AXI4_Lite_Types.bsv deleted file mode 100644 index a1bb465..0000000 --- a/src/bsv_lib/AXI4_Lite_Types.bsv +++ /dev/null @@ -1,272 +0,0 @@ -/* -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 deleted file mode 100644 index 08ff7c1..0000000 --- a/src/bsv_lib/Semi_FIFOF.bsv +++ /dev/null @@ -1,129 +0,0 @@ -/* -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/pinmux_generator.py b/src/pinmux_generator.py index 661060f..407314c 100644 --- a/src/pinmux_generator.py +++ b/src/pinmux_generator.py @@ -17,231 +17,15 @@ # default module imports import getopt -import os import os.path import sys -import time -import math - -# project module imports -from interface_decl import Interfaces, mux_interface, io_interface -from parse import Parse -from actual_pinmux import init -from bus_transactors import axi4_lite - -copyright = ''' -/* - This BSV file has been generated by the PinMux tool available at: - https://bitbucket.org/casl/pinmux. - - Authors: Neel Gala, Luke - Date of generation: ''' + time.strftime("%c") + ''' -*/ -''' -header = copyright + ''' -package pinmux; - - typedef struct{ - Bit#(1) outputval; // output from core to pad bit7 - Bit#(1) output_en; // output enable from core to pad bit6 - Bit#(1) input_en; // input enable from core to io_cell bit5 - Bit#(1) pullup_en; // pullup enable from core to io_cell bit4 - Bit#(1) pulldown_en; // pulldown enable from core to io_cell bit3 - Bit#(1) drivestrength; // drivestrength from core to io_cell bit2 - Bit#(1) pushpull_en; // pushpull enable from core to io_cell bit1 - Bit#(1) opendrain_en; // opendrain enable form core to io_cell bit0 - } GenericIOType deriving(Eq,Bits,FShow); - -''' -footer = ''' - endinterface; - endmodule -endpackage -''' - - -def pinmuxgen(pth=None, verify=True): - """ populating the file with the code - """ - - p = Parse(pth, verify) - init(p) - ifaces = Interfaces(pth) - ifaces.ifaceadd('io', p.N_IO, io_interface, 0) - - bp = 'bsv_src' - if pth: - bp = os.path.join(pth, bp) - if not os.path.exists(bp): - os.makedirs(bp) - - pmp = os.path.join(bp, 'pinmux.bsv') - ptp = os.path.join(bp, 'PinTop.bsv') - bvp = os.path.join(bp, 'bus.bsv') - - # package and interface declaration followed by - # the generic io_cell definition - with open(pmp, "w") as bsv_file: - bsv_file.write(header) - - bsv_file.write('''\ - interface MuxSelectionLines; - - // declare the method which will capture the user pin-mux - // selection values.The width of the input is dependent on the number - // of muxes happening per IO. For now we have a generalized width - // where each IO will have the same number of muxes.''') - - for cell in p.muxed_cells: - cnum = int(math.log(len(cell) - 1, 2)) - bsv_file.write(mux_interface.ifacefmt(cell[0], cnum)) - - bsv_file.write(''' - endinterface - - interface PeripheralSide; - // declare the interface to the IO cells. - // Each IO cell will have 8 input field (output from pin mux - // and on output field (input to pinmux)''') - # ============================================================== - - # == create method definitions for all peripheral interfaces ==# - ifaces.ifacefmt(bsv_file) - - # ============================================================== - - # ===== finish interface definition and start module definition======= - bsv_file.write(''' - endinterface - - interface Ifc_pinmux; - interface MuxSelectionLines mux_lines; - interface PeripheralSide peripheral_side; - endinterface - (*synthesize*) - module mkpinmux(Ifc_pinmux); -''') - # ==================================================================== - - # ======================= create wire and registers =================# - bsv_file.write(''' - // the followins wires capture the pin-mux selection - // values for each mux assigned to a CELL -''') - for cell in p.muxed_cells: - bsv_file.write(mux_interface.wirefmt( - cell[0], int(math.log(len(cell) - 1, 2)))) - - ifaces.wirefmt(bsv_file) - - bsv_file.write("\n") - # ==================================================================== - # ========================= Actual pinmuxing ========================# - bsv_file.write(''' - /*====== This where the muxing starts for each io-cell======*/ -''') - bsv_file.write(p.pinmux) - bsv_file.write(''' - /*============================================================*/ -''') - # ==================================================================== - # ================= interface definitions for each method =============# - bsv_file.write(''' - interface mux_lines = interface MuxSelectionLines -''') - for cell in p.muxed_cells: - bsv_file.write(mux_interface.ifacedef(cell[0], - int(math.log(len(cell) - 1, 2)))) - bsv_file.write(''' - endinterface; - interface peripheral_side = interface PeripheralSide -''') - ifaces.ifacedef(bsv_file) - bsv_file.write(footer) - print("BSV file successfully generated: bsv_src/pinmux.bsv") - # ====================================================================== - - with open(ptp, 'w') as bsv_file: - bsv_file.write(copyright + ''' -package PinTop; - import pinmux::*; - interface Ifc_PintTop; - method ActionValue#(Bool) write(Bit#({0}) addr, Bit#({1}) data); - method Tuple2#(Bool,Bit#({1})) read(Bit#({0}) addr); - interface PeripheralSide peripheral_side; - endinterface - - module mkPinTop(Ifc_PintTop); - // instantiate the pin-mux module here - Ifc_pinmux pinmux <-mkpinmux; - - // declare the registers which will be used to mux the IOs -'''.format(p.ADDR_WIDTH, p.DATA_WIDTH)) - - for cell in p.muxed_cells: - bsv_file.write(''' - Reg#(Bit#({0})) rg_muxio_{1} <-mkReg(0);'''.format( - int(math.log(len(cell) - 1, 2)), cell[0])) - - bsv_file.write(''' - // rule to connect the registers to the selection lines of the - // pin-mux module - rule connect_selection_registers;''') - - for cell in p.muxed_cells: - bsv_file.write(''' - pinmux.mux_lines.cell{0}_mux(rg_muxio_{0});'''.format(cell[0])) - - bsv_file.write(''' - endrule - // method definitions for the write user interface - method ActionValue#(Bool) write(Bit#({2}) addr, Bit#({3}) data); - Bool err=False; - case (addr[{0}:{1}])'''.format(p.upper_offset, p.lower_offset, - p.ADDR_WIDTH, p.DATA_WIDTH)) - index = 0 - for cell in p.muxed_cells: - bsv_file.write(''' - {0}: rg_muxio_{1}<=truncate(data);'''.format(index, cell[0])) - index = index + 1 - - bsv_file.write(''' - default: err=True; - endcase - return err; - endmethod''') - - bsv_file.write(''' - // method definitions for the read user interface - method Tuple2#(Bool,Bit#({3})) read(Bit#({2}) addr); - Bool err=False; - Bit#(32) data=0; - case (addr[{0}:{1}])'''.format(p.upper_offset, p.lower_offset, - p.ADDR_WIDTH, p.DATA_WIDTH)) - index = 0 - for cell in p.muxed_cells: - bsv_file.write(''' - {0}: data=zeroExtend(rg_muxio_{1});'''.format(index, cell[0])) - index = index + 1 - - bsv_file.write(''' - default:err=True; - endcase - return tuple2(err,data); - endmethod - interface peripheral_side=pinmux.peripheral_side; - endmodule -endpackage -''') - - # ######## Generate bus transactors ################ - with open(bvp, 'w') as bsv_file: - bsv_file.write(axi4_lite.format(p.ADDR_WIDTH, p.DATA_WIDTH)) - # ################################################## +from bsv.pinmux_generator import pinmuxgen as bsvgen def printhelp(): print ('''pinmux_generator.py [-o outputdir] [-v|--validate] [-h|--help] + [-t outputtype] + -t | outputtype : outputtype, defaults to bsv -o outputdir : defaults to bsv_src. also location for reading pinmux.txt interfaces.txt and *.txt -v | --validate : runs some validation on the pinmux @@ -253,9 +37,10 @@ if __name__ == '__main__': try: options, remainder = getopt.getopt( sys.argv[1:], - 'o:vh', + 'o:vht:', ['output=', 'validate', + 'outputtype=', 'help', 'version=', ]) @@ -264,15 +49,24 @@ if __name__ == '__main__': printhelp() sys.exit(1) + output_type = 'bsv' output_dir = None validate = False for opt, arg in options: if opt in ('-o', '--output'): output_dir = arg + elif opt in ('-t', '--outputtype'): + output_type = arg elif opt in ('-v', '--validate'): validate = True elif opt in ('-h', '--help'): printhelp() sys.exit(0) - pinmuxgen(output_dir, validate) + gentypes = {'bsv': bsvgen} + if not gentypes.has_key(output_type): + print "ERROR: output type '%s' does not exist" % output_type + printhelp() + sys.exit(0) + gentypes[output_type](output_dir, validate) +