VHDL.pm 22.1 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
#-------------------------------------------------------------------------------
#  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
#
#-------------------------------------------------------------------------------
#  File:              VHDL.pm
#  Created on:        28.05.2015
Christian Fibich's avatar
Christian Fibich committed
13
14
#  $LastChangedBy$
#  $LastChangedDate$
15
16
17
18
19
20
21
#
#  Description:
#  Contains functions to generate VHDL package and wrapper files for FIJI
#  Contains enum values for marking Verilog-Perl netlist ports with userdata:
#
#-------------------------------------------------------------------------------

Christian Fibich's avatar
Christian Fibich committed
22
23
## @file VHDL.pm
# @brief Contains class \ref FIJI::VHDL
24
25

## @class FIJI::VHDL
Christian Fibich's avatar
Christian Fibich committed
26
27
28
29
30
# @brief Functions generating VHDL code
## @class FIJI::VHDL
# Contains functions to generate VHDL package and wrapper files for FIJI
# Contains enum values for marking Verilog-Perl netlist ports with userdata:

31
32
33
34
package FIJI::VHDL;

use strict;
use warnings;
35
use Data::Dumper;
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
use Log::Log4perl qw(get_logger);

use FIJI::Settings;

#  FIJI_USERDATA_xxx is intended as key for the port->userdata{} hash
#  FIJI_USERDATA_PORTTYPE:  type of the port (see FIJI_PORTTYPE_xxx enum)
#  FIJI_USERDATA_FIU_INDEX: FIU# this FIJI_PORTTYPE_MODIFIED or FIJI_PORTTYPE_ORIGINAL should be connected to
#  FIJI_USERDATA_FD_INDEX:  Fault Detection channel this FIJI_PORTTYPE_FAULT_DETECTION should be connected to
use enum qw(FIJI_USERDATA_PORTTYPE FIJI_USERDATA_FIU_INDEX FIJI_USERDATA_FD_INDEX);

#  FIJI_PORTTYPE_xxx is intended to be used as value for port->userdata{FIJI::VHDL->FIJI_USERDATA_PORTTYPE} to determine the special port usage
#  FIJI_PORTTYPE_CLOCK: clock output to FIJI from DUT
#  FIJI_PORTTYPE_MODIFIED: modified net input to DUT
#  FIJI_PORTTYPE_ORIGINAL: original net output to FIJI
#  FIJI_PORTTYPE_FAULT_DETECTION: fault detection net output to FIJI
#  FIJI_PORTTYPE_TRIGGER_FROM_DUT: internal trigger from DUT to FIJI
#  FIJI_PORTTYPE_RESET_FROM_DUT:   internal reset from DUT to FIJI
#  FIJI_PORTTYPE_RESET_TO_DUT:     internal reset from FIJI to DUT
use enum qw(FIJI_PORTTYPE_CLOCK FIJI_PORTTYPE_MODIFIED FIJI_PORTTYPE_ORIGINAL FIJI_PORTTYPE_FAULT_DETECTION FIJI_PORTTYPE_TRIGGER_FROM_DUT FIJI_PORTTYPE_RESET_FROM_DUT FIJI_PORTTYPE_RESET_TO_DUT);

