Skip to content

Commit d83b568

Browse files
committed
[chip, gpio, dv] Added W1's, W0's, T1's and T0's testing for GPIOs
The smoketest.c and top_chip_dv_gpio_base_vseq works in pairs in a way that C drives W1's and W0's pattern on the outputs and vseq drives T1's and T0's pattern on the inputs. Both C and vseq waits for an expected pattern to arrive in order to drive the next pattern. Signed-off-by: Kinza Qamar <kqzaman@lowrisc.org>
1 parent 4670d7a commit d83b568

File tree

2 files changed

+215
-2
lines changed

2 files changed

+215
-2
lines changed

hw/top_chip/dv/env/seq_lib/top_chip_dv_gpio_base_vseq.sv

Lines changed: 124 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,20 @@ class top_chip_dv_gpio_base_vseq extends top_chip_dv_base_vseq;
88
// Standard SV/UVM methods
99
extern function new(string name = "");
1010
extern task body();
11+
12+
// Class specific methods
13+
14+
// Drives a pattern on the GPIOs
15+
extern local virtual task drive_pattern(int unsigned num_clks, int unsigned pin, bit val);
16+
17+
// Waits for the paatern to appear on the GPIOs
18+
extern local virtual task wait_for_pattern(logic [NUM_GPIOS-1:0] exp_val);
19+
20+
// Checks the GPIOs in both input and output mode. A smoketest.c writes walking 0's and walking
21+
// 1's pattern on the lower and upper byte of direct_out register and gpio_test() should wait (for
22+
// a reasonable amount of timeout) for that pattern to appear on the pads to drive 1's and 0's in
23+
// temperature sequence fashion.
24+
extern virtual task gpio_test();
1125
endclass : top_chip_dv_gpio_base_vseq
1226

