VHDL.pm 24.2 KB
Newer Older
1
2
3
#-----------------------------------------------------------------------
# Fault InJection Instrumenter (FIJI)
# https://embsys.technikum-wien.at/projects/vecs/fiji
4
#
5
6
7
8
# The creation of this file has been supported by the publicly funded
# R&D project Josef Ressel Center for Verification of Embedded Computing
# Systems (VECS) managed by the Christian Doppler Gesellschaft (CDG).
#
9
10
11
# Authors:
# Christian Fibich <fibich@technikum-wien.at>
# Stefan Tauner <tauner@technikum-wien.at>
12
#
13
14
# This module is free software; you can redistribute it and/or modify
# it under the same terms as Perl itself.
15
#
16
17
18
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19
#
20
21
# See the LICENSE file for more details.
#-----------------------------------------------------------------------
22

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

## @class FIJI::VHDL
Christian Fibich's avatar
Christian Fibich committed
27
28
29
30
31
# @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:

32
33
34
35
36
package FIJI::VHDL;

use strict;
use warnings;
use Log::Log4perl qw(get_logger);
37
use POSIX qw(ceil);
38
use FIJI qw(:fiji_version);
39
40
41
42
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)
43
#  FIJI_USERDATA_PREV_PORTNAME:  original name of the port in case it was driving an instrumented net
44
45
#  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
46
use enum qw(FIJI_USERDATA_PORTTYPE FIJI_USERDATA_PREV_PORTNAME FIJI_USERDATA_FIU_INDEX FIJI_USERDATA_FD_INDEX);
47
48
49
50
51
52

#  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
53
54
55
56
#  FIJI_PORTTYPE_TRIG_FROM_DUT: internal trigger from DUT to FIJI
#  FIJI_PORTTYPE_RST_FROM_DUT:   internal reset from DUT to FIJI
#  FIJI_PORTTYPE_RST_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_TRIG_FROM_DUT FIJI_PORTTYPE_RST_FROM_DUT FIJI_PORTTYPE_RST_TO_DUT);
57
58