#  Default values hash for signal and instantiation names, and the trigger and reset values
Christian Fibich's avatar
Christian Fibich committed
57
use constant FIJI_DEFAULTS => {
58
59
60
61
62
    TX_OUT_NAME       => "s_fiji_tx_o",
    RX_IN_NAME        => "s_fiji_rx_i",
    DUT_INST_NAME     => "i_DUT",
    FIJI_INST_NAME    => "i_FIJI",
    FIJI_WRAPPER_NAME => "fiji_top",
63
64
65
66
67
68
69
70
71
72
73
74

    FIJI_WRAPPER_CLOCK_SIGNAL_NAME          => "s_fiji_clk",
    FIJI_WRAPPER_ORIGINAL_SIGNAL_NAME       => "s_fiji_original",
    FIJI_WRAPPER_MODIFIED_SIGNAL_NAME       => "s_fiji_modified",
    FIJI_WRAPPER_FAULT_SIGNAL_NAME          => "s_fiji_fault_detect",
    FIJI_WRAPPER_TRIGGER_DUT_SIGNAL_NAME    => "s_fiji_trigger_from_dut",
    FIJI_WRAPPER_TRIGGER_EXT_SIGNAL_NAME    => "s_fiji_trigger_ext",
    FIJI_WRAPPER_RESET_FROM_DUT_SIGNAL_NAME => "s_fiji_reset_from_dut",
    FIJI_WRAPPER_RESET_TO_DUT_SIGNAL_NAME   => "s_fiji_reset_to_dut",
    FIJI_WRAPPER_RESET_EXT_SIGNAL_NAME      => "s_fiji_reset_ext",
    RESET_EXT_IN_NAME                       => "s_fiji_reset",

75
76
    FIJI_TRIGGER_EXT_ASSIGNMENT => "not(c_trigger_ext_active)",
    FIJI_RESET_EXT_ASSIGNMENT   => "not(c_reset_ext_active)",
77

78
    FIJI_FAULT_INJECTION_GEN_LABEL    => "gen_fault_injection",
79
    FIJI_NO_FAULT_INJECTION_GEN_LABEL => "gen_no_fault_injection",
Christian Fibich's avatar
Christian Fibich committed
80
81

    FIJI_WRAPPER_ATTRIBUTES => " -- no attributes",
Christian Fibich's avatar
Christian Fibich committed
82
};
83
84
85
86
87
88
89
90

