import os
import os.path
import time
-import math
# project module imports
from bsv.interface_decl import Interfaces, mux_interface, io_interface
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
'''
"""
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'
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']:
+ 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))
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)
ifaces.busfmt(bsv_file)
-def get_cell_bit_width(p):
- max_num_cells = 0
- for cell in p.muxed_cells:
- max_num_cells = max(len(cell) - 1, max_num_cells)
- return int(math.log(max_num_cells, 2))
-
-
-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;
// 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);
// the followins wires capture the pin-mux selection
// values for each mux assigned to a CELL
''')
- cell_bit_width = 'Bit#(%d)' % get_cell_bit_width(p)
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")
# ========================= 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('''
bsv_file.write(
mux_interface.ifacedef(
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")
# ======================================================================
// declare the registers which will be used to mux the IOs
'''.format(p.ADDR_WIDTH, p.DATA_WIDTH))
- cell_bit_width = str(get_cell_bit_width(p))
+ 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(
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))
# ##################################################