#  Default values hash for signal and instantiation names, and the trigger and reset values
Christian Fibich's avatar
Christian Fibich committed
59
use constant FIJI_DEFAULTS => {
60
61
62
63
64
    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",
65

66
67
68
69
70
71
72
73
74
75
    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_TRIG_DUT_SIGNAL_NAME     => "s_fiji_trig_from_dut",
    FIJI_WRAPPER_TRIG_EXT_SIGNAL_NAME     => "s_fiji_trig_ext",
    FIJI_WRAPPER_RST_FROM_DUT_SIGNAL_NAME => "s_fiji_reset_from_dut",
    FIJI_WRAPPER_RST_TO_DUT_SIGNAL_NAME   => "s_fiji_reset_to_dut",
    FIJI_WRAPPER_RST_EXT_SIGNAL_NAME      => "s_fiji_reset_ext",
    RST_EXT_IN_NAME                       => "s_fiji_reset",
76

77
78
    FIJI_TRIG_EXT_ASSIGNMENT => "not(c_trigger_ext_active)",
    FIJI_RST_EXT_ASSIGNMENT  => "not(c_reset_ext_active)",
79

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

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

## @function generate_config_package ($fiji_settings_filename, $vhdl_filename)
# @brief Generate a public_config_pkg VHDL package file for FIJI
#
89
90
91
# \param fiji_settings          a reference to a FIJI Settings hash
# \param fiji_settings_filename the respective file
# \param vhdl_filename          the name of the VHDL file to be generated
92
93
#
# \returns 0 if VHDL file was generated successfully.
Christian Fibich's avatar
Christian Fibich committed
94
sub generate_config_package {
95
    my ($fiji_settings, $fiji_settings_filename, $vhdl_filename) = @_;
96

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

    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
107
    my $lfsr_fmt = sprintf("X\"%%0%dx\"", $fiji_consts->{'LFSR_WIDTH'} / 4);
108
    my $lfsr_width_multiple_of_4 = ceil($fiji_consts->{'LFSR_WIDTH'}/4)*4-1;
109
110
111
    my @fiu_configs = ();

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

125
126
    # 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
127
128
    my $invert1 = ($fiji_consts->{'FD_1_EN'}) ? $fiji_consts->{'FD_1_INVERT'} : 0;
    my $invert2 = ($fiji_consts->{'FD_2_EN'}) ? $fiji_consts->{'FD_2_INVERT'} : 0;
Christian Fibich's avatar
Christian Fibich committed
129
    my $fault_detect_string = sprintf("%01d%01d", $invert2, $invert1);
Christian Fibich's avatar
Christian Fibich committed
130

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

137
    my $reset_dut_in_duration = ($fiji_consts->{'RST_DUT_IN_EN'} eq 1) ? $fiji_consts->{'RST_DUT_IN_DUR'} : 1;
138

139
    $logger->debug(sprintf("Generating VHDL text."));
140

141
    my $vhdl = <<"END_VHDL";
142
--------------------------------------------------------------------------------
143
144
145
-- Fault InJection Instrumenter (FIJI)
-- https://embsys.technikum-wien.at/projects/vecs/fiji
--
146
147
148
149
-- The creation of this file has been supported by the publicly funded
-- R&D project Josef Ressel Center for Verification of Embedded Computing
-- Systems (VECS) managed by the Christian Doppler Gesellschaft (CDG).
--
150
151
152
153
154
155
156
157
158
159
160
161
162
163
-- Copyright (C) 2017 Christian Fibich <fibich\@technikum-wien.at>
-- Copyright (C) 2017 Stefan Tauner <tauner\@technikum-wien.at>
--
-- Copyright and related rights are licensed under the Solderpad Hardware
-- License, Version 0.51 (the "License"); you may not use this file except
-- in compliance with the License. You may obtain a copy of the License at
-- http://solderpad.org/licenses/SHL-0.51. Unless required by applicable
-- law or agreed to in writing, software, hardware and materials
-- distributed under this License is distributed on an "AS IS" BASIS,
-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either expressed or
-- implied. See the License for the specific language governing
-- permissions and limitations under the License.
--
-- See the LICENSE file for more details.
164
165
--------------------------------------------------------------------------------
-- File:              $vhdl_filename
166
167
168
169
--
-- Generated at $gentime
-- by FIJI version $fiji_version
-- for Design ID $design_id
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
--
-- 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
191
  constant c_fault_detect_invert_mask : std_logic_vector(1 downto 0) := "$fault_detect_string";
192
193
194
195
196
197
198
199

  ------------------------------------------------------------------------------
  -- 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
200
201
  constant c_lfsr_poly_mul4 : std_logic_vector($lfsr_width_multiple_of_4 downto 0) := $lfsr_poly_string;
  constant c_lfsr_poly  : std_logic_vector(c_lfsr_width-1 downto 0) := c_lfsr_poly_mul4(c_lfsr_width-1 downto 0);
202
  -- Initial value for the LFSR
203
204
  constant c_lfsr_seed_mul4 : std_logic_vector($lfsr_width_multiple_of_4 downto 0) := $lfsr_seed_string;
  constant c_lfsr_seed  : std_logic_vector(c_lfsr_width-1 downto 0) := c_lfsr_seed_mul4(c_lfsr_width-1 downto 0);
205
206
207
208
209
210
211
212
213

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

  -- Width of the timers in bytes.
  constant c_timer_width  : natural := $fiji_consts->{'TIMER_WIDTH'};
  
  -- FIC -> DUT reset signal: active level
214
  constant c_reset_dut_in_active : std_logic := '$fiji_consts->{'RST_DUT_IN_ACT'}';
215
  -- reset duration
216
  constant c_reset_dut_in_duration : positive := $reset_dut_in_duration; 
217
218

  -- external reset signal: active level
219
  constant c_reset_ext_active : std_logic := '$fiji_consts->{'RST_EXT_ACT'}';
220
221

  -- DUT -> FIC reset signal: active level
222
  constant c_reset_dut_out_active : std_logic := '$fiji_consts->{'RST_DUT_OUT_ACT'}';
223
224
225


  -- active level of the external and internal triggers
226
227
  constant c_trigger_ext_active             : std_logic := '$fiji_consts->{'TRIG_EXT_ACT'}';
  constant c_trigger_dut_active             : std_logic := '$fiji_consts->{'TRIG_DUT_ACT'}';
228
229
230
231
232
233
234
235
236

  -- hardware id
  constant c_id    : std_logic_vector(15 downto 0) :=  $vhdl_id;

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

  type t_single_fiu_record is record
237
    fault_model             : t_select_fault_models;  -- Select dynamic or single fault model. See fault_injection_unit
238
239
240
241
242
243
244
245
246
247
248
249
250
251
    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

252
    $logger->debug(sprintf("Writing public config package to $vhdl_filename."));
253

Christian Fibich's avatar
Christian Fibich committed
254
    if (open(my $fh, ">", $vhdl_filename)) {
255
256
257
258
259
        print $fh $vhdl;
        close $fh;
    } else {
        return "Could not open file '$vhdl_filename' for writing: $!";
    }
260

261
    $logger->info(sprintf("Successfully generated public config package in $vhdl_filename."));
262

263
    return undef;
264
265
}

266
267
268
269
270
271
272
273
# VHDL '93 supports escaped identifiers in a similar way to Verilog
# A VHDL escaped identifier is delimited by '\' characters, thus
# '\' characters in the identifier have to be escaped.
sub _vhdl_escape_identifier {
    my $identifier = shift;
    return ($identifier =~ /^\\/) ? '\\'.($identifier =~ s/\\/\\\\/gr).'\\' : $identifier;
}

274
## @function generate_wrapper_module (%$netlist, %$fiji_settings, $dut_toplevel, $vhdl_filename)
275
276
# @brief Generate a VHDL wrapper module instantiating FIJI logic and the DUT
#
277
278
# \param netlist        the Verilog-Perl netlist
# \param fiji_settings  the path to the fiji.cfg file
279
# \param dut_toplevel   the top-level module in the vqm netlist
280
# \param vhdl_filename  the VHDL file to be generated
281
282
#
# \returns 0 if VHDL file was generated successfully.
Christian Fibich's avatar
Christian Fibich committed
283
sub generate_wrapper_module {
284
    my ($nl, $fiji_settings, $dut_toplevel, $vhdl_filename) = @_;
285

286
    my $logger = get_logger("");
287
    my $name   = $0;
288
289
    $name =~ s/\.p[lm]//;
    $logger->debug("=== generate_wrapper_module ===");
Christian Fibich's avatar
Christian Fibich committed
290
    $logger->debug(sprintf("%d argument(s)%s", scalar(@_), scalar(@_) > 0 ? ": @_" : ""));
291
292

    my $fiji_consts = $fiji_settings->{'design'};
293
    my $fius        = $fiji_settings->{'fius'};
294
295
296

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

Christian Fibich's avatar
Christian Fibich committed
297
298
    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'};
299

Christian Fibich's avatar
Christian Fibich committed
300
301
302
    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'};
303

Christian Fibich's avatar
Christian Fibich committed
304
    # assign some defaults
Christian Fibich's avatar
Christian Fibich committed
305
306
307
308
    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'};
309
310
311
312
313
    my $fiji_trigger_from_dut_signal_name = FIJI_DEFAULTS->{'FIJI_WRAPPER_TRIG_DUT_SIGNAL_NAME'};
    my $fiji_trigger_ext_signal_name      = FIJI_DEFAULTS->{'FIJI_WRAPPER_TRIG_EXT_SIGNAL_NAME'};
    my $fiji_reset_from_dut_signal_name   = FIJI_DEFAULTS->{'FIJI_WRAPPER_RST_FROM_DUT_SIGNAL_NAME'};
    my $fiji_reset_to_dut_signal_name     = FIJI_DEFAULTS->{'FIJI_WRAPPER_RST_TO_DUT_SIGNAL_NAME'};
    my $fiji_reset_ext_signal_name        = FIJI_DEFAULTS->{'FIJI_WRAPPER_RST_EXT_SIGNAL_NAME'};
Christian Fibich's avatar
Christian Fibich committed
314
315
    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
316
    my $attributes                        = FIJI_DEFAULTS->{'FIJI_WRAPPER_ATTRIBUTES'};
317

318
319
    my $trigger_ext_assignment = "not(c_trigger_ext_active)";
    my $reset_ext_assignment   = "not(c_reset_ext_active)";
320

321
    my $vqm_toplevel_module = $nl->find_module($dut_toplevel);
322
323

    # check inputs
324
    return "Top-level module $dut_toplevel not found." if (!defined $vqm_toplevel_module);
325
    return "Module $dut_toplevel is not at the top level." unless ($vqm_toplevel_module->is_top);
326
327
328
329
330
331
332
333

    # 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
334
    push @ext_ports, "--", "-- FIJI ports", "--";
335
336
    push @ext_ports, _vhdl_escape_identifier($tx_name) . ": out std_logic";
    push @ext_ports, _vhdl_escape_identifier($rx_name) . ": in  std_logic";
337

338
339
    if ($fiji_consts->{'RST_EXT_EN'}) {
        my $re = _vhdl_escape_identifier((defined $fiji_consts->{'RST_EXT_IN_NAME'}) ? $fiji_consts->{'RST_EXT_IN_NAME'} : FIJI_DEFAULTS->{'RST_EXT_IN_NAME'});
340
341
        push @ext_ports, "$re : in  std_logic";
        $reset_ext_assignment = $re;
342
    }
343
344
    if ($fiji_consts->{'TRIG_EXT_EN'}) {
        my $te = _vhdl_escape_identifier((defined $fiji_consts->{'TRIG_EXT_IN_NAME'}) ? $fiji_consts->{'TRIG_EXT_IN_NAME'} : FIJI_DEFAULTS->{'TRIG_EXT_IN_NAME'});
345
346
        push @ext_ports, "$te : in  std_logic";
        $trigger_ext_assignment = $te;
347
    }
348

349
    # add divider
350
    push @ext_ports, "--", "-- DUT ports", "--";
351

Christian Fibich's avatar
Christian Fibich committed
352
    # @FIXME: Verilog-Perl bug
353
354
    # 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
355
    foreach my $port ($vqm_toplevel_module->ports_sorted) {
356

357
358
        # retrieve userdata from netlist
        my $fiji_porttype = $port->userdata(FIJI_USERDATA_PORTTYPE);
359
360
        my $fiu_idx       = $port->userdata(FIJI_USERDATA_FIU_INDEX);
        my $fd_idx        = $port->userdata(FIJI_USERDATA_FD_INDEX);
361
362

        # add to ports of vhdl component definition
363
364
        
        push @dut_comp_ports, ((_vhdl_escape_identifier($port->name)) . " : " . ($port->direction) . " " . (port2vhdtype($port)));
365

Christian Fibich's avatar
Christian Fibich committed
366
        # check if port has assigned a special FIJI function
Christian Fibich's avatar
Christian Fibich committed
367
368
        if (defined $fiji_porttype) {
            if ($fiji_porttype == FIJI_PORTTYPE_CLOCK) {
369

370
                # clock from DUT to FIJI
371
                push @dut_port_maps, (_vhdl_escape_identifier($port->name) . " => $fiji_clock_signal_name");
Christian Fibich's avatar
Christian Fibich committed
372
373
            } elsif ($fiji_porttype == FIJI_PORTTYPE_ORIGINAL) {
                return "Port " . ($port->name) . " has no fiu_idx assignment" unless (defined $fiu_idx);
374
                push @dut_port_maps, (_vhdl_escape_identifier($port->name) . " => $fiji_original_signal_name(" . $fiu_idx . ")");
Christian Fibich's avatar
Christian Fibich committed
375
376
            } elsif ($fiji_porttype == FIJI_PORTTYPE_MODIFIED) {
                return "Port " . ($port->name) . " has no fiu_idx assignment" unless (defined $fiu_idx);
377
                push @dut_port_maps, (_vhdl_escape_identifier($port->name) . " => $fiji_modified_signal_name(" . $fiu_idx . ")");
Christian Fibich's avatar
Christian Fibich committed
378
379
            } elsif ($fiji_porttype == FIJI_PORTTYPE_FAULT_DETECTION) {
                return "Port " . ($port->name) . " has no fd_idx assignment" unless (defined $fd_idx);
380
                push @dut_port_maps, (_vhdl_escape_identifier($port->name) . " => $fiji_fault_detection_signal_name(" . $fd_idx . ")");
381
            } elsif ($fiji_porttype == FIJI_PORTTYPE_TRIG_FROM_DUT) {
382
                push @dut_port_maps, (_vhdl_escape_identifier($port->name) . " => $fiji_trigger_from_dut_signal_name");
383
            } elsif ($fiji_porttype == FIJI_PORTTYPE_RST_FROM_DUT) {
384
                push @dut_port_maps, (_vhdl_escape_identifier($port->name) . " => $fiji_reset_from_dut_signal_name");
385
            } elsif ($fiji_porttype == FIJI_PORTTYPE_RST_TO_DUT) {
386
                push @dut_port_maps, (_vhdl_escape_identifier($port->name) . " => $fiji_reset_to_dut_signal_name");
387
388
389
390
            } else {
                $logger->error("Unknown fiji_porttype assignment: $fiji_porttype");
            }
        } else {
391

392
            my $extportname = _vhdl_escape_identifier((defined($port->userdata(FIJI_USERDATA_PREV_PORTNAME))) ? $port->userdata(FIJI_USERDATA_PREV_PORTNAME) : $port->name);
393
            # add to externally connected DUT ports
394
            push @ext_ports, ("$extportname : " . ($port->direction) . " " . (port2vhdtype($port)));
395
            push @dut_port_maps, (_vhdl_escape_identifier($port->name) . " => $extportname");
396
397
        }
    }
398

399
    # generate VHDL text for declaration blocks
Christian Fibich's avatar
Christian Fibich committed
400
401
402
    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);
403
404

    my $gentime = localtime;
405
406
    my $fiji_version = FIJI_VERSION;
    my $design_id = sprintf("0x%04x", $fiji_consts->{'ID'});
407
408
409

    # generate VHDL wrapper text
    my $vhdl = <<"END_VHDL";
410
411
412
--------------------------------------------------------------------------------
-- Fault InJection Instrumenter (FIJI)
-- https://embsys.technikum-wien.at/projects/vecs/fiji
413
--
414
415
416
417
-- The creation of this file has been supported by the publicly funded
-- R&D project Josef Ressel Center for Verification of Embedded Computing
-- Systems (VECS) managed by the Christian Doppler Gesellschaft (CDG).
--
418
419
-- Copyright (C) 2017 Christian Fibich <fibich\@technikum-wien.at>
-- Copyright (C) 2017 Stefan Tauner <tauner\@technikum-wien.at>
420
--
421
422
423
424
425
426
427
428
429
-- Copyright and related rights are licensed under the Solderpad Hardware
-- License, Version 0.51 (the "License"); you may not use this file except
-- in compliance with the License. You may obtain a copy of the License at
-- http://solderpad.org/licenses/SHL-0.51. Unless required by applicable
-- law or agreed to in writing, software, hardware and materials
-- distributed under this License is distributed on an "AS IS" BASIS,
-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either expressed or
-- implied. See the License for the specific language governing
-- permissions and limitations under the License.
430
--
431
-- See the LICENSE file for more details.
432
433
434
---------------------------------------------------------------------------------
--
-- FIJI Wrapper generated at $gentime
435
436
-- by FIJI version $fiji_version
-- for Design ID $design_id
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
-- 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
463
    $attributes
464

465
466
467
468
469
470
471
472
    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;
473
    signal $fiji_clock_signal_name              : std_logic;
474
    signal $fiji_reset_from_dut_signal_name     : std_logic := not(c_reset_dut_out_active);
475
476
    signal $fiji_reset_to_dut_signal_name       : std_logic;
    signal $fiji_trigger_from_dut_signal_name   : std_logic := not(c_trigger_dut_active);
477
    signal $fiji_fault_detection_signal_name    : std_logic_vector(c_num_fault_detect_nets-1 downto 0) := (others => '0');
478
479
480
481
482
483
484
485
486
487
    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
        );