## @function generate_config_package ($fiji_settings_filename, $vhdl_filename)
# @brief Generate a public_config_pkg VHDL package file for FIJI
#
# \param fiji_settings_filename the cfg file generated by fiji_setup
# \param vhdl_filename the name of the VHDL file to be generated
#
# \returns 0 if VHDL file was generated successfully.
Christian Fibich's avatar
Christian Fibich committed
91
92
sub generate_config_package {
    my ($class, $fiji_settings_filename, $vhdl_filename) = @_;
93

94
    my $logger = get_logger("");
95
96
97
    my $name   = $0;
    $name =~ s/\.p[lm]//;
    $logger->debug("=== generate_config_package ===");
Christian Fibich's avatar
Christian Fibich committed
98
    $logger->debug(sprintf("%d argument(s)%s", scalar(@_), scalar(@_) > 0 ? ": @_" : ""));
99

100
101
102
103
104
    my ($fiji_settings, $warn) = FIJI::Settings->new('download', $fiji_settings_filename);
    if (!defined($fiji_settings)) {
        return $warn . " Aborting.\n";
    } elsif (defined($warn)) {
        $logger->warn($warn);
105
106
107
108
109
    }
    my $fiji_consts = $fiji_settings->{'design'};
    my $fius        = $fiji_settings->{'fius'};

    # LFSR initial value is given as a 0-padded hex number
Christian Fibich's avatar
Christian Fibich committed
110
    my $lfsr_fmt = sprintf("X\"%%0%dx\"", $fiji_consts->{'LFSR_WIDTH'} / 4);
111
112
113
    my @fiu_configs = ();

    # generate the fiu_config record contents
Christian Fibich's avatar
Christian Fibich committed
114
115
    for (my $i = 0 ; $i < $fiji_consts->{'FIU_NUM'} ; $i++) {
        my $lfsr_mask = sprintf("$lfsr_fmt", @{$fius}[$i]->{'FIU_LFSR_MASK'});
116
        my $str = <<"END_FIU";
117
118
119
120
121
        $i => (
            fault_model => @{$fius}[$i]->{'FIU_MODEL'},
            lfsr_mask =>   $lfsr_mask
        )
END_FIU
122
123
        push @fiu_configs, $str;
    }
Christian Fibich's avatar
Christian Fibich committed
124
125
    my $lfsr_poly_string = sprintf($lfsr_fmt, $fiji_consts->{'LFSR_POLY'});
    my $lfsr_seed_string = sprintf($lfsr_fmt, $fiji_consts->{'LFSR_SEED'});
126

127
128
    # invert is given as 2-bit binary mask
    # need to do this because fault detection invert can be specified even if channel is not enabled
Christian Fibich's avatar
Christian Fibich committed
129
130
131
    my $invert1 = ($fiji_consts->{'FAULT_DETECT_1_EN'}) ? $fiji_consts->{'FAULT_DETECT_1_INVERT'} : 0;
    my $invert2 = ($fiji_consts->{'FAULT_DETECT_2_EN'}) ? $fiji_consts->{'FAULT_DETECT_2_INVERT'} : 0;
    my $fault_detect_string = sprintf("%01d%01d", $invert2, $invert1);
Christian Fibich's avatar
Christian Fibich committed
132

Christian Fibich's avatar
Christian Fibich committed
133
134
    my $fiu_configs_string = join("        ,\n", @fiu_configs);
    my $vhdl_id = sprintf("X\"%04x\"", $fiji_consts->{'ID'});
135
    my $gentime = localtime;
136

Christian Fibich's avatar
Christian Fibich committed
137
    my $reset_dut_in_duration = ($fiji_consts->{'RESET_DUT_IN_EN'} eq 1) ? $fiji_consts->{'RESET_DUT_IN_DURATION'} : 1;
138

Christian Fibich's avatar
Christian Fibich committed
139
    $logger->debug(sprintf("Generating VHDL text.\n"));
140

141
    my $vhdl = <<"END_VHDL";
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
168
169
170
171
172
173
174
--------------------------------------------------------------------------------
-- 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                                              --
--                                                                            --
--------------------------------------------------------------------------------
-- File:              $vhdl_filename
-- Generated:         $gentime
--
-- Description:
-- Public config package for $fiji_settings_filename
--------------------------------------------------------------------------------

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 := $fiji_consts->{'FREQUENCY'};
  -- The baud rate
  constant c_baudrate  : positive := $fiji_consts->{'BAUDRATE'};
  -- The invert mask for the fault detection signals
175
  constant c_fault_detect_invert_mask : std_logic_vector(1 downto 0) := "$fault_detect_string";
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197

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

  -- Width of the LFSR for random FIU enable & stuck-open
  constant c_lfsr_width : natural                                   := $fiji_consts->{'LFSR_WIDTH'};
  -- Polynomial for the LFSR
  constant c_lfsr_poly  : std_logic_vector(c_lfsr_width-1 downto 0) := $lfsr_poly_string;
  -- Initial value for the LFSR
  constant c_lfsr_seed  : std_logic_vector(c_lfsr_width-1 downto 0) := $lfsr_seed_string;

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

  -- Width of the timers in bytes.
  constant c_timer_width  : natural := $fiji_consts->{'TIMER_WIDTH'};
  
  -- FIC -> DUT reset signal: active level
  constant c_reset_dut_in_active : std_logic := '$fiji_consts->{'RESET_DUT_IN_ACTIVE'}';
  -- reset duration
198
  constant c_reset_dut_in_duration : positive := $reset_dut_in_duration; 
199
200

  -- external reset signal: active level
201
  constant c_reset_ext_active : std_logic := '$fiji_consts->{'RESET_EXT_ACTIVE'}';
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

  -- DUT -> FIC reset signal: active level
  constant c_reset_dut_out_active : std_logic := '$fiji_consts->{'RESET_DUT_OUT_ACTIVE'}';


  -- active level of the external and internal triggers
  constant c_trigger_ext_active             : std_logic := '$fiji_consts->{'TRIGGER_EXT_ACTIVE'}';
  constant c_trigger_dut_active             : std_logic := '$fiji_consts->{'TRIGGER_DUT_ACTIVE'}';

  -- hardware id
  constant c_id    : std_logic_vector(15 downto 0) :=  $vhdl_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 for Stuck-open fault
  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 := (

$fiu_configs_string

  );

end package public_config_pkg;
END_VHDL

Christian Fibich's avatar
Christian Fibich committed
234
    $logger->debug(sprintf("Writing public config package to $vhdl_filename.\n"));
235

Christian Fibich's avatar
Christian Fibich committed
236
    if (open(my $fh, ">", $vhdl_filename)) {
237
238
239
240
241
        print $fh $vhdl;
        close $fh;
    } else {
        return "Could not open file '$vhdl_filename' for writing: $!";
    }
242

Christian Fibich's avatar
Christian Fibich committed
243
    $logger->info(sprintf("Successfully generated public config package for $fiji_settings_filename in $vhdl_filename.\n"));
244

245
    return undef;
246
247
}