1327
function top_chip_dv_gpio_base_vseq::new (string name = "");
@@ -17,5 +31,114 @@ endfunction : new
1731
task top_chip_dv_gpio_base_vseq::body();
1832
super.body();
1933
`DV_WAIT(cfg.sw_test_status_vif.sw_test_status == SwTestStatusInTest);
20-
// TODO
34+
gpio_test();
2135
endtask : body
36+
37+
task top_chip_dv_gpio_base_vseq::drive_pattern(int unsigned num_clks, int unsigned pin, bit val);
38+
cfg.peri_clk_vif.wait_clks(num_clks);
39+
cfg.gpio_vif.drive_pin(pin, val);
40+
endtask : drive_pattern
41+
42+
task top_chip_dv_gpio_base_vseq::wait_for_pattern(logic [NUM_GPIOS-1:0] exp_val);
43+
`DV_SPINWAIT(wait(cfg.gpio_vif.pins ==? exp_val);,
44+
$sformatf("Timed out waiting for GPIOs == %0h", exp_val),
45+
/*use default_spinwait_timeout_ns*/,
46+
`gfn)
47+
endtask : wait_for_pattern
48+
49+
task top_chip_dv_gpio_base_vseq::gpio_test();
50+
// Enable the pulldown so that the pads are driving 0's than Z's when no external driver is
51+
// connected
52+
cfg.gpio_vif.set_pulldown_en('1);
53+
54+
// GPIO pads : 'h0
55+
//
56+
// Disable GPIOs from being driven as chip inputs.
57+
cfg.gpio_vif.drive_en({(NUM_GPIOS/4){1'b0}});
58+
59+
`uvm_info(`gfn, "Starting GPIOs outputs test", UVM_LOW)
60+
61+
// The C code first sets the GPIOs to '0s in order to walk 1 on first 8 pins of upper and lower
62+
// halves.
63+
//
64+
// Wait and check for all 0s.
65+
wait_for_pattern({NUM_GPIOS{1'b0}});
66+
67+
// Check for walking 1's pattern on lower 8 pins.
68+
for (int i = 0; i < NUM_GPIOS/4; i++) begin
69+
wait_for_pattern({24'h?, 1 << i});
70+
end
71+
72+
// GPIO pads : 'h00000080
73+
//
74+
// Drive 1's in temperature pattern on the lower 8 pins.
75+
for (int i = NUM_GPIOS/4; i < (NUM_GPIOS/4) * 2; i++) begin
76+
drive_pattern(1, i, 1);
77+
end
78+
79+
// GPIO pads : 'h0000FF80
80+
//
81+
// Check for walking 1's pattern on the first 8 pins upper half.
82+
for (int i = 0; i < NUM_GPIOS/4; i++) begin
83+
wait_for_pattern({8'h?, 1 << i, 16'h????});
84+
end
85+
86+
// GPIO pads : 'h0080FF80
87+
//
88+
// Drive 1's in temperature pattern on the second half of 8 pins of upper half.
89+
for (int i = (NUM_GPIOS/4) * 3; i < NUM_GPIOS; i++) begin
90+
drive_pattern(1, i, 1);
91+
end
92+
93+
// GPIO pads : 'hFF80FF80
94+
//
95+
// The C code first sets the first 8 pins of both upper and lower halves to 1's in order to walk
96+
// 0's.
97+
//
98+
// Wait and check for all 1s.
99+
wait_for_pattern({NUM_GPIOS{1'b1}});
100+
101+
// GPIO pads : 'hFFFFFFFF
102+
//
103+
// Check for walking 0's pattern on first 8 pins of lower half.
104+
for (int i = 0; i < NUM_GPIOS/4; i++) begin
105+
wait_for_pattern({24'h?, ~(1 << i)});
106+
// logic [(NUM_GPIOS/4)-1:0] exp_gpios = ~(1 << i);
107+
// $display("waiting for %0h at %0t", exp_gpios, $realtime);
108+
// `DV_SPINWAIT(wait(cfg.gpio_vif.pins ==? {8'h??, 8'h??, 8'h??, exp_gpios});,
109+
// $sformatf("Timed out waiting for GPIOs == %0h", exp_gpios),
110+
// /*use default_spinwait_timeout_ns*/,
111+
// `gfn)
112+
end
113+
114+
// GPIO pads : 'hFFFFFF7F
115+
//
116+
// Drive 0's in temperature pattern on the upper 8 pins of the lower half.
117+
for (int i = NUM_GPIOS/4; i < (NUM_GPIOS/4) * 2; i++) begin
118+
drive_pattern(1, i, 0);
119+
// cfg.peri_clk_vif.wait_clks(1);
120+
// cfg.gpio_vif.drive_pin(i, 0);
121+
end
122+
123+
// GPIO pads : 'hFFFF007F
124+
//
125+
// Check for walking 0's pattern on lower 8 pins of the upper half.
126+
for (int i = 0; i < NUM_GPIOS/4; i++) begin
127+
wait_for_pattern({8'h?, ~(1 << i), 16'h?});
128+
// logic [(NUM_GPIOS/4)-1:0] exp_gpios = ~(1 << i);
129+
// $display("waiting for %0h at %0t", exp_gpios, $realtime);
130+
// `DV_SPINWAIT(wait(cfg.gpio_vif.pins ==? {8'h??, exp_gpios, 8'h??, 8'h??});,
131+
// $sformatf("Timed out waiting for GPIOs == %0h", exp_gpios),
132+
// /*use default_spinwait_timeout_ns*/,
133+
// `gfn)
134+
end
135+
136+
// GPIO pads : 'hFF00007F
137+
//
138+
// Drive 0's in temperature pattern on the upper 8 pins of the upper half.
139+
for (int i = (NUM_GPIOS/4) * 3; i < NUM_GPIOS; i++) begin
140+
drive_pattern(1, i, 0);
141+
end
142+
143+
// GPIO pads : 'h7F00007F
144+
endtask : gpio_test

sw/device/tests/gpio/smoketest.c

Lines changed: 91 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,98 @@ static bool reg_test(gpio_t gpio)
4949
return true;
5050
}
5151

52+
// Drive a pattern (val)
53+
static void drive(gpio_t gpio, uint32_t masked_reg, uint32_t val) {
54+
DEV_WRITE(gpio + masked_reg, 0XFFFF0000 | val);
55+
}
56+
57+
// Wait for an expected pattern (compare_val).
58+
static void wait(gpio_t gpio, uint32_t compare_val) {
59+
while(DEV_READ(gpio + GPIO_REG_DATA_IN) != compare_val){
60+
}
61+
}
62+
63+
// Verifies GPIOs in partially output and input direction.
64+
//
65+
// 1- First, drive 0's on the top 8 pins of lower and upper halves of GPIOs.
66+
// 2- Walk 1's on the first eight pins in output mode.
67+
// 3- top_chip_dv_gpio_base_vseq will wait for that pattern to appear on the pads. Once it sees that
68+
// pattern, it will drive 1's in temperature sequence on to the next eight pins.
69+
// 4- gpio_test waits for the pattern 0x0000T1W1 on the GPIO pads by reading DATA_IN register. Then
70+
// will walk 1's on the next 8 pins and waits for pattern 0xT1W1T1W1.
71+
// 5- On the other side, the vseq waits for the W1's pattern on the first 8 pins on the upper half
72+
// and drive 1's in temperature sequence on the next 8 pins.
73+
// 6- After all that, gpio_test start to write 1's to all the pads in order to drive 0's. Everything
74+
// beyond that is similar but the expected driven sequence is going to be temperature 0's and
75+
// walking 0's.
76+
static bool gpio_test(gpio_t gpio)
77+
{
78+
// Enable the top 8 pins of lower and upper halves in output mode
79+
gpio_set_all_oe(gpio, 0x00FF00FF);
80+
81+
// Set the gpios to all 0s in order to walk 1 on first bytes of both lower and upper halves.
82+
gpio_write_direct_out(gpio, 0x0);
83+
84+
// GPIO pads value : 0x00000000
85+
//
86+
// Walk 1's on lower first byte. gpio_test drives first byte in a walking 1 fashion and
87+
// vseq drives the 2nd byte as temperature 1's. Hence, the expected value to wait for is 0xFF80,
88+
for (int i = 0; i < GPIO_NUM_PINS/4; i++) {
89+
drive(gpio, GPIO_REG_MASKED_OUT_LOWER, 1 << i);
90+
if (i == ((GPIO_NUM_PINS/4)-1)) {
91+
wait(gpio, 0xFF80);
92+
}
93+
}
94+
95+
// GPIO pads value : 0x0000FF80
96+
//
97+
// Walk 1's on upper first byte. gpio_test drives upper first byte in a walking 1 fashion
98+
// and vseq drives the 2nd byte as temperature 1's. Additionally the pads should contain 0xFF80
99+
// on lower 16 pins. Hence, the expected value to wait for is 0xFF80FF80,
100+
for (int i = 0; i < GPIO_NUM_PINS/4; i++) {
101+
drive(gpio, GPIO_REG_MASKED_OUT_UPPER, 1 << i);
102+
if (i == ((GPIO_NUM_PINS/4)-1)) {
103+
wait(gpio, 0xFF80FF80);
104+
}
105+
}
106+
107+
// GPIO pads value : 0xFF80FF80
108+
//
109+
// Set the outputs to all 1's in order to walk 0's on first bytes of both lower and upper halves
110+
// pins.
111+
gpio_write_direct_out(gpio, 0x00FF00FF);
112+
113+
// GPIO pads value : 0xFFFFFFFF
114+
//
115+
// Walk 0's on lower first byte. gpio_test drives lower first byte in a walking 0 fashion and
116+
// vseq drives the second byte as temperature 0's. Hence, the expected value to wait for is
117+
// 0xFFFF007F.
118+
for (int i = 0; i < GPIO_NUM_PINS/4; i++) {
119+
drive(gpio, GPIO_REG_MASKED_OUT_LOWER, ~(1 << i));
120+
if (i == ((GPIO_NUM_PINS/4)-1)) {
121+
wait(gpio, 0xFFFF007F);
122+
}
123+
}
124+
125+
// GPIO pads value : 0xFFFF007F
126+
//
127+
// Walk 0's on the upper first byte. gpio_test drives upper first byte in a walking 0 fashion
128+
// and vseq drives the second byte as temperature 0's. Hence, the expected value to wait for is
129+
// 0x007F007F.
130+
for (int i = 0; i < GPIO_NUM_PINS/4; i++) {
131+
drive(gpio, GPIO_REG_MASKED_OUT_UPPER, ~(1 << i));
132+
if (i == ((GPIO_NUM_PINS/4)-1)) {
133+
wait(gpio, 0x007F007F);
134+
}
135+
}
136+
137+
// GPIO pads value : 0x007F007F
138+
139+
return true;
140+
}
141+
52142
bool test_main()
53143
{
54144
gpio_t gpio = mocha_system_gpio();
55-
return reg_test(gpio);
145+
return gpio_test(gpio);
56146
}

0 commit comments

Comments
 (0)