488
    $gen_fault_injection_label : if g_implement_fault_injection = true generate
489
490
491
492
493
494
495
496
497
498
499
500

        $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,
501
502
                s_fiji_trig_ext_i      => $fiji_trigger_ext_signal_name,
                s_fiji_trig_dut_i      => $fiji_trigger_from_dut_signal_name,
503
504
505
506
507
508
                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;

509
    $gen_no_fault_injection_label : if g_implement_fault_injection = false generate
510
511
512
513
514
515
        $fiji_modified_signal_name <= $fiji_original_signal_name;
    end generate;

end wrap;
END_VHDL

516
    $logger->debug(sprintf("Writing VHDL wrapper to $vhdl_filename."));
517

Christian Fibich's avatar
Christian Fibich committed
518
    if (open(my $fh, ">", $vhdl_filename)) {
519
520
521
522
523
        print $fh $vhdl;
        close $fh;
    } else {
        return "Could not open file '$vhdl_filename' $!";
    }
524

525
    $logger->info(sprintf("Successfully generated VHDL wrapper in $vhdl_filename."));
526

527
    return undef;
528
529
530

}

Christian Fibich's avatar
Christian Fibich committed
531
532
## @function public port2vhdtype ()
# @brief generates a VHDL type declaration for a given port/its net
533
534
535
536
sub port2vhdtype {
    my $port = shift(@_);
    my $type;

Christian Fibich's avatar
Christian Fibich committed
537
    if (!defined $port->net->msb) {
538
        $type = "std_logic";
Christian Fibich's avatar
Christian Fibich committed
539
540
    } elsif ($port->net->msb > $port->net->lsb) {
        $type = sprintf("std_logic_vector(%d downto %d)", $port->net->msb, $port->net->lsb);
541
    } else {
Christian Fibich's avatar
Christian Fibich committed
542
        $type = sprintf("std_logic_vector(%d to %d)", $port->net->msb, $port->net->lsb);
543
544
545
546
547
    }

    return $type;
}

548
1;