Christian Fibich's avatar
Christian Fibich committed
248
## @function generate_wrapper_module (%$wrapper_config)
249
250
# @brief Generate a VHDL wrapper module instantiating FIJI logic and the DUT
#
Christian Fibich's avatar
Christian Fibich committed
251
# \param wrapper_config a configuration hash ref.
252
253
254
255
256
257
#   -> {'netlist'} the Verilog-Perl netlist file
#   -> {'dut_toplevel_module_name'} the toplevel module in the vqm netlist
#   -> {'fiji_settings_filename'}   the path to the fiji.cfg file
#   -> {'vhdl_filename'}            the VHDL file to be generated
#
# \returns 0 if VHDL file was generated successfully.
Christian Fibich's avatar
Christian Fibich committed
258
259
sub generate_wrapper_module {
    my ($class, $wrapper_config) = @_;
260

261
262
263
264
    my $vqm_netlist            = $wrapper_config->{'netlist'};
    my $dut_toplevel           = $wrapper_config->{'dut_toplevel_module_name'};
    my $fiji_settings_filename = $wrapper_config->{'fiji_settings_filename'};
    my $vhdl_filename          = $wrapper_config->{'vhdl_filename'};
265

266
    my $logger = get_logger("");
267
    my $name   = $0;
268
269
    $name =~ s/\.p[lm]//;
    $logger->debug("=== generate_wrapper_module ===");
Christian Fibich's avatar
Christian Fibich committed
270
    $logger->debug(sprintf("%d argument(s)%s", scalar(@_), scalar(@_) > 0 ? ": @_" : ""));
271

272
273
274
275
276
    my ($fiji_settings, $warn) = FIJI::Settings->new('download', $fiji_settings_filename);
    if (!defined($fiji_settings)) {
        return $warn . " Aborting.\n";
    } elsif (defined($warn)) {
        $logger->warn($warn);
277
278
    }
    my $fiji_consts = $fiji_settings->{'design'};
279
    my $fius        = $fiji_settings->{'fius'};
280
281
282

    $logger->debug("=== Assigning values ===");

Christian Fibich's avatar
Christian Fibich committed
283
284
    my $tx_name = (defined $fiji_consts->{'TX_OUT_NAME'}) ? $fiji_consts->{'TX_OUT_NAME'} : FIJI_DEFAULTS->{'TX_OUT_NAME'};
    my $rx_name = (defined $fiji_consts->{'RX_IN_NAME'})  ? $fiji_consts->{'RX_IN_NAME'}  : FIJI_DEFAULTS->{'RX_IN_NAME'};
285

Christian Fibich's avatar
Christian Fibich committed
286
287
288
    my $dut_inst_name  = (defined $fiji_consts->{'DUT_INST_NAME'})     ? $fiji_consts->{'DUT_INST_NAME'}     : FIJI_DEFAULTS->{'DUT_INST_NAME'};
    my $fiji_inst_name = (defined $fiji_consts->{'FIJI_INST_NAME'})    ? $fiji_consts->{'FIJI_INST_NAME'}    : FIJI_DEFAULTS->{'FIJI_INST_NAME'};
    my $wrapper_name   = (defined $fiji_consts->{'FIJI_WRAPPER_NAME'}) ? $fiji_consts->{'FIJI_WRAPPER_NAME'} : FIJI_DEFAULTS->{'FIJI_WRAPPER_NAME'};
289

Christian Fibich's avatar
Christian Fibich committed
290
    # assign some defaults
Christian Fibich's avatar
Christian Fibich committed
291
292
293
294
295
296
297
298
299
300
301
    my $fiji_clock_signal_name            = FIJI_DEFAULTS->{'FIJI_WRAPPER_CLOCK_SIGNAL_NAME'};
    my $fiji_original_signal_name         = FIJI_DEFAULTS->{'FIJI_WRAPPER_ORIGINAL_SIGNAL_NAME'};
    my $fiji_modified_signal_name         = FIJI_DEFAULTS->{'FIJI_WRAPPER_MODIFIED_SIGNAL_NAME'};
    my $fiji_fault_detection_signal_name  = FIJI_DEFAULTS->{'FIJI_WRAPPER_FAULT_SIGNAL_NAME'};
    my $fiji_trigger_from_dut_signal_name = FIJI_DEFAULTS->{'FIJI_WRAPPER_TRIGGER_DUT_SIGNAL_NAME'};
    my $fiji_trigger_ext_signal_name      = FIJI_DEFAULTS->{'FIJI_WRAPPER_TRIGGER_EXT_SIGNAL_NAME'};
    my $fiji_reset_from_dut_signal_name   = FIJI_DEFAULTS->{'FIJI_WRAPPER_RESET_FROM_DUT_SIGNAL_NAME'};
    my $fiji_reset_to_dut_signal_name     = FIJI_DEFAULTS->{'FIJI_WRAPPER_RESET_TO_DUT_SIGNAL_NAME'};
    my $fiji_reset_ext_signal_name        = FIJI_DEFAULTS->{'FIJI_WRAPPER_RESET_EXT_SIGNAL_NAME'};
    my $gen_fault_injection_label         = FIJI_DEFAULTS->{'FIJI_FAULT_INJECTION_GEN_LABEL'};
    my $gen_no_fault_injection_label      = FIJI_DEFAULTS->{'FIJI_NO_FAULT_INJECTION_GEN_LABEL'};
Christian Fibich's avatar
Christian Fibich committed
302
    my $attributes                        = FIJI_DEFAULTS->{'FIJI_WRAPPER_ATTRIBUTES'};
303

304
305
    my $trigger_ext_assignment = "not(c_trigger_ext_active)";
    my $reset_ext_assignment   = "not(c_reset_ext_active)";
306
307
308
309

    my $vqm_toplevel_module = $vqm_netlist->find_module($dut_toplevel);

    # check inputs
Christian Fibich's avatar
Christian Fibich committed
310
311
    return "Toplevel module $dut_toplevel not found.\n" if (!defined $vqm_toplevel_module);
    return "Module $dut_toplevel is not at the top level.\n" unless ($vqm_toplevel_module->is_top);
312
313
314
315
316
317
318
319

    # create lists for vhdl declarations and maps
    my @ext_ports          = ();
    my @dut_comp_ports     = ();
    my @dut_port_maps      = ();
    my @signal_assignments = ();

    # add FIJI external ports
320
321
322
323
    push @ext_ports, "--", "-- FIJI ports", "--";
    push @ext_ports, $tx_name . ": out std_logic";
    push @ext_ports, $rx_name . ": in  std_logic";

Christian Fibich's avatar
Christian Fibich committed
324
    if ($fiji_consts->{'RESET_EXT_EN'}) {
325
326
327
        my $re = (defined $fiji_consts->{'RESET_EXT_IN_NAME'}) ? $fiji_consts->{'RESET_EXT_IN_NAME'} : FIJI_DEFAULTS->{'RESET_EXT_IN_NAME'};
        push @ext_ports, "$re : in  std_logic";
        $reset_ext_assignment = $re;
328
    }
Christian Fibich's avatar
Christian Fibich committed
329
    if ($fiji_consts->{'TRIGGER_EXT_EN'}) {
330
331
332
        my $te = (defined $fiji_consts->{'TRIGGER_EXT_IN_NAME'}) ? $fiji_consts->{'TRIGGER_EXT_IN_NAME'} : FIJI_DEFAULTS->{'TRIGGER_EXT_IN_NAME'};
        push @ext_ports, "$te : in  std_logic";
        $trigger_ext_assignment = $te;
333
    }
334

335
    # add divider
336
    push @ext_ports, "--", "-- DUT ports", "--";
337

Christian Fibich's avatar
Christian Fibich committed
338
    # @FIXME: Verilog-Perl bug
339
340
    # using ->ports_sorted instead of ->ports_ordered here because verilog-perl only
    # updates ports_sorted when using ->new_port.
Christian Fibich's avatar
Christian Fibich committed
341
    foreach my $port ($vqm_toplevel_module->ports_sorted) {
342

343
344
        # retrieve userdata from netlist
        my $fiji_porttype = $port->userdata(FIJI_USERDATA_PORTTYPE);
345
346
        my $fiu_idx       = $port->userdata(FIJI_USERDATA_FIU_INDEX);
        my $fd_idx        = $port->userdata(FIJI_USERDATA_FD_INDEX);
347
348

        # add to ports of vhdl component definition
Christian Fibich's avatar
Christian Fibich committed
349
        push @dut_comp_ports, (($port->name) . " : " . ($port->direction) . " " . (port2vhdtype($port)));
350

Christian Fibich's avatar
Christian Fibich committed
351
        # check if port has assigned a special FIJI function
Christian Fibich's avatar
Christian Fibich committed
352
353
        if (defined $fiji_porttype) {
            if ($fiji_porttype == FIJI_PORTTYPE_CLOCK) {
354

355
                # clock from DUT to FIJI
Christian Fibich's avatar
Christian Fibich committed
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
                push @dut_port_maps, (($port->name) . " => $fiji_clock_signal_name");
            } elsif ($fiji_porttype == FIJI_PORTTYPE_ORIGINAL) {
                return "Port " . ($port->name) . " has no fiu_idx assignment" unless (defined $fiu_idx);
                push @dut_port_maps, (($port->name) . " => $fiji_original_signal_name(" . $fiu_idx . ")");
            } elsif ($fiji_porttype == FIJI_PORTTYPE_MODIFIED) {
                return "Port " . ($port->name) . " has no fiu_idx assignment" unless (defined $fiu_idx);
                push @dut_port_maps, (($port->name) . " => $fiji_modified_signal_name(" . $fiu_idx . ")");
            } elsif ($fiji_porttype == FIJI_PORTTYPE_FAULT_DETECTION) {
                return "Port " . ($port->name) . " has no fd_idx assignment" unless (defined $fd_idx);
                push @dut_port_maps, (($port->name) . " => $fiji_fault_detection_signal_name(" . $fd_idx . ")");
            } elsif ($fiji_porttype == FIJI_PORTTYPE_TRIGGER_FROM_DUT) {
                push @dut_port_maps, (($port->name) . " => $fiji_trigger_from_dut_signal_name");
            } elsif ($fiji_porttype == FIJI_PORTTYPE_RESET_FROM_DUT) {
                push @dut_port_maps, (($port->name) . " => $fiji_reset_from_dut_signal_name");
            } elsif ($fiji_porttype == FIJI_PORTTYPE_RESET_TO_DUT) {
                push @dut_port_maps, (($port->name) . " => $fiji_reset_to_dut_signal_name");
372
373
374
375
            } else {
                $logger->error("Unknown fiji_porttype assignment: $fiji_porttype");
            }
        } else {
376

377
            # add to externally connected DUT ports
Christian Fibich's avatar
Christian Fibich committed
378
379
            push @ext_ports, (($port->name) . " : " . ($port->direction) . " " . (port2vhdtype($port)));
            push @dut_port_maps, (($port->name) . " => " . ($port->name));
380
381
        }
    }
382

383
    # generate VHDL text for declaration blocks
Christian Fibich's avatar
Christian Fibich committed
384
385
386
    my $ext_ports_vhdl      = join(";\n        ",     @ext_ports);
    my $dut_comp_ports_vhdl = join(";\n            ", @dut_comp_ports);
    my $dut_port_maps_vhdl  = join(",\n            ", @dut_port_maps);
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429

    my $gentime = localtime;

    # generate VHDL wrapper text
    my $vhdl = <<"END_VHDL";
---------------------------------------------------------------------------------
--  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
--
---------------------------------------------------------------------------------
--
-- FIJI Wrapper generated at $gentime
-- Options:
--     toplevel  = "$dut_toplevel"
--     inst_name = "$dut_inst_name"
--     fiji_name = "$fiji_inst_name"
--     wrapper   = "$wrapper_name"
--
---------------------------------------------------------------------------------

library ieee;
    use ieee.std_logic_1164.all;
library work;
    use work.private_config_pkg.all;
    use work.public_config_pkg.all;
    use work.fault_injection_top_pkg.all;

entity $wrapper_name is
    generic (
        g_implement_fault_injection : boolean := true
    );
    port (
        $ext_ports_vhdl
    );
end entity $wrapper_name;

architecture wrap of $wrapper_name is
    
Christian Fibich's avatar
Christian Fibich committed
430
    $attributes
431

432
433
434
435
436
437
438
439
440
    component $dut_toplevel is
        port (
            $dut_comp_ports_vhdl
        );
    end component $dut_toplevel;

    signal $fiji_trigger_ext_signal_name        : std_logic;
    signal $fiji_reset_ext_signal_name          : std_logic;
    signal $fiji_clock_signal_name                : std_logic;
441
    signal $fiji_reset_from_dut_signal_name     : std_logic := not(c_reset_dut_out_active);
442
443
444
445
446
447
448
449
450
451
452
453
454
    signal $fiji_reset_to_dut_signal_name       : std_logic;
    signal $fiji_trigger_from_dut_signal_name   : std_logic := not(c_trigger_dut_active);
    signal $fiji_fault_detection_signal_name       : std_logic_vector(c_num_fault_detect_nets-1 downto 0) := (others => '0');
    signal $fiji_original_signal_name           : std_logic_vector(c_fiu_config'length-1 downto 0);
    signal $fiji_modified_signal_name           : std_logic_vector(c_fiu_config'length-1 downto 0);
    
begin

    $dut_inst_name : $dut_toplevel
        port map(
            $dut_port_maps_vhdl
        );

455
    $gen_fault_injection_label : if g_implement_fault_injection = true generate
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475

        $fiji_trigger_ext_signal_name <= $trigger_ext_assignment;
        $fiji_reset_ext_signal_name   <= $reset_ext_assignment;

        $fiji_inst_name : fault_injection_top
            port map (
                s_fiji_clk_i           => $fiji_clock_signal_name,
                s_fiji_reset_ext_i     => $fiji_reset_ext_signal_name,
                s_fiji_reset_dut_out_i => $fiji_reset_from_dut_signal_name,
                s_fiji_reset_dut_in_o  => $fiji_reset_to_dut_signal_name,
                s_fiji_rx_i            => $rx_name,
                s_fiji_tx_o            => $tx_name,
                s_fiji_trigger_ext_i   => $fiji_trigger_ext_signal_name,
                s_fiji_trigger_dut_i   => $fiji_trigger_from_dut_signal_name,
                s_fiji_fault_detect_i  => $fiji_fault_detection_signal_name,
                s_fiji_original_i      => $fiji_original_signal_name,
                s_fiji_modified_o      => $fiji_modified_signal_name
            );
    end generate;

476
    $gen_no_fault_injection_label : if g_implement_fault_injection = false generate
477
478
479
480
481
482
        $fiji_modified_signal_name <= $fiji_original_signal_name;
    end generate;

end wrap;
END_VHDL

Christian Fibich's avatar
Christian Fibich committed
483
    $logger->debug(sprintf("Writing VHDL wrapper to $vhdl_filename.\n"));
484

Christian Fibich's avatar
Christian Fibich committed
485
    if (open(my $fh, ">", $vhdl_filename)) {
486
487
488
489
490
        print $fh $vhdl;
        close $fh;
    } else {
        return "Could not open file '$vhdl_filename' $!";
    }
491

Christian Fibich's avatar
Christian Fibich committed
492
    $logger->info(sprintf("Successfully generated VHDL wrapper for $fiji_settings_filename in $vhdl_filename.\n"));
493

494
    return undef;
495
496
497

}

Christian Fibich's avatar
Christian Fibich committed
498
499
## @function public port2vhdtype ()
# @brief generates a VHDL type declaration for a given port/its net
500
501
502
503
sub port2vhdtype {
    my $port = shift(@_);
    my $type;

Christian Fibich's avatar
Christian Fibich committed
504
    if (!defined $port->net->msb) {
505
        $type = "std_logic";
Christian Fibich's avatar
Christian Fibich committed
506
507
    } elsif ($port->net->msb > $port->net->lsb) {
        $type = sprintf("std_logic_vector(%d downto %d)", $port->net->msb, $port->net->lsb);
508
    } else {
Christian Fibich's avatar
Christian Fibich committed
509
        $type = sprintf("std_logic_vector(%d to %d)", $port->net->msb, $port->net->lsb);
510
511
512
513
514
    }

    return $type;
}

515
1;