build_fiu_vhd.tcl 8.14 KB
Newer Older
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
#-------------------------------------------------------------------------------
#  University of Applied Sciences Technikum Wien
#
#  Department of Embedded Systems
#  http://embsys.technikum-wien.at
#
#  Josef Ressel Center for Verification of Embedded Computing Systems
#  http://vecs.technikum-wien.at
#
#-------------------------------------------------------------------------------
#  Description:
#
#  Parametrizable generation static FIU configuration vhdl packages for
#  top testbench
#
#  procedure build_fiu_list_from_cfg:
#  Uses cfg (INI) files for the config with the following format:
#  
#  [CONSTS]
#  FREQUENCY=<Clock frequency in Hz>
#  TIMER_WIDTH=<Timer Width in Bits>
#  BAUDRATE=<Baud rate in 1/s>
#  FIU_NUM=<Number of FIU blocks>
#
#  [FIUx]
#  FAULT_MODEL=<Fault Model to implement by this fiu {RUNTIME|STUCK_AT_0|STUCK_AT_1|SEU|DELAY|STUCK_OPEN|PASSTHROUGH}>
#  LFSR_BIT_FOR_STUCK_OPEN=<Which bit of the LFSR is taken as "random" source for stuck-open {0...15}>
#  LFSR_MASK=<Which bits are ANDed together for stuck at open {X"0000" ... X"FFFF"}>
#
#-------------------------------------------------------------------------------

if { [namespace exists inidict] == 0 } {
    source inidict.tcl
}

#! generate a VHDL package file from a cfg (INI) file

proc build_config_pkg_from_cfg {global_pkg_file_name cfg_file_name} {

    set cfgdict [dict create]
    set fiu_list [list ]

    # try to open/parse the supplied INI file
    if { [catch {inidict::readfile $cfg_file_name cfgdict} fid] } {
        echo "Couldn't open file: $fid"
        return -1
    }

    # the consts section contains the timer widths, clock frequency and baud rate
    
    set FREQUENCY 5000000000
    set TIMER_WIDTH       32
    set BAUDRATE      115200
    set FIU_NUM            0
55
    set FAULT_DETECT_INVERT_MASK 0
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71

    if { [dict exists $cfgdict "CONSTS"] } {
        set consts [dict get $cfgdict "CONSTS"]

        if { [catch { set FREQUENCY [dict get $consts "FREQUENCY"] } ] } {
            echo "Could not retrieve FREQUENCY from CONSTS section"
        }
        if { [catch { set TIMER_WIDTH [dict get $consts "TIMER_WIDTH"] } ] } {
            echo "Could not retrieve TIMER_WIDTH from CONSTS section"
        }
        if { [catch { set BAUDRATE [dict get $consts "BAUDRATE"] } ] } {
            echo "Could not retrieve BAUDRATE from CONSTS section"
        }
        if { [catch { set  FIU_NUM [dict get $consts "FIU_NUM"] } ] } {
            echo "Could not retrieve  FIU_NUM from CONSTS section"
        }
72
73
74
        if { [catch { set  FAULT_DETECT_INVERT_MASK [dict get $consts "FAULT_DETECT_INVERT_MASK"] } ] } {
            echo "Could not retrieve  FAULT_DETECT_INVERT_MASK from CONSTS section"
        }
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

    } else {
        echo "Invalid config file: no CONSTS section."
        echo "Defaults used."
    }


    # each section represents an FIU
    set fiu_idx 0

    while { [dict exists $cfgdict "FIU$fiu_idx"] } {

        set fiu_name "FIU$fiu_idx"

        set fiu [dict get $cfgdict $fiu_name]

        set FAULT_MODEL "PASS_THRU"
        set LFSR_MASK 0

        if { [catch { set FAULT_MODEL [dict get $fiu "FAULT_MODEL"] } ] } {
            echo "Could not retrieve FAULT_MODEL from $fiu_name section"
        }
        if { [catch { set  LFSR_MASK [dict get $fiu "LFSR_MASK"] } ] } {
            echo "Could not retrieve LFSR_MASK from $fiu_name section"
        }

        # append the current FIU's configuration to the FIU list
        lappend fiu_list $FAULT_MODEL $LFSR_MASK

        incr fiu_idx
    }

    if { $FIU_NUM != $fiu_idx } {
        echo "Configuration inconsistent: CONSTS/FIU_NUM does not equal number of [FIU*] sections "
    }


112
    set id [build_global_cfg_pkg $global_pkg_file_name $TIMER_WIDTH $FREQUENCY $BAUDRATE $FAULT_DETECT_INVERT_MASK $fiu_list]
113
114
115
116
117

    return $id

}

118
proc build_global_cfg_pkg {file_name timer_width fclk baud fault_detect fiu_list} {
119
120
121
122
123
124
125
126
127
128
129
130

    if {[expr {[llength $fiu_list] % 2}] != 0} {
        echo "Invalid# args in list"
        return -1;
    }

    set dut_in_reset_active 0
    set dut_out_reset_active 0
    set ext_reset_active 0
    set ext_active 0
    set int_active 1
    set reset_dut_in_duration 4
131
132
    set fault_detect_1 [expr {(($fault_detect >> 1) & 1)}]
    set fault_detect_0 [expr {(($fault_detect) & 1)}]
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167

    # ID caluclation mechanism:
    # proposal is to do this by taking the MD5 hash of all configuration values
    # (as strings) joined together, converting it to HEX, taking the 16 LSBits,
    # shifting them to the left and setting the LSB to 1
#    scan [string range [::md5::md5 -hex [join $fiu_list ""]] end-3 end] %x id
    set id 1
    set id [expr {(($id << 1) | 1) & 0xFFFF}]

    echo "ID is 0x[format %4.4X $id]"
    
    # generate timestamp

    set systemTime [clock format [clock seconds] -format "%a %b %d %H:%M:%S %Y"] 

    # open the supplied VHDL file name
    set fd [open $file_name w]

    # writing the header containing libraries to use and the calc'd ID
    set header "-- Automatically generated $systemTime
library ieee;
    use ieee.std_logic_1164.all;

library work;
    use work.fault_selection_type_pkg.all;

package public_config_pkg is

  ------------------------------------------------------------------------------
  -- Design configuration
  ------------------------------------------------------------------------------
  -- The design\'s clock frequency
  constant c_frequency : positive := $fclk;
  -- The baud rate
  constant c_baudrate  : positive := $baud;
168
169
  -- The invert mask for the fault detection signals
  constant c_fault_detect_invert_mask : std_logic_vector(1 downto 0) := \"${fault_detect_1}${fault_detect_0}\";
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247

  ------------------------------------------------------------------------------
  -- LFSR configuration
  ------------------------------------------------------------------------------

  -- Width of the LFSR for random FIU enable & stuck-open
  constant c_lfsr_width : natural                                   := 16;
  -- Polynomial for the LFSR
  constant c_lfsr_poly  : std_logic_vector(c_lfsr_width-1 downto 0) := X\"002d\";
  -- Initial value for the LFSR
  constant c_lfsr_seed  : std_logic_vector(c_lfsr_width-1 downto 0) := X\"cafe\";

  ------------------------------------------------------------------------------
  -- Controller Configuration
  ------------------------------------------------------------------------------

  -- Width of the timers in bytes.
  constant c_timer_width  : natural := 4;
  
  -- FIC -> DUT reset signal: active level
  constant c_reset_dut_in_active : std_logic := \'$dut_in_reset_active\';
  -- reset duration
  constant c_reset_dut_in_duration : positive := $reset_dut_in_duration;

  -- external reset signal: active level
  constant c_reset_ext_active : std_logic := \'$ext_reset_active\';

  -- DUT -> FIC reset signal: active level
  constant c_reset_dut_out_active : std_logic := \'$dut_out_reset_active\';


  -- active level of the external and internal triggers
  constant c_trigger_ext_active             : std_logic := \'$ext_active\';
  constant c_trigger_dut_active             : std_logic := \'$int_active\';

  -- hardware id
  constant c_id    : std_logic_vector(15 downto 0) :=  X\"[format %4.4X $id]\";




  ------------------------------------------------------------------------------
  -- FIU Configuration
  ------------------------------------------------------------------------------

  type t_single_fiu_record is record
    fault_model             : t_select_fault_models;  --Select dynamic or single fault model. See fault_injection_unit
    lfsr_mask               : std_logic_vector(c_lfsr_width-1 downto 0);  -- Select which LFSR bits to AND with FIU enable
  end record t_single_fiu_record;

  type t_fiu_records is array (natural range <>) of t_single_fiu_record;

  constant c_fiu_config : t_fiu_records := \(
"

    puts $fd $header

    set fiu_strings [list]

    # output an array constant with one record for each FIU
    foreach {fault_model lfsr_mask} $fiu_list {

        set fiu_string "      (fault_model     => $fault_model,
       lfsr_mask       => X\"[format %4.4X $lfsr_mask]\"\)"

        lappend fiu_strings $fiu_string

    }

    puts $fd [join $fiu_strings ",\n\n"]

    puts $fd "\n  );\n\nend package public_config_pkg;"

    close $fd

    return $id

}