-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathutil.tcl
120 lines (106 loc) · 3.64 KB
/
util.tcl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
proc clog2 {num} {
set value 0
while {[expr 2 ** $value] < $num} {
incr value
}
return $value
}
# https://wiki.tcl-lang.org/page/Templates+and+subst
proc substify {in {var OUT}} {
set pos 0
foreach pair [regexp -line -all -inline -indices {^%.*$} $in] {
lassign $pair from to
set s [string range $in $pos [expr {$from-2}]]
append script "append $var \[" [list subst $s] "]\n" \
[string range $in [expr {$from+1}] $to] "\n"
set pos [expr {$to+2}]
}
set s [string range $in $pos end]
append script "append $var \[" [list subst $s] "]\n"
}
proc range2mask {high low} {
set mask 0
for {set i $low} {$i <= $high} {incr i} {
set mask [expr $mask | (1 << $i)]
}
return $mask
}
proc get_prefix {specdata clock_name} {
foreach clock [dict get $specdata clocks] {
if {[dict get $clock name] == $clock_name} {
return [dict get $clock prefix]
}
}
return ""
}
# Workaround for the following warning.
# WARNING: [SYN 201-107] Renaming port name 'ExampleIp/Start' to 'ExampleIp/Start_r' to avoid the conflict with HDL keywords or other object names.
# Hardcodes a list of reserved port names and rules to rewrite them. Some initial testing shows that
proc get_hls_portname {bitfield_name} {
set reserved_names [list]
lappend reserved_names "start"
lappend reserved_names "begin"
lappend reserved_names "end"
set idx [lsearch $reserved_names [string tolower $bitfield_name]]
if {$idx != -1} {
# preserve original caps
set bitfield_name "${bitfield_name}_r"
}
return $bitfield_name
}
proc get_register_addresses {specdata} {
set address_info [list]
set newreg [dict create]
dict set newreg name ap_ctrl
dict set newreg width 0x4
dict set newreg offset 0x0
lappend address_info $newreg
set newreg [dict create]
dict set newreg name gie
dict set newreg width 0x4
dict set newreg offset 0x4
lappend address_info $newreg
set newreg [dict create]
dict set newreg name ip_intr_en
dict set newreg width 0x4
dict set newreg offset 0x8
lappend address_info $newreg
set newreg [dict create]
dict set newreg name ip_intr_sts
dict set newreg width 0x4
dict set newreg offset 0xc
lappend address_info $newreg
set offset 0x10
foreach register [dict get $specdata registers] {
set newreg [dict create]
dict set newreg name [dict get $register name]
set width 8
dict set newreg width $width
dict set newreg offset $offset
set offset [format 0x%x [expr $offset + $width]]
lappend address_info $newreg
}
return $address_info
}
proc find_register_offset_by_name {return_var address_info register_name} {
global $return_var
foreach address $address_info {
puts $address
if {[dict get $address name] == $register_name} {
set $return_var [dict get $address offset]
return 0
}
}
return -1
}
proc get_num_words_in_address_space {specdata} {
set interface [dict get $specdata axi4lite_interface]
set reserved_addresses [dict get $interface reserved_addresses]
set num_regs [llength [dict get $specdata registers]]
return [expr $reserved_addresses + ($num_regs * 2)]
}
proc get_axi4lite_interface_addr_width {specdata} {
# HLS reserves 64 bits for each register for the user register file and 32 bits for each of its own registers, regardless of the actual used register size
set bytes_per_word 4
return [clog2 [expr [get_num_words_in_address_space $specdata] * $bytes_per_word]]
}