write test circuit
This commit is contained in:
parent
f84a62b19f
commit
e35f8f0939
5 changed files with 2774 additions and 0 deletions
136
test-circuit/minichannel.act
Normal file
136
test-circuit/minichannel.act
Normal file
|
|
@ -0,0 +1,136 @@
|
||||||
|
|
||||||
|
import std::data;
|
||||||
|
|
||||||
|
function ceil_log2 (pint a) : pint
|
||||||
|
{
|
||||||
|
pint i;
|
||||||
|
pint M;
|
||||||
|
chp {
|
||||||
|
i := 0;
|
||||||
|
M := a-1;
|
||||||
|
*[ M > 0 -> i := i + 1; M := M/2 ];
|
||||||
|
self := i
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template<pbool reset; pint V; pint N>
|
||||||
|
defchan gen_a1of <: chan(enum<N>) (std::data::d1of?!<N> d; bool!? a)
|
||||||
|
{
|
||||||
|
{ 0 <= V & V < N : "Initial token value out of range" };
|
||||||
|
|
||||||
|
|
||||||
|
methods {
|
||||||
|
/*-- initialize channel, sender end --*/
|
||||||
|
send_init {
|
||||||
|
[ reset -> (,i:N: [ i != V -> d.d[i]- [] else -> d.d[i]+ ])
|
||||||
|
[] else -> (,i:N: d.d[i]-)
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-- set output data --*/
|
||||||
|
set {
|
||||||
|
[([]i:N: self = i -> d.d[i]+)]
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-- finish synchronization --*/
|
||||||
|
send_up {
|
||||||
|
[a]
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-- reset part of the protocol --*/
|
||||||
|
send_rest {
|
||||||
|
(,i:N:d.d[i]-);[~a]
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-- initialize channel, receiver end --*/
|
||||||
|
recv_init {
|
||||||
|
a-
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-- get value --*/
|
||||||
|
get {
|
||||||
|
[([]i:N:d.d[i] -> self := i)]
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-- finish synchronization action --*/
|
||||||
|
recv_up {
|
||||||
|
a+
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-- reset part of the protocol --*/
|
||||||
|
recv_rest {
|
||||||
|
[(&i:N:~d.d[i])];a-
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-- probe expression on receiver --*/
|
||||||
|
recv_probe = (|i:N:d.d[i]);
|
||||||
|
|
||||||
|
// no sender probe
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export defchan a1of <: gen_a1of<false,0> () { }
|
||||||
|
export defchan ar1of <: gen_a1of<true,0> () { }
|
||||||
|
|
||||||
|
|
||||||
|
template<pbool reset; pint V; pint M>
|
||||||
|
defchan gen_aMx1of2 <: chan(int<M>) (std::data::Mx1of2?!<M> d; bool!? a)
|
||||||
|
{
|
||||||
|
{ 0 <= V & ceil_log2(V) < M : "Initial token value out of range" };
|
||||||
|
|
||||||
|
methods {
|
||||||
|
/*-- initialize channel, sender end --*/
|
||||||
|
send_init {
|
||||||
|
[ reset -> (,i:M: [ ((V >> i) & 1) = 0 -> d.d[i].f+ [] else -> d.d[i].t+ ])
|
||||||
|
[] else -> (,i:M: d.d[i].t-,d.d[i].f-)
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-- set output data --*/
|
||||||
|
set {
|
||||||
|
(,i:M: [((self >> i) & 1) = 0 -> d.d[i].f+ [] else -> d.d[i].t+ ])
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-- finish synchronization --*/
|
||||||
|
send_up {
|
||||||
|
[a]
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-- reset part of the protocol --*/
|
||||||
|
send_rest {
|
||||||
|
(,i:M: d.d[i].t-,d.d[i].f-);[~a]
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-- initialize channel, receiver end --*/
|
||||||
|
recv_init {
|
||||||
|
a-
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-- get value --*/
|
||||||
|
get {
|
||||||
|
[(&i:M: d.d[i].t | d.d[i].f)];
|
||||||
|
self := 0;
|
||||||
|
(;i:M: [ d.d[i].t -> self := self | (1 << i)
|
||||||
|
[] else -> skip
|
||||||
|
]
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-- finish synchronization action --*/
|
||||||
|
recv_up {
|
||||||
|
a+
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-- reset part of the protocol --*/
|
||||||
|
recv_rest {
|
||||||
|
[(&i:M:~d.d[i].t & ~d.d[i].f)];a-
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-- probe expression on receiver --*/
|
||||||
|
recv_probe = (d.d[0].t|d.d[0].f);
|
||||||
|
|
||||||
|
// no sender probe
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export defchan aMx1of2 <: gen_aMx1of2<false,0> () { }
|
||||||
|
export defchan arMx1of2 <: gen_aMx1of2<true,0> () { }
|
||||||
19
test-circuit/mult_wrapper.act
Normal file
19
test-circuit/mult_wrapper.act
Normal file
|
|
@ -0,0 +1,19 @@
|
||||||
|
|
||||||
|
import "umul4x4.act";
|
||||||
|
import std::data;
|
||||||
|
import "minichannel.act";
|
||||||
|
|
||||||
|
defproc pipelined_mult(aMx1of2?<4> A, B; aMx1of2!<8> RES; bool? reset) {
|
||||||
|
|
||||||
|
pint IN_WIDTH = 4;
|
||||||
|
pint OUT_WIDTH = 8;
|
||||||
|
|
||||||
|
umul4x4 mult;
|
||||||
|
mult.a = A.d;
|
||||||
|
mult.ack_out = A.a;
|
||||||
|
mult.b = B.d;
|
||||||
|
mult.ack_out = B.a;
|
||||||
|
RES.d = mult.s;
|
||||||
|
RES.a = mult.ack_in;
|
||||||
|
mult.reset = reset;
|
||||||
|
}
|
||||||
91
test-circuit/simlib.act
Normal file
91
test-circuit/simlib.act
Normal file
|
|
@ -0,0 +1,91 @@
|
||||||
|
|
||||||
|
template<pbool INCLUDE_ENABLE; pint D_WIDTH, OUT_CHANNELS, N; pint DATA[N]; pbool LOOP; pint SOURCE_ID; pbool LOG>
|
||||||
|
defproc source_sequence_multi (chan!(int<D_WIDTH>) O[OUT_CHANNELS]; bool? enable)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
int<D_WIDTH> buf;
|
||||||
|
|
||||||
|
chp {
|
||||||
|
// and send it to every channel
|
||||||
|
(, j : OUT_CHANNELS :
|
||||||
|
*[
|
||||||
|
i := 0;
|
||||||
|
|
||||||
|
*[ i < N ->
|
||||||
|
|
||||||
|
// select the right data element
|
||||||
|
[([]k:N: i=k -> buf := DATA[k])];
|
||||||
|
|
||||||
|
// wait on enable flag
|
||||||
|
[~INCLUDE_ENABLE|enable];
|
||||||
|
|
||||||
|
O[j]!buf;
|
||||||
|
|
||||||
|
// if logging was enabled, log the send
|
||||||
|
[ LOG ->
|
||||||
|
log ("Source ", SOURCE_ID, " (Channel ", j, "): Sent value ", buf, "%x (0x", buf, ")")
|
||||||
|
[] else ->
|
||||||
|
skip
|
||||||
|
];
|
||||||
|
|
||||||
|
i := i + 1
|
||||||
|
]
|
||||||
|
<- LOOP ]
|
||||||
|
);
|
||||||
|
|
||||||
|
log ("Source ", SOURCE_ID, ": Sequence ended.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <pint IN_D_WIDTH, OUT_D_WIDTH, IN_CHANNELS, OUT_CHANNELS, SB_ID; pbool VERBOSE_TESTING>
|
||||||
|
defproc lockstep (chan?(int<IN_D_WIDTH>) IN[IN_CHANNELS]; chan?(int<OUT_D_WIDTH>) OUT_M[OUT_CHANNELS], OUT_D[OUT_CHANNELS])
|
||||||
|
{
|
||||||
|
int<IN_D_WIDTH> input[IN_CHANNELS];
|
||||||
|
int<OUT_D_WIDTH> output_m[OUT_CHANNELS], output_d[OUT_CHANNELS];
|
||||||
|
bool not_failed;
|
||||||
|
int num;
|
||||||
|
|
||||||
|
chp {
|
||||||
|
|
||||||
|
num := 0;
|
||||||
|
|
||||||
|
*[
|
||||||
|
// receive the data
|
||||||
|
(, i : IN_CHANNELS : IN[i]?input[i]),
|
||||||
|
(, i : OUT_CHANNELS : OUT_M[i]?output_m[i]),
|
||||||
|
(, j : OUT_CHANNELS : OUT_D[j]?output_d[j]);
|
||||||
|
|
||||||
|
// check the results
|
||||||
|
not_failed+;
|
||||||
|
(; i : OUT_CHANNELS : [not_failed -> not_failed := output_m[i] = output_d[i] [] else -> skip]);
|
||||||
|
|
||||||
|
// print the output
|
||||||
|
[ not_failed -> (
|
||||||
|
// only print successful tests if verbose testing is enabled
|
||||||
|
[ VERBOSE_TESTING -> (
|
||||||
|
log_st ("");
|
||||||
|
log_p ("Scoreboard ", SB_ID, ": TEST SUCCESS (", num, "); inputs {");
|
||||||
|
(; i : IN_CHANNELS : log_p (i, ": ", input[i], "%x (0x", input[i], "); "));
|
||||||
|
log_p ("}, outputs {");
|
||||||
|
(; i : OUT_CHANNELS : log_p (i, ": ", output_d[i], "%x (0x", output_d[i], "); "));
|
||||||
|
log_p ("}");
|
||||||
|
log_nl ("")
|
||||||
|
)
|
||||||
|
[] else -> (
|
||||||
|
skip
|
||||||
|
)]
|
||||||
|
)
|
||||||
|
[] else -> (
|
||||||
|
log_st ("");
|
||||||
|
log_p ("Scoreboard ", SB_ID, ": TEST FAILED (", num, "); inputs {");
|
||||||
|
(; i : IN_CHANNELS : log_p (i, ": ", input[i], "%x (0x", input[i], "); "));
|
||||||
|
log_p ("}, outputs {");
|
||||||
|
(; i : OUT_CHANNELS : log_p (i, ": expected ", output_m[i], "%x (0x", output_m[i], "), got ", output_d[i], "%x (0x", output_d[i], "); "));
|
||||||
|
log_p ("}");
|
||||||
|
log_nl ("")
|
||||||
|
)];
|
||||||
|
num := num + 1
|
||||||
|
]
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
61
test-circuit/testbench.act
Normal file
61
test-circuit/testbench.act
Normal file
|
|
@ -0,0 +1,61 @@
|
||||||
|
|
||||||
|
import "simlib.act";
|
||||||
|
import "mult_wrapper.act";
|
||||||
|
|
||||||
|
template<pint IN_WIDTH, OUT_WIDTH>
|
||||||
|
defproc mul_model (chan(int<IN_WIDTH>)? A,B; chan(int<OUT_WIDTH>)! RES; bool res) {
|
||||||
|
int<IN_WIDTH> a, b;
|
||||||
|
int<OUT_WIDTH>res;
|
||||||
|
|
||||||
|
chp {
|
||||||
|
*[
|
||||||
|
[#A];
|
||||||
|
B?b, A?a;
|
||||||
|
RES!(a*b)
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
defproc tb() {
|
||||||
|
|
||||||
|
pint IN_WIDTH = 4;
|
||||||
|
pint OUT_WIDTH = 8;
|
||||||
|
|
||||||
|
pint IN_SEQ_L = 8;
|
||||||
|
pint in_seq_a[IN_SEQ_L];
|
||||||
|
pint in_seq_b[IN_SEQ_L];
|
||||||
|
in_seq_a = {7, 6, 5, 1, 2, 3, 0, 4};
|
||||||
|
in_seq_b = {4, 0, 3, 2, 1, 5, 6, 7};
|
||||||
|
|
||||||
|
// model and DUT
|
||||||
|
mul_model<IN_WIDTH, OUT_WIDTH> model;
|
||||||
|
pipelined_mult dut;
|
||||||
|
|
||||||
|
// simulation harness
|
||||||
|
lockstep<IN_WIDTH, OUT_WIDTH, 2, 1, 1, true> sb;
|
||||||
|
source_sequence_multi<true, IN_D_WIDTH, 3, IN_SEQ_L, in_seq_a, true, 1, true> a_src;
|
||||||
|
source_sequence_multi<true, IN_D_WIDTH, 3, IN_SEQ_L, in_seq_b, true, 2, true> b_src;
|
||||||
|
|
||||||
|
// model inputs
|
||||||
|
model.A = a_src.O[0];
|
||||||
|
model.B = b_src.O[0];
|
||||||
|
|
||||||
|
// DUT inputs
|
||||||
|
dut.A = a_src.O[1];
|
||||||
|
dut.b = b_src.O[1];
|
||||||
|
|
||||||
|
// scoreboard inputs
|
||||||
|
sb.IN[0] = a_src[2];
|
||||||
|
sb.IN[1] = b_src[2];
|
||||||
|
sb.OUT_M[0] = model.RES;
|
||||||
|
sb.OUT_D[0] = dut.RES;
|
||||||
|
|
||||||
|
chp {
|
||||||
|
a_src.enable-, b_src.enable-;
|
||||||
|
dut.reset+;
|
||||||
|
[after=1000];
|
||||||
|
dut.reset-;
|
||||||
|
|
||||||
|
a_src.enable+, b_src.enable+
|
||||||
|
}
|
||||||
|
}
|
||||||
2467
test-circuit/umul4x4.act
Normal file
2467
test-circuit/umul4x4.act
Normal file
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue