aboutsummaryrefslogtreecommitdiffstats
path: root/common/kernel/relptr.h
blob: f0f45b7d03bdf47823453b127e977ad24aeb225e (plain)
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
/*
 *  nextpnr -- Next Generation Place and Route
 *
 *  Copyright (C) 2018  Claire Xenia Wolf <claire@yosyshq.com>
 *
 *  Permission to use, copy, modify, and/or distribute this software for any
 *  purpose with or without fee is hereby granted, provided that the above
 *  copyright notice and this permission notice appear in all copies.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 *  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 *  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 *  ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 *  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 *  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 *  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 *
 */

#ifndef RELPTR_H
#define RELPTR_H

#include <cstdint>

#include "nextpnr_assertions.h"
#include "nextpnr_namespaces.h"

NEXTPNR_NAMESPACE_BEGIN

template <typename T> struct RelPtr
{
    int32_t offset;

    const T *get() const { return reinterpret_cast<const T *>(reinterpret_cast<const char *>(this) + offset); }

    const T &operator[](std::size_t index) const { return get()[index]; }

    const T &operator*() const { return *(get()); }

    const T *operator->() const { return get(); }

    RelPtr(const RelPtr &) = delete;
    RelPtr &operator=(const RelPtr &) = delete;
};

NPNR_PACKED_STRUCT(template <typename T> struct RelSlice {
    int32_t offset;
    uint32_t length;

    const T *get() const { return reinterpret_cast<const T *>(reinterpret_cast<const char *>(this) + offset); }

    const T &operator[](std::size_t index) const
    {
        NPNR_ASSERT(index < length);
        return get()[index];
    }

    const T *begin() const { return get(); }
    const T *end() const { return get() + length; }

    size_t size() const { return length; }
    ptrdiff_t ssize() const { return length; }

    const T &operator*() const { return *(get()); }

    const T *operator->() const { return get(); }

    RelSlice(const RelSlice &) = delete;
    RelSlice &operator=(const RelSlice &) = delete;
});

NEXTPNR_NAMESPACE_END

#endif /* RELPTR_H */
ass="n">A1REG = 1; parameter integer B0REG = 1; parameter integer B1REG = 1; parameter integer CREG = 1; parameter integer DREG = 1; parameter integer MREG = 1; parameter integer PREG = 1; parameter integer CARRYINREG = 1; parameter integer CARRYOUTREG = 1; parameter integer OPMODEREG = 1; parameter CARRYINSEL = "OPMODE5"; parameter RSTTYPE = "SYNC"; reg CLK; reg CEA, CEB, CEC, CED, CEM, CEP, CECARRYIN, CEOPMODE; reg RSTA, RSTB, RSTC, RSTD, RSTM, RSTP, RSTCARRYIN, RSTOPMODE; reg [17:0] A; reg [17:0] B; reg [47:0] C; reg [17:0] D; reg [47:0] PCIN; reg [7:0] OPMODE; reg CARRYIN; output CARRYOUTF, REF_CARRYOUTF; output CARRYOUT, REF_CARRYOUT, REF_OLD_CARRYOUT; output [35:0] M, REF_M; output [47:0] P, REF_P, REF_OLD_P; output [17:0] BCOUT, REF_BCOUT, REF_OLD_BCOUT; output [47:0] PCOUT, REF_PCOUT, REF_OLD_PCOUT; integer errcount = 0; reg ERROR_FLAG = 0; task clkcycle; begin #5; CLK = ~CLK; #10; CLK = ~CLK; #2; ERROR_FLAG = 0; if (REF_BCOUT !== BCOUT || REF_OLD_BCOUT != BCOUT) begin $display("ERROR at %1t: REF_BCOUT=%b REF_OLD_BCOUT=%b UUT_BCOUT=%b DIFF=%b", $time, REF_BCOUT, REF_OLD_BCOUT, BCOUT, REF_BCOUT ^ BCOUT); errcount = errcount + 1; ERROR_FLAG = 1; end if (REF_M !== M) begin $display("ERROR at %1t: REF_M=%b UUT_M=%b DIFF=%b", $time, REF_M, M, REF_M ^ M); errcount = errcount + 1; ERROR_FLAG = 1; end if (REF_P !== P || REF_OLD_P != P) begin $display("ERROR at %1t: REF_P=%b REF_OLD_P=%b UUT_P=%b DIFF=%b", $time, REF_P, REF_OLD_P, P, REF_P ^ P); errcount = errcount + 1; ERROR_FLAG = 1; end if (REF_PCOUT !== PCOUT || REF_OLD_PCOUT != PCOUT) begin $display("ERROR at %1t: REF_PCOUT=%b REF_OLD_PCOUT=%b UUT_PCOUT=%b DIFF=%b", $time, REF_PCOUT, REF_OLD_PCOUT, PCOUT, REF_PCOUT ^ PCOUT); errcount = errcount + 1; ERROR_FLAG = 1; end if (REF_CARRYOUT !== CARRYOUT || (REF_OLD_CARRYOUT != CARRYOUT && !CARRYOUTREG)) begin $display("ERROR at %1t: REF_CARRYOUT=%b REF_OLD_CARRYOUT=%b UUT_CARRYOUT=%b DIFF=%b", $time, REF_CARRYOUT, REF_OLD_CARRYOUT, CARRYOUT, REF_CARRYOUT ^ CARRYOUT); errcount = errcount + 1; ERROR_FLAG = 1; end if (REF_CARRYOUTF !== CARRYOUTF) begin $display("ERROR at %1t: REF_CARRYOUTF=%b UUT_CARRYOUTF=%b", $time, REF_CARRYOUTF, CARRYOUTF); errcount = errcount + 1; ERROR_FLAG = 1; end #3; end endtask reg config_valid = 0; task drc; begin config_valid = 1; if (OPMODE[1:0] == 2'b10 && PREG != 1) config_valid = 0; if (OPMODE[3:2] == 2'b10 && PREG != 1) config_valid = 0; end endtask initial begin $dumpfile("test_dsp48a1_model.vcd"); $dumpvars(0, testbench); #2; CLK = 1'b0; {CEA, CEB, CEC, CED, CEM, CEP, CECARRYIN, CEOPMODE} = 8'b11111111; {A, B, C, D, PCIN, OPMODE, CARRYIN} = 0; {RSTA, RSTB, RSTC, RSTD, RSTM, RSTP, RSTCARRYIN, RSTOPMODE} = 8'b11111111; repeat (10) begin #10; CLK = 1'b1; #10; CLK = 1'b0; #10; CLK = 1'b1; #10; CLK = 1'b0; end {RSTA, RSTB, RSTC, RSTD, RSTM, RSTP, RSTCARRYIN, RSTOPMODE} = 0; repeat (10000) begin clkcycle; config_valid = 0; while (!config_valid) begin A = $urandom; B = $urandom; C = {$urandom, $urandom}; D = $urandom; PCIN = {$urandom, $urandom}; {CEA, CEB, CEC, CED, CEM, CEP, CECARRYIN, CEOPMODE} = $urandom | $urandom | $urandom; {RSTA, RSTB, RSTC, RSTD, RSTM, RSTP, RSTCARRYIN, RSTOPMODE} = $urandom & $urandom & $urandom & $urandom & $urandom & $urandom; {CARRYIN, OPMODE} = $urandom; drc; end end if (errcount == 0) begin $display("All tests passed."); $finish; end else begin $display("Caught %1d errors.", errcount); $stop; end end DSP48A #( .A0REG (A0REG), .A1REG (A1REG), .B0REG (B0REG), .B1REG (B1REG), .CREG (CREG), .DREG (DREG), .MREG (MREG), .PREG (PREG), .CARRYINREG (CARRYINREG), .OPMODEREG (OPMODEREG), .CARRYINSEL (CARRYINSEL), .RSTTYPE (RSTTYPE) ) ref_old ( .A (A), .B (B), .C (C), .D (D), .PCIN (PCIN), .CARRYIN (CARRYIN), .OPMODE (OPMODE), .BCOUT (REF_OLD_BCOUT), .CARRYOUT (REF_OLD_CARRYOUT), .P (REF_OLD_P), .PCOUT (REF_OLD_PCOUT), .CEA (CEA), .CEB (CEB), .CEC (CEC), .CED (CED), .CEM (CEM), .CEP (CEP), .CECARRYIN (CECARRYIN), .CEOPMODE (CEOPMODE), .CLK (CLK), .RSTA (RSTA), .RSTB (RSTB), .RSTC (RSTC), .RSTD (RSTD), .RSTM (RSTM), .RSTP (RSTP), .RSTCARRYIN (RSTCARRYIN), .RSTOPMODE (RSTOPMODE) ); DSP48A1 #( .A0REG (A0REG), .A1REG (A1REG), .B0REG (B0REG), .B1REG (B1REG), .CREG (CREG), .DREG (DREG), .MREG (MREG), .PREG (PREG), .CARRYINREG (CARRYINREG), .CARRYOUTREG (CARRYOUTREG), .OPMODEREG (OPMODEREG), .CARRYINSEL (CARRYINSEL), .RSTTYPE (RSTTYPE) ) ref ( .A (A), .B (B), .C (C), .D (D), .PCIN (PCIN), .CARRYIN (CARRYIN), .OPMODE (OPMODE), .BCOUT (REF_BCOUT), .CARRYOUTF (REF_CARRYOUTF), .CARRYOUT (REF_CARRYOUT), .P (REF_P), .M (REF_M), .PCOUT (REF_PCOUT), .CEA (CEA), .CEB (CEB), .CEC (CEC), .CED (CED), .CEM (CEM), .CEP (CEP), .CECARRYIN (CECARRYIN), .CEOPMODE (CEOPMODE), .CLK (CLK), .RSTA (RSTA), .RSTB (RSTB), .RSTC (RSTC), .RSTD (RSTD), .RSTM (RSTM), .RSTP (RSTP), .RSTCARRYIN (RSTCARRYIN), .RSTOPMODE (RSTOPMODE) ); DSP48A1_UUT #( .A0REG (A0REG), .A1REG (A1REG), .B0REG (B0REG), .B1REG (B1REG), .CREG (CREG), .DREG (DREG), .MREG (MREG), .PREG (PREG), .CARRYINREG (CARRYINREG), .CARRYOUTREG (CARRYOUTREG), .OPMODEREG (OPMODEREG), .CARRYINSEL (CARRYINSEL), .RSTTYPE (RSTTYPE) ) uut ( .A (A), .B (B), .C (C), .D (D), .PCIN (PCIN), .CARRYIN (CARRYIN), .OPMODE (OPMODE), .BCOUT (BCOUT), .CARRYOUTF (CARRYOUTF), .CARRYOUT (CARRYOUT), .P (P), .M (M), .PCOUT (PCOUT), .CEA (CEA), .CEB (CEB), .CEC (CEC), .CED (CED), .CEM (CEM), .CEP (CEP), .CECARRYIN (CECARRYIN), .CEOPMODE (CEOPMODE), .CLK (CLK), .RSTA (RSTA), .RSTB (RSTB), .RSTC (RSTC), .RSTD (RSTD), .RSTM (RSTM), .RSTP (RSTP), .RSTCARRYIN (RSTCARRYIN), .RSTOPMODE (RSTOPMODE) ); endmodule module mult_noreg; testbench #( .A0REG (0), .A1REG (0), .B0REG (0), .B1REG (0), .CREG (0), .DREG (0), .MREG (0), .PREG (0), .CARRYINREG (0), .CARRYOUTREG (0), .OPMODEREG (0), .CARRYINSEL ("CARRYIN"), .RSTTYPE ("SYNC") ) testbench (); endmodule module mult_allreg; testbench #( .A0REG (1), .A1REG (1), .B0REG (1), .B1REG (1), .CREG (1), .DREG (1), .MREG (1), .PREG (1), .CARRYINREG (1), .CARRYOUTREG (1), .OPMODEREG (1), .CARRYINSEL ("OPMODE5"), .RSTTYPE ("SYNC") ) testbench (); endmodule module mult_inreg; testbench #( .A0REG (1), .A1REG (1), .B0REG (1), .B1REG (1), .CREG (1), .DREG (1), .MREG (0), .PREG (0), .CARRYINREG (1), .CARRYOUTREG (0), .OPMODEREG (0), .CARRYINSEL ("CARRYIN"), .RSTTYPE ("SYNC") ) testbench (); endmodule