zynq-sandbox

old FPGA projects for ZYNQ
git clone http://frotz.net/git/zynq-sandbox.git
Log | Files | Refs | README

mkzynq.go (5354B)


      1 // Copyright 2014 Brian Swetland <swetland@frotz.net>
      2 //
      3 // Licensed under the Apache License, Version 2.0 (the "License");
      4 // you may not use this file except in compliance with the License.
      5 // You may obtain a copy of the License at
      6 //
      7 //     http://www.apache.org/licenses/LICENSE-2.0
      8 //
      9 // Unless required by applicable law or agreed to in writing, software
     10 // distributed under the License is distributed on an "AS IS" BASIS,
     11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     12 // See the License for the specific language governing permissions and
     13 // limitations under the License.
     14 
     15 // Tool to generate a SystemVerilog wrapper around the Xilinx Zynq PS7 Macro
     16 
     17 package main
     18 
     19 import "flag"
     20 import "os"
     21 import "bufio"
     22 import "strings"
     23 import "strconv"
     24 import "fmt"
     25 
     26 type net struct {
     27 	next *net
     28 	kind string
     29 	def string
     30 	name string
     31 	value string
     32 }
     33 
     34 const (
     35 	SIMPLE_FIXUP = 1
     36 	PREFIX_FIXUP = 2
     37 )
     38 
     39 type fixup struct {
     40 	next *fixup
     41 	pattern string
     42 	mapping string
     43 	kind int
     44 }
     45 
     46 func fixup_nets(netlist *net, fixups *fixup) {
     47 	for n := netlist; n != nil; n = n.next {
     48 		for f := fixups; f != nil; f = f.next {
     49 			if (f.kind == PREFIX_FIXUP) && strings.HasPrefix(n.name, f.pattern) {
     50 				n.value = f.mapping + strings.ToLower(strings.TrimPrefix(n.name, f.pattern))
     51 				goto fixedup
     52 			}
     53 			if (f.kind == SIMPLE_FIXUP) && (n.name == f.pattern) {
     54 				n.value = f.mapping
     55 				goto fixedup
     56 			}
     57 		}
     58 		// tie off unmapped input nets
     59 		if n.kind == "input" {
     60 			n.value = "0"
     61 		}
     62 fixedup:
     63 	}
     64 }
     65 
     66 // extract  input|output|inout [...] <name>;  lines from blackbox macro verilog source
     67 
     68 func load_template(fn string) *net {
     69 	var netlist *net
     70 	file, _ := os.Open(fn)
     71 	scanner := bufio.NewScanner(file)
     72 	for scanner.Scan() {
     73 		line := scanner.Text()
     74 		line = strings.TrimSpace(line)
     75 		if !strings.HasSuffix(line, ";") {
     76 			continue
     77 		}
     78 		line = line[:len(line)-1]
     79 		parts := strings.Split(line, " ");
     80 		if (parts[0] != "input") && (parts[0] != "output") && (parts[0] != "inout") {
     81 			continue;
     82 		}
     83 		if (len(parts) == 3) {
     84 			netlist = &net{
     85 				next: netlist,
     86 				kind: parts[0],
     87 				def: parts[1],
     88 				name: parts[2],
     89 			}
     90 		} else if (len(parts) == 2) {
     91 			netlist = &net{
     92 				next: netlist,
     93 				kind: parts[0],
     94 				def: "",
     95 				name: parts[1],
     96 			}
     97 		} else {
     98 			continue;
     99 		}
    100 	}
    101 	return netlist
    102 }
    103 
    104 var axi_m_gp = flag.Int("axi-master-gp", 0, "number of gp axi master ifcs (0-2)")
    105 var axi_s_gp = flag.Int("axi-slave-gp", 0, "number of gp axi slave ifcs (0-2)")
    106 var axi_s_hp = flag.Int("axi-slave-hp", 0, "number of gp axi slave ifcs (0-4)")
    107 var fclks = flag.Int("fclks", 1, "number of clocks from PS")
    108 var tmpl = flag.String("template", "PS7.v", "template for PS7 macro")
    109 
    110 var fixups *fixup
    111 var ports *net
    112 
    113 func mkport(kind string, def string, name string) {
    114 	ports = &net{
    115 		next: ports,
    116 		kind: kind,
    117 		def: def,
    118 		name: name,
    119 		}
    120 }
    121 
    122 func prefix_fixup(prefix string, mapping string) {
    123 	fixups = &fixup {
    124 		next: fixups,
    125 		kind: PREFIX_FIXUP,
    126 		pattern: prefix,
    127 		mapping: mapping,
    128 	}
    129 }
    130 
    131 func simple_fixup(prefix string, mapping string) {
    132 	fixups = &fixup {
    133 		next: fixups,
    134 		kind: SIMPLE_FIXUP,
    135 		pattern: prefix,
    136 		mapping: mapping,
    137 	}
    138 }
    139 
    140 func fixup_axi(count int, prefix string, mapping string, kind string) {
    141 	defval := ""
    142 	if (kind == "axi_ifc.slave") {
    143 		defval = "0"
    144 	}
    145 	for n := 1; n <= count; n++ {
    146 		num := strconv.Itoa(n-1)
    147 		prefix_fixup(prefix + num, mapping + num + ".")
    148 		simple_fixup(prefix + num + "ACLK", mapping + num + "_clk")
    149 		simple_fixup(prefix + num + "AWQOS", defval)
    150 		simple_fixup(prefix + num + "ARQOS", defval)
    151 		simple_fixup(prefix + num + "AWPROT", defval)
    152 		simple_fixup(prefix + num + "ARPROT", defval)
    153 		simple_fixup(prefix + num + "WID", defval)
    154 		simple_fixup(prefix + num + "ARESETN", "")
    155 		simple_fixup(prefix + num + "WRISSUECAP1EN", "0")
    156 		simple_fixup(prefix + num + "RDISSUECAP1EN", "0")
    157 		simple_fixup(prefix + num + "WACOUNT", "")
    158 		simple_fixup(prefix + num + "RACOUNT", "")
    159 		simple_fixup(prefix + num + "WCOUNT", "")
    160 		simple_fixup(prefix + num + "RCOUNT", "")
    161 		mkport(kind, "", mapping + num)
    162 		mkport("input", "", mapping + num + "_clk")
    163 	}
    164 }
    165 
    166 func main() {
    167 	flag.Parse()
    168 
    169 	netlist := load_template(*tmpl)
    170 
    171 	fixup_axi(*axi_m_gp, "MAXIGP", "m_axi_gp", "axi_ifc.master")
    172 	fixup_axi(*axi_s_gp, "SAXIGP", "s_axi_gp", "axi_ifc.slave")
    173 	fixup_axi(*axi_s_hp, "SAXIHP", "s_axi_hp", "axi_ifc.slave")
    174 
    175 	// route clocks out from PS7
    176 	simple_fixup("FCLKCLK", "{ fclk3_i, fclk2_i, fclk1_i, fclk0_i }")
    177 	for n := 0; n < *fclks; n++ {
    178 		mkport("output", "", "fclk" + strconv.Itoa(n))
    179 	}
    180 
    181 	fixup_nets(netlist, fixups)
    182 
    183 	fmt.Printf("// machine-generated by mkzynq.go - do not edit\n")
    184 	fmt.Printf("`timescale 1ns / 1ps\n\n")
    185 	fmt.Printf("module zynq_ps7(\n")
    186 	for p := ports; p != nil; p = p.next {
    187 		if p.next != nil {
    188 			fmt.Printf("\t%s %s,\n", p.kind, p.name)
    189 		} else {
    190 			fmt.Printf("\t%s %s\n", p.kind, p.name)
    191 		}
    192 	}
    193 	fmt.Printf("\t);\n\n")
    194 
    195 	// global buffers for active clocks from PS
    196 	fmt.Printf("wire fclk0_i, fclk1_i, fclk2_i, fclk3_i;\n\n")
    197 	for n := 0; n < *fclks; n++ {
    198 		fmt.Printf("BUFG fclk%d_bufg(.I(fclk%d_i), .O(fclk%d));\n", n, n, n);
    199 	}
    200 
    201 	fmt.Printf("\nPS7 ps7_i(\n")
    202 	for n := netlist; n != nil; n = n.next {
    203 		if n.next != nil {
    204 			fmt.Printf("\t.%s(%s),\n", n.name, n.value)
    205 		} else {
    206 			fmt.Printf("\t.%s(%s)\n", n.name, n.value)
    207 		}
    208 	}
    209 	fmt.Printf("\t);\n\nendmodule\n")
    210 }
    211