getting bsv compile working
[pinmux.git] / src / bsv / pinmux_generator.py
index 7a01fb33ccfc8589f3c029fbd93e27b0f3b681d0..9657c95a3b896aff8d615bfc53db124f5f046a1d 100644 (file)
 # ========================================================================
 
 # default module imports
+import shutil
 import os
 import os.path
 import time
-import math
 
 # project module imports
 from bsv.interface_decl import Interfaces, mux_interface, io_interface
@@ -39,20 +39,8 @@ copyright = '''
 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
 '''
@@ -63,8 +51,10 @@ def pinmuxgen(pth=None, verify=True):
     """
 
     p = Parse(pth, verify)
+    iocells = Interfaces()
+    iocells.ifaceadd('io', p.N_IO, io_interface, 0)
     ifaces = Interfaces(pth)
-    ifaces.ifaceadd('io', p.N_IO, io_interface, 0)
+    #ifaces.ifaceadd('io', p.N_IO, io_interface, 0)
     init(p, ifaces)
 
     bp = 'bsv_src'
@@ -72,13 +62,27 @@ def pinmuxgen(pth=None, verify=True):
         bp = os.path.join(pth, bp)
     if not os.path.exists(bp):
         os.makedirs(bp)
+    bl = os.path.join(bp, 'bsv_lib')
+    if not os.path.exists(bl):
+        os.makedirs(bl)
+
+    cwd = os.path.split(__file__)[0]
+
+    # copy over template and library files
+    shutil.copyfile(os.path.join(cwd, 'Makefile.template'),
+                    os.path.join(bp, 'Makefile'))
+    cwd = os.path.join(cwd, 'bsv_lib')
+    for fname in ['AXI4_Lite_Types.bsv', 'Semi_FIFOF.bsv', 
+                  'gpio.bsv',  'mux.bsv']:
+        shutil.copyfile(os.path.join(cwd, fname),
+                        os.path.join(bl, fname))
 
     bus = os.path.join(bp, 'busenable.bsv')
     pmp = os.path.join(bp, 'pinmux.bsv')
     ptp = os.path.join(bp, 'PinTop.bsv')
     bvp = os.path.join(bp, 'bus.bsv')
 
-    write_pmp(pmp, p, ifaces)
+    write_pmp(pmp, p, ifaces, iocells)
     write_ptp(ptp, p, ifaces)
     write_bvp(bvp, p, ifaces)
     write_bus(bus, p, ifaces)
@@ -91,12 +95,13 @@ def write_bus(bus, p, ifaces):
         ifaces.busfmt(bsv_file)
 
 
-def write_pmp(pmp, p, ifaces):
+def write_pmp(pmp, p, ifaces, iocells):
     # package and interface declaration followed by
     # the generic io_cell definition
     with open(pmp, "w") as bsv_file:
         bsv_file.write(header)
 
+        cell_bit_width = 'Bit#(%d)' % p.cell_bitwidth
         bsv_file.write('''\
    interface MuxSelectionLines;
 
@@ -106,30 +111,64 @@ def write_pmp(pmp, p, ifaces):
       // where each IO will have the same number of muxes.''')
 
         for cell in p.muxed_cells:
-            cnum = 'Bit#(' + str(int(math.log(len(cell) - 1, 2))) + ')'
-            bsv_file.write(mux_interface.ifacefmt(cell[0], cnum))
+            bsv_file.write(mux_interface.ifacefmt(cell[0], cell_bit_width))
+
+        bsv_file.write("\n      endinterface\n")
 
         bsv_file.write('''
-      endinterface
 
-      interface PeripheralSide;
+      interface IOCellSide;
       // 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)''')
+      // Each IO cell will have 1 input field (output from pin mux)
+      // and an output and out-enable field (input to pinmux)''')
+
+        # == create method definitions for all iocell interfaces ==#
+        iocells.ifacefmt(bsv_file)
+
+        # ===== finish interface definition and start module definition=======
+        bsv_file.write("\n      endinterface\n")
+
+        # ===== io cell definition =======
+        bsv_file.write('''
+
+      interface PeripheralSide;
+      // declare the interface to the peripherals
+      // Each peripheral's function will be either an input, output
+      // or be bi-directional.  an input field will be an output from the
+      // peripheral and an output field will be an input to the peripheral.
+      // Bi-directional functions also have an output-enable (which
+      // again comes *in* from the peripheral)''')
         # ==============================================================
 
         # == create method definitions for all peripheral interfaces ==#
         ifaces.ifacefmt(bsv_file)
-
-        # ==============================================================
+        bsv_file.write("\n      endinterface\n")
 
         # ===== finish interface definition and start module definition=======
         bsv_file.write('''
-   endinterface
 
    interface Ifc_pinmux;
+      // this interface controls how each IO cell is routed.  setting
+      // any given IO cell's mux control value will result in redirection
+      // of not just the input or output to different peripheral functions
+      // but also the *direction* control - if appropriate - as well.
       interface MuxSelectionLines mux_lines;
+
+      // this interface contains the inputs, outputs and direction-control
+      // lines for all peripherals.  GPIO is considered to also be just
+      // a peripheral because it also has in, out and direction-control.
       interface PeripheralSide peripheral_side;
+
+      // this interface is to be linked to the individual IO cells.
+      // if looking at a "non-muxed" GPIO design, basically the
+      // IO cell input, output and direction-control wires are cut
+      // (giving six pairs of dangling wires, named left and right)
+      // these iocells are routed in their place on one side ("left")
+      // and the matching *GPIO* peripheral interfaces in/out/dir
+      // connect to the OTHER side ("right").  the result is that
+      // the muxer settings end up controlling the routing of where
+      // the I/O from the IOcell actually goes.
+      interface IOCellSide iocell_side;
    endinterface
    (*synthesize*)
    module mkpinmux(Ifc_pinmux);
@@ -141,15 +180,11 @@ def write_pmp(pmp, p, ifaces):
       // the followins wires capture the pin-mux selection
       // values for each mux assigned to a CELL
 ''')
-        max_num_cells = 0
-        for cell in p.muxed_cells:
-                max_num_cells = max(len(cell)-1, max_num_cells)
-        cell_bit_width = 'Bit#(%d)' %int(math.log(max_num_cells, 2))
-
         for cell in p.muxed_cells:
             bsv_file.write(mux_interface.wirefmt(
                 cell[0], cell_bit_width))
 
+        iocells.wirefmt(bsv_file)
         ifaces.wirefmt(bsv_file)
 
         bsv_file.write("\n")
@@ -157,6 +192,7 @@ def write_pmp(pmp, p, ifaces):
         # ========================= Actual pinmuxing ========================#
         bsv_file.write('''
       /*====== This where the muxing starts for each io-cell======*/
+      Wire#(Bit#(1)) val0<-mkDWire(0); // need a zero
 ''')
         bsv_file.write(p.pinmux)
         bsv_file.write('''
@@ -170,14 +206,21 @@ def write_pmp(pmp, p, ifaces):
         for cell in p.muxed_cells:
             bsv_file.write(
                 mux_interface.ifacedef(
-                    cell[0], 'Bit#(' + str(int(
-                        math.log(
-                            len(cell) - 1, 2))) + ')'))
+                    cell[0], cell_bit_width))
+        bsv_file.write("\n    endinterface;")
+
+        bsv_file.write('''
+    interface iocell_side = interface IOCellSide
+''')
+        iocells.ifacedef(bsv_file)
+        bsv_file.write("\n     endinterface;")
+
         bsv_file.write('''
-    endinterface;
     interface peripheral_side = interface PeripheralSide
 ''')
         ifaces.ifacedef(bsv_file)
+        bsv_file.write("\n     endinterface;")
+
         bsv_file.write(footer)
         print("BSV file successfully generated: bsv_src/pinmux.bsv")
         # ======================================================================
@@ -201,10 +244,11 @@ package PinTop;
         // declare the registers which will be used to mux the IOs
 '''.format(p.ADDR_WIDTH, p.DATA_WIDTH))
 
+        cell_bit_width = str(p.cell_bitwidth)
         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]))
+                cell_bit_width, cell[0]))
 
         bsv_file.write('''
         // rule to connect the registers to the selection lines of the
@@ -260,6 +304,44 @@ endpackage
 
 def write_bvp(bvp, p, ifaces):
     # ######## Generate bus transactors ################
+    gpiocfg = '\t\tinterface GPIO_config#({4}) bank{3}_config;\n' \
+              '\t\tinterface AXI4_Lite_Slave_IFC#({0},{1},{2}) bank{3}_slave;'
+    muxcfg = '\t\tinterface MUX_config#({4}) muxb{3}_config;\n' \
+        '\t\tinterface AXI4_Lite_Slave_IFC#({0},{1},{2}) muxb{3}_slave;'
+
+    gpiodec = '\tGPIO#({0}) mygpio{1} <- mkgpio();'
+    muxdec = '\tMUX#({0}) mymux{1} <- mkgpio();'
+    gpioifc = '\tinterface bank{0}_config=mygpio{0}.pad_config;\n' \
+              '\tinterface bank{0}A_slave=mygpio{0}.axi_slave;'
+    muxifc = '\tinterface muxb{0}_config=mymux{0}.pad_config;\n' \
+        '\tinterface muxb{0}A_slave=mymux{0}.axi_slave;'
     with open(bvp, 'w') as bsv_file:
-        bsv_file.write(axi4_lite.format(p.ADDR_WIDTH, p.DATA_WIDTH))
+        # assume here that all muxes have a 1:1 gpio
+        cfg = []
+        decl = []
+        idec = []
+        iks = sorted(ifaces.keys())
+        for iname in iks:
+            if not iname.startswith('gpio'):  # TODO: declare other interfaces
+                continue
+            bank = iname[4:]
+            ifc = ifaces[iname]
+            npins = len(ifc.pinspecs)
+            cfg.append(gpiocfg.format(p.ADDR_WIDTH, p.DATA_WIDTH,
+                                      0,  # USERSPACE
+                                      bank, npins))
+            cfg.append(muxcfg.format(p.ADDR_WIDTH, p.DATA_WIDTH,
+                                     0,  # USERSPACE
+                                     bank, npins))
+            decl.append(gpiodec.format(npins, bank))
+            decl.append(muxdec .format(npins, bank))
+            idec.append(gpioifc.format(bank))
+            idec.append(muxifc.format(bank))
+        print dir(ifaces)
+        print ifaces.items()
+        print dir(ifaces['gpioa'])
+        print ifaces['gpioa'].pinspecs
+        gpiodecl = '\n'.join(decl) + '\n' + '\n'.join(idec)
+        gpiocfg = '\n'.join(cfg)
+        bsv_file.write(axi4_lite.format(gpiodecl, gpiocfg))
     # ##